diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analysis/db/admin.c | 209 | ||||
-rw-r--r-- | src/analysis/db/admin.h | 6 | ||||
-rw-r--r-- | src/analysis/db/controller.c | 122 | ||||
-rw-r--r-- | src/analysis/db/protocol.h | 20 |
4 files changed, 306 insertions, 51 deletions
diff --git a/src/analysis/db/admin.c b/src/analysis/db/admin.c index 355f8c0..771a912 100644 --- a/src/analysis/db/admin.c +++ b/src/analysis/db/admin.c @@ -25,10 +25,13 @@ #include <assert.h> +#include <malloc.h> #include <poll.h> +#include <string.h> #include "client-int.h" +#include "../../common/leb128.h" #include "../../core/logs.h" @@ -38,6 +41,10 @@ struct _GAdminClient { GHubClient parent; /* A laisser en premier */ + char **binaries; /* Liste de binaires existants*/ + size_t binaries_count; /* Taille de cette liste */ + GMutex binaries_lock; /* Concurrence des accès */ + }; /* Description de client à l'écoute (classe) */ @@ -45,6 +52,10 @@ struct _GAdminClientClass { GHubClientClass parent; /* A laisser en premier */ + /* Signaux */ + + void (* existing_binaries_updated) (GAdminClient *); + }; @@ -63,6 +74,9 @@ static void g_admin_client_finalize(GAdminClient *); /* Assure l'accueil des nouvelles mises à jour. */ static void *g_admin_client_update(GAdminClient *); +/* Met à jour la liste des binaires existants. */ +static bool g_admin_client_update_existing_binaries(GAdminClient *, packed_buffer *); + /* Indique le type défini pour une description de client à l'écoute. */ @@ -96,6 +110,14 @@ static void g_admin_client_class_init(GAdminClientClass *klass) client->role = CRL_ADMIN; client->recv_func = (GThreadFunc)g_admin_client_update; + g_signal_new("existing-binaries-updated", + G_TYPE_ADMIN_CLIENT, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GAdminClientClass, existing_binaries_updated), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + } @@ -113,6 +135,9 @@ static void g_admin_client_class_init(GAdminClientClass *klass) static void g_admin_client_init(GAdminClient *client) { + client->binaries = NULL; + client->binaries_count = 0; + g_mutex_init(&client->binaries_lock); } @@ -152,6 +177,19 @@ static void g_admin_client_dispose(GAdminClient *client) static void g_admin_client_finalize(GAdminClient *client) { + size_t i; /* Boucle de parcours */ + + if (client->binaries != NULL) + { + for (i = 0; i < client->binaries_count; i++) + free(client->binaries[i]); + + free(client->binaries); + + } + + g_mutex_clear(&client->binaries_lock); + G_OBJECT_CLASS(g_admin_client_parent_class)->finalize(G_OBJECT(client)); } @@ -256,6 +294,11 @@ static void *g_admin_client_update(GAdminClient *client) switch (command) { + case DBC_EXISTING_BINARIES: + status = g_admin_client_update_existing_binaries(client, &in_pbuf); + if (!status) goto bad_exchange; + break; + default: log_variadic_message(LMT_INFO, _("This command is not available on this side: 0x%08x"), command); @@ -290,3 +333,169 @@ static void *g_admin_client_update(GAdminClient *client) return NULL; } + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* * +* Description : Effectue une demande de liste de binaires existants. * +* * +* Retour : true si la commande a bien été envoyée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_admin_client_request_existing_binaries(GAdminClient *client) +{ + bool result; /* Bilan partiel à remonter */ + packed_buffer out_pbuf; /* Tampon d'émission */ + SSL *tls_fd; /* Canal de communication SSL */ + + init_packed_buffer(&out_pbuf); + + tls_fd = g_hub_client_get_ssl_fd(G_HUB_CLIENT(client)); + + if (tls_fd == NULL) + result = false; + + else + { + result = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_LIST_BINARIES }, sizeof(uint32_t), true); + + if (result) + result = ssl_send_packed_buffer(&out_pbuf, tls_fd); + + g_hub_client_put_ssl_fd(G_HUB_CLIENT(client), tls_fd); + + } + + exit_packed_buffer(&out_pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* pbuf = données présentes à traiter. * +* * +* Description : Met à jour la liste des binaires existants. * +* * +* Retour : true si l'opération s'est déroulée sans encombre, ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_admin_client_update_existing_binaries(GAdminClient *client, packed_buffer *pbuf) +{ + bool result; /* Validité à retourner */ + size_t i; /* Boucle de parcours */ + uleb128_t count; /* Nombre d'éléments détectés */ + rle_string name; /* Nom à exporter */ + + result = true; + + g_mutex_lock(&client->binaries_lock); + + if (client->binaries != NULL) + { + for (i = 0; i < client->binaries_count; i++) + free(client->binaries[i]); + + free(client->binaries); + + client->binaries = NULL; + client->binaries_count = 0; + + } + + result = unpack_uleb128(&count, pbuf); + if (!result) goto exit; + + client->binaries_count = count; + + if (count > 0) + { + client->binaries = calloc(client->binaries_count, sizeof(char *)); + + for (i = 0; i < client->binaries_count; i++) + { + result = unpack_rle_string(&name, pbuf); + if (!result) break; + + client->binaries[i] = strdup(name.data); + + exit_rle_string(&name); + + } + + if (i < client->binaries_count) + { + for (i = 0; i < client->binaries_count; i++) + if (client->binaries[i] != NULL) + free(client->binaries[i]); + + free(client->binaries); + + client->binaries = NULL; + client->binaries_count = 0; + + } + + } + + exit: + + g_mutex_unlock(&client->binaries_lock); + + if (result) + g_signal_emit_by_name(client, "existing-binaries-updated"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* count = taille de la liste retournée. [OUT] * +* * +* Description : Fournit la liste des instantanés existants. * +* * +* Retour : Liste de binaires en place ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char **g_admin_client_get_existing_binaries(GAdminClient *client, size_t *count) +{ + char **result; /* Liste à retourner */ + size_t i; /* Boucle de parcours */ + + result = NULL; + *count = 0; + + g_mutex_lock(&client->binaries_lock); + + if (client->binaries_count > 0) + { + result = malloc(client->binaries_count * sizeof(char *)); + *count = client->binaries_count; + + for (i = 0; i < client->binaries_count; i++) + result[i] = strdup(client->binaries[i]); + + } + + g_mutex_unlock(&client->binaries_lock); + + return result; + +} diff --git a/src/analysis/db/admin.h b/src/analysis/db/admin.h index f5a6b5d..31366ae 100644 --- a/src/analysis/db/admin.h +++ b/src/analysis/db/admin.h @@ -57,6 +57,12 @@ GType g_admin_client_get_type(void); /* Prépare un client pour une connexion à une BD. */ GAdminClient *g_admin_client_new(void); +/* Effectue une demande de liste de binaires existants. */ +bool g_admin_client_request_existing_binaries(GAdminClient *); + +/* Fournit la liste des instantanés existants. */ +char **g_admin_client_get_existing_binaries(GAdminClient *, size_t *); + #endif /* _ANALYSIS_DB_ADMIN_H */ diff --git a/src/analysis/db/controller.c b/src/analysis/db/controller.c index 46b628d..a27c20a 100644 --- a/src/analysis/db/controller.c +++ b/src/analysis/db/controller.c @@ -26,6 +26,7 @@ #include <assert.h> #include <errno.h> +#include <dirent.h> #include <malloc.h> #include <poll.h> #include <pthread.h> @@ -36,6 +37,8 @@ #include "backend-int.h" +#include "misc/rlestr.h" +#include "../../common/leb128.h" #include "../../common/packed.h" #include "../../core/logs.h" @@ -80,6 +83,9 @@ static void *g_cdb_controller_process(GCdbController *); /* Prend en compte une connexion nouvelle d'un utilisateur. */ static void g_cdb_controller_add_client(GCdbController *, SSL *, const char *, const char *); +/* Envoie au client la liste des binaires présents. */ +static bool g_cdb_controller_send_existing_binaries(GCdbController *, packed_buffer_t *); + /* Indique le type défini pour une gestion d'archives. */ @@ -238,12 +244,10 @@ static void *g_cdb_controller_process(GCdbController *controller) GServerBackend *base; /* Base de l'instance */ struct pollfd fds[3]; /* Surveillance des flux */ int ret; /* Bilan d'un appel */ - packed_buffer in_pbuf; /* Tampon de réception */ - uint32_t tmp32; /* Valeur sur 32 bits */ + packed_buffer_t in_pbuf; /* Tampon de réception */ bool status; /* Bilan de lecture initiale */ uint32_t command; /* Commande de la requête */ - DBError error; /* Bilan d'une opération */ - packed_buffer out_pbuf; /* Tampon d'émission */ + packed_buffer_t out_pbuf; /* Tampon d'émission */ char *msg; /* Erreur à faire remonter */ base = G_SERVER_BACKEND(controller); @@ -305,27 +309,23 @@ static void *g_cdb_controller_process(GCdbController *controller) switch (command) { - case DBC_LIST_ARCHIVES: - - /* - error = g_cdb_controller_write(archive); + case DBC_LIST_BINARIES: - init_packed_buffer(&out_pbuf); + init_packed_buffer(&out_pbuf); - status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SAVE }, - sizeof(uint32_t), true); - if (!status) goto reply_error; + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_EXISTING_BINARIES }, + sizeof(uint32_t), true); + if (!status) goto reply_error; - status = extend_packed_buffer(&out_pbuf, (uint32_t []) { error }, sizeof(uint32_t), true); - if (!status) goto reply_error; + status = g_cdb_controller_send_existing_binaries(controller, &out_pbuf); + if (!status) goto reply_error; - status = ssl_send_packed_buffer(&out_pbuf, controller->tls_fd); - if (!status) goto reply_error; - */ + status = ssl_send_packed_buffer(&out_pbuf, controller->tls_fd); + if (!status) goto reply_error; - exit_packed_buffer(&out_pbuf); + exit_packed_buffer(&out_pbuf); - break; + break; default: asprintf(&msg, _("Bad protocol command: 0x%08x"), command); @@ -397,16 +397,12 @@ static void g_cdb_controller_add_client(GCdbController *controller, SSL *fd, con } - - - -#if 0 /****************************************************************************** * * -* Paramètres : controller = archive à connecter avec un utilisateur. * -* pbuf = paquet à consituer pour un envoi unique. [OUT] * +* Paramètres : controller = administration d'archives d'analyse. * +* pbuf = paquet à consituer pour un envoi unique. [OUT] * * * -* Description : Envoie à tous les clients la nouvelle liste d'instantanés. * +* Description : Envoie au client la liste des binaires présents. * * * * Retour : Bilan de constitution de la réponse. * * * @@ -414,36 +410,72 @@ static void g_cdb_controller_add_client(GCdbController *controller, SSL *fd, con * * ******************************************************************************/ -static bool g_cdb_controller_send_snapshot_update(GCdbController *controller, packed_buffer *pbuf) +static bool g_cdb_controller_send_existing_binaries(GCdbController *controller, packed_buffer_t *pbuf) { bool result; /* Bilan à retourner */ - bool do_send; /* Réalisation de l'émission */ - packed_buffer out_pbuf; /* Tampon d'émission */ + DIR *directory; /* Répertoire de travail */ + uleb128_t count; /* Nombre d'éléments détectés */ + packed_buffer_t items; /* Liste des éléments trouvés */ + struct dirent *item; /* Propriétés d'un élément */ + rle_string name; /* Nom à exporter */ + bool status; /* Bilan d'une inscription */ + int ret; /* Bilan de fermture */ + + result = false; + + directory = opendir(controller->basedir); + if (directory == NULL) + { + LOG_ERROR_N("opendir"); - do_send = (pbuf == NULL); + if (errno == ENOENT) + { + count = 0; + result = pack_uleb128(&count, pbuf); + } - if (pbuf == NULL) - pbuf = &out_pbuf; + goto bad_dir; - init_packed_buffer(pbuf); + } - result = extend_packed_buffer(pbuf, (uint32_t []) { DBC_SNAPSHOTS_UPDATED }, - sizeof(uint32_t), true); - if (!result) goto bad_reply; + count = 0; + init_packed_buffer(&items); - result = g_db_snapshot_pack_all(archive->snapshot, pbuf); - if (!result) goto bad_reply; + for (item = readdir(directory); item != NULL; item = readdir(directory)) + { + if (item->d_type != DT_DIR) + continue; - result = extend_packed_buffer(pbuf, SNAPSHOT_END_MARK, SNAP_ID_HEX_SZ, false); - if (!result) goto bad_reply; + if (strcmp(item->d_name, ".") == 0 || strcmp(item->d_name, "..") == 0) + continue; - bad_reply: + init_static_rle_string(&name, item->d_name); - if (do_send || !result) - exit_packed_buffer(pbuf); + status = pack_rle_string(&name, &items); + + exit_rle_string(&name); + + if (!status) + goto reg_error; + + count++; + + } + + result = pack_uleb128(&count, pbuf); + + if (result) + result = include_packed_buffer(pbuf, &items); + + reg_error: + + exit_packed_buffer(&items); + + ret = closedir(directory); + if (ret == -1) LOG_ERROR_N("closedir"); + + bad_dir: return result; } - -#endif diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index 41e3ae7..4bef28e 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -126,8 +126,6 @@ typedef enum _DBAction typedef enum _DBCommand { /** - * Gestion des commandes 'DBC_HELO' et 'DBC_WELCOME'. - * * Le client envoie un tout premier paquet de la forme suivante : * * [ Ordre de sauvegarde : DBC_HELO ] @@ -148,11 +146,21 @@ typedef enum _DBCommand /* ------------------------ Commandes pour administrateur ------------------------ */ + /** + * Le client envoie une requête pour lister les binaires de la forme suivante : + * + * [ Demande de liste : DBC_LIST_BINARIES ] + * + * Le serveur liste tous les répertoires présents et renvoie cette liste : + * + * [ Marqueur de liste : DBC_EXISTING_BINARIES ] + * [ Quantité d'éléments en ULEB128 ] + * [ Noms en chaîne RLE... ] + * + */ - - DBC_LIST_ARCHIVES, /* Fourniture des identifiants */ - - + DBC_LIST_BINARIES, /* Fourniture des identifiants */ + DBC_EXISTING_BINARIES, /* Eléments présents */ /* ------------------------ Commandes pour analyste ------------------------ */ |