summaryrefslogtreecommitdiff
path: root/src/analysis/db
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2021-05-30 23:40:39 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2021-05-30 23:40:39 (GMT)
commit1865cce4d51b9c7a6fb718f4e2c034a57365ad1b (patch)
treec82b56f65504596c1ab3e3ef426cca55bca40a62 /src/analysis/db
parent3a9cf58a75c87b9046c1646a97b798508619fd62 (diff)
Create a command to list remote binaries.
Diffstat (limited to 'src/analysis/db')
-rw-r--r--src/analysis/db/admin.c209
-rw-r--r--src/analysis/db/admin.h6
-rw-r--r--src/analysis/db/controller.c122
-rw-r--r--src/analysis/db/protocol.h20
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 ------------------------ */