summaryrefslogtreecommitdiff
path: root/src/analysis/db/cdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/db/cdb.c')
-rw-r--r--src/analysis/db/cdb.c349
1 files changed, 166 insertions, 183 deletions
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index 9e24f84..8d589b3 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * cdb.h - prototypes pour la manipulation des archives au format CDB
+ * cdb.c - manipulation des archives au format CDB
*
* Copyright (C) 2014-2019 Cyrille Bagard
*
@@ -29,7 +29,6 @@
#include <malloc.h>
#include <poll.h>
#include <pthread.h>
-#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -42,6 +41,7 @@
#include <config.h>
+#include "backend-int.h"
#include "collection.h"
#include "protocol.h"
#include "snapshot.h"
@@ -61,7 +61,8 @@
/* Informations relatives à un client */
typedef struct _cdb_client
{
- SSL *ssl_fd; /* Canal de communication */
+ SSL *tls_fd; /* Canal de communication */
+ char *peer_name; /* Désignation du correspondant*/
char *user; /* Utilisateur à l'autre bout */
uint64_t last_time; /* Date de dernier envoi */
@@ -89,11 +90,6 @@ struct _GCdbArchive
size_t count; /* Quantité de clients */
GMutex clients_access; /* Verrou pour l'accès */
- GThread *process; /* Procédure de traitement */
- GMutex id_access; /* Accès à l'identifiant */
- GCond id_cond; /* Condition d'attente */
- pthread_t process_id; /* Identifiant de la procédure */
-
};
/* Description d'une archive d'éléments utilisateur (classe) */
@@ -147,6 +143,15 @@ static void on_collection_extended(GDbCollection *, GDbItem *, GCdbArchive *);
/* Assure le traitement des requêtes de clients. */
static void *g_cdb_archive_process(GCdbArchive *);
+/* Prend en compte une connexion nouvelle d'un utilisateur. */
+static void g_cdb_archive_add_client(GCdbArchive *, SSL *, const char *, const char *);
+
+/* Dissocie un utilisateur de l'archive. */
+static void _g_cdb_archive_remove_client(GCdbArchive *, size_t);
+
+/* Dissocie un utilisateur de l'archive. */
+static void g_cdb_archive_remove_client(GCdbArchive *, size_t);
+
/* Envoie un paquet de données constitué à tous les clients. */
static void g_cdb_archive_send_reply_to_all_clients(GCdbArchive *, packed_buffer *);
@@ -156,12 +161,6 @@ static bool g_cdb_archive_send_snapshot_update(GCdbArchive *, packed_buffer *);
/* Envoie à tous les clients le nouvel instantané courant. */
static bool g_cdb_archive_send_snapshot_change(GCdbArchive *, packed_buffer *);
-/* Dissocie un utilisateur de l'archive. */
-static void _g_cdb_archive_remove_client(GCdbArchive *, size_t);
-
-/* Dissocie un utilisateur de l'archive. */
-static void g_cdb_archive_remove_client(GCdbArchive *, size_t);
-
/* ---------------------------------------------------------------------------------- */
@@ -170,7 +169,7 @@ static void g_cdb_archive_remove_client(GCdbArchive *, size_t);
/* Indique le type défini pour une une archive d'éléments utilisateur. */
-G_DEFINE_TYPE(GCdbArchive, g_cdb_archive, G_TYPE_OBJECT);
+G_DEFINE_TYPE(GCdbArchive, g_cdb_archive, G_TYPE_SERVER_BACKEND);
/******************************************************************************
@@ -188,12 +187,20 @@ G_DEFINE_TYPE(GCdbArchive, g_cdb_archive, G_TYPE_OBJECT);
static void g_cdb_archive_class_init(GCdbArchiveClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
+ GServerBackendClass *backend; /* Classe parente */
object = G_OBJECT_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_cdb_archive_dispose;
object->finalize = (GObjectFinalizeFunc)g_cdb_archive_finalize;
+ backend = G_SERVER_BACKEND_CLASS(klass);
+
+ backend->thread_name = "cdb_archiver";
+ backend->thread_func = (GThreadFunc)g_cdb_archive_process;
+
+ backend->add_client = (add_backend_client_fc)g_cdb_archive_add_client;
+
}
@@ -213,6 +220,7 @@ static void g_cdb_archive_init(GCdbArchive *archive)
{
setup_empty_rle_string(&archive->hash);
+ archive->filename = NULL;
archive->tmpdir = NULL;
archive->collections = create_collections_list();
@@ -221,9 +229,6 @@ static void g_cdb_archive_init(GCdbArchive *archive)
g_mutex_init(&archive->clients_access);
- g_mutex_init(&archive->id_access);
- g_cond_init(&archive->id_cond);
-
}
@@ -241,10 +246,9 @@ static void g_cdb_archive_init(GCdbArchive *archive)
static void g_cdb_archive_dispose(GCdbArchive *archive)
{
- g_clear_object(&archive->snapshot);
+ g_server_backend_stop(G_SERVER_BACKEND(archive));
- g_cond_clear(&archive->id_cond);
- g_mutex_clear(&archive->id_access);
+ g_clear_object(&archive->snapshot);
g_mutex_clear(&archive->clients_access);
@@ -284,7 +288,8 @@ static void g_cdb_archive_finalize(GCdbArchive *archive)
if (archive->xml_desc != NULL)
free(archive->xml_desc);
- free(archive->filename);
+ if (archive->filename != NULL)
+ free(archive->filename);
if (archive->tmpdir != NULL)
free(archive->tmpdir);
@@ -804,7 +809,7 @@ static void on_collection_extended(GDbCollection *collec, GDbItem *item, GCdbArc
for (i = 0; i < archive->count && status; i++)
{
- status = ssl_send_packed_buffer(&pbuf, archive->clients[i].ssl_fd);
+ status = ssl_send_packed_buffer(&pbuf, archive->clients[i].tls_fd);
if (!status)
LOG_ERROR(LMT_ERROR, _("Failed to send some DB update"));
@@ -832,6 +837,7 @@ static void on_collection_extended(GDbCollection *collec, GDbItem *item, GCdbArc
static void *g_cdb_archive_process(GCdbArchive *archive)
{
+ GServerBackend *base; /* Base de l'instance */
struct pollfd *fds; /* Surveillance des flux */
nfds_t nfds; /* Quantité de ces flux */
nfds_t i; /* Boucle de parcours */
@@ -846,14 +852,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
bool reload; /* Besoin de rechargement */
char *msg; /* Erreur à faire remonter */
- void interrupt_poll_with_sigusr1(int sig) { };
-
- signal(SIGUSR1, interrupt_poll_with_sigusr1);
-
- g_mutex_lock(&archive->id_access);
- archive->process_id = pthread_self();
- g_cond_signal(&archive->id_cond);
- g_mutex_unlock(&archive->id_access);
+ base = G_SERVER_BACKEND(archive);
fds = NULL;
@@ -863,35 +862,46 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
g_mutex_lock(&archive->clients_access);
- nfds = archive->count;
+ nfds = archive->count + 2;
fds = realloc(fds, nfds * sizeof(struct pollfd));
- for (i = 0; i < nfds; i++)
+ for (i = 0; i < (nfds - 2); i++)
{
- fds[i].fd = SSL_get_fd(archive->clients[i].ssl_fd);
+ fds[i].fd = SSL_get_fd(archive->clients[i].tls_fd);
fds[i].events = POLLIN | POLLPRI;
}
g_mutex_unlock(&archive->clients_access);
- if (nfds == 0)
+ if (nfds == 2)
goto gcap_no_more_clients;
+ fds[nfds - 2].fd = base->stop_ctrl[0];
+ fds[nfds - 2].events = POLLIN | POLLPRI;
+
+ fds[nfds - 1].fd = base->refresh_ctrl[0];
+ fds[nfds - 1].events = POLLIN | POLLPRI;
+
/* Lancement d'une phase de surveillance */
ret = poll(fds, nfds, -1);
if (ret == -1)
{
- if (errno == EINTR) continue;
-
LOG_ERROR_N("poll");
break;
-
}
+ /* Demande expresse d'arrêt des procédures */
+ if (fds[nfds - 2].revents)
+ break;
+
+ /* Demande d'actualisation */
+ if (fds[nfds - 1].revents)
+ continue;
+
/* Traitement des requêtes reçues */
- for (i = 0; i < nfds; i++)
+ for (i = 0; i < (nfds - 1); i++)
{
/* Le canal est fermé, une sortie doit être demandée... */
if (fds[i].revents & POLLNVAL)
@@ -910,7 +920,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
{
init_packed_buffer(&in_pbuf);
- status = ssl_recv_packed_buffer(&in_pbuf, archive->clients[i].ssl_fd);
+ status = ssl_recv_packed_buffer(&in_pbuf, archive->clients[i].tls_fd);
if (!status) goto gcap_bad_exchange;
next_command:
@@ -935,7 +945,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
status = extend_packed_buffer(&out_pbuf, (uint32_t []) { error }, sizeof(uint32_t), true);
if (!status) goto gcap_bad_reply;
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd);
+ status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
if (!status) goto gcap_bad_reply;
exit_packed_buffer(&out_pbuf);
@@ -976,7 +986,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
status = extend_packed_buffer(&out_pbuf, (uint8_t []) { 0x0 }, sizeof(uint8_t), true);
if (!status) goto gcap_bad_reply;
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd);
+ status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
if (!status) goto gcap_bad_reply;
exit_packed_buffer(&out_pbuf);
@@ -998,7 +1008,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
&in_pbuf, &out_pbuf, archive->db);
if (!status) goto gcap_bad_reply;
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd);
+ status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
if (!status) goto gcap_bad_reply;
exit_packed_buffer(&out_pbuf);
@@ -1010,7 +1020,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
if (!g_cdb_archive_send_snapshot_update(archive, &out_pbuf))
goto critical_error;
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd);
+ status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
if (!status) goto gcap_bad_reply;
exit_packed_buffer(&out_pbuf);
@@ -1022,7 +1032,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
if (!g_cdb_archive_send_snapshot_change(archive, &out_pbuf))
goto critical_error;
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd);
+ status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
if (!status) goto gcap_bad_reply;
exit_packed_buffer(&out_pbuf);
@@ -1185,12 +1195,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
gcap_no_more_clients:
- archive->process = NULL;
-
- g_mutex_lock(&archive->id_access);
- archive->process_id = 0;
- g_cond_signal(&archive->id_cond);
- g_mutex_unlock(&archive->id_access);
+ g_server_backend_stop(G_SERVER_BACKEND(archive));
if (fds != NULL)
free(fds);
@@ -1202,6 +1207,115 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
/******************************************************************************
* *
+* Paramètres : archive = support pour le suivi d'une connexion. *
+* fd = canal de communication réseau ouvert. *
+* peer_name = désignation de la connexion. *
+* user = désignation de l'utilisateur de la connexion. *
+* *
+* Description : Prend en compte une connexion nouvelle d'un utilisateur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_cdb_archive_add_client(GCdbArchive *archive, SSL *fd, const char *peer_name, const char *user)
+{
+ cdb_client *client; /* Nouvelle fiche d'entité */
+
+ /**
+ * La situation est un peu compliquée lors de l'accueil d'un nouveau client :
+ *
+ * - soit on envoie tous les éléments à prendre en compte, mais on doit
+ * bloquer la base de données jusqu'à l'intégration pleine et entière
+ * du client, afin que ce dernier ne loupe pas l'envoi d'un nouvel
+ * élément entre temps.
+ *
+ * - soit on intègre le client et celui ci demande des mises à jour
+ * collection par collection ; c'est également à lui que revient le rejet
+ * des éléments envoyés en solitaires avant la réception de la base
+ * complète.
+ *
+ * On fait le choix du second scenario ici, du fait de la difficulté
+ * de maîtriser facilement la reconstitution d'une liste de clients dans
+ * g_cdb_archive_process() depuis un autre flot d'exécution.
+ */
+
+ g_mutex_lock(&archive->clients_access);
+
+ archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client));
+
+ client = &archive->clients[archive->count - 1];
+
+ client->tls_fd = fd;
+ client->peer_name = strdup(peer_name);
+ client->user = strdup(user);
+
+ g_mutex_unlock(&archive->clients_access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = archive à connecter avec un utilisateur. *
+* index = indice de l'utilisateur concerné. *
+* *
+* Description : Dissocie un utilisateur de l'archive. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void _g_cdb_archive_remove_client(GCdbArchive *archive, size_t index)
+{
+ cdb_client *client; /* Client à traiter */
+
+ assert(!g_mutex_trylock(&archive->clients_access));
+
+ client = &archive->clients[index];
+
+ SSL_free(client->tls_fd);
+ free(client->user);
+
+ if ((index + 1) < archive->count)
+ memmove(&archive->clients[index], &archive->clients[index + 1],
+ (archive->count - index - 1) * sizeof(cdb_client));
+
+ archive->clients = realloc(archive->clients, --archive->count * sizeof(cdb_client));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = archive à connecter avec un utilisateur. *
+* index = indice de l'utilisateur concerné. *
+* *
+* Description : Dissocie un utilisateur de l'archive. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_cdb_archive_remove_client(GCdbArchive *archive, size_t index)
+{
+ g_mutex_lock(&archive->clients_access);
+
+ _g_cdb_archive_remove_client(archive, index);
+
+ g_mutex_unlock(&archive->clients_access);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : archive = archive à connecter avec un utilisateur. *
* pbuf = paquet de données à émettre. *
* *
@@ -1222,7 +1336,7 @@ static void g_cdb_archive_send_reply_to_all_clients(GCdbArchive *archive, packed
for (i = 0; i < archive->count; i++)
{
- status = ssl_send_packed_buffer(pbuf, archive->clients[i].ssl_fd);
+ status = ssl_send_packed_buffer(pbuf, archive->clients[i].tls_fd);
if (!status)
{
log_variadic_message(LMT_ERROR, _("Error while replying to client %zu"), i);
@@ -1337,134 +1451,3 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *archive, packed_buff
return result;
}
-
-
-/******************************************************************************
-* *
-* Paramètres : archive = archive à connecter avec un utilisateur. *
-* fd = canal de communication réseau ouvert. *
-* *
-* Description : Associe un nouvel utilisateur à l'archive. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_cdb_archive_add_client(GCdbArchive *archive, SSL *fd)
-{
- X509 *peer_cert; /* Certificat présenté */
- volatile pthread_t *process_id; /* Identifiant de la procédure */
-
- /**
- * La situation est un peu compliquée lors de l'accueil d'un nouveau client :
- *
- * - soit on envoie tous les éléments à prendre en compte, mais on doit
- * bloquer la base de données jusqu'à l'intégration pleine et entière
- * du client, afin que ce dernier ne loupe pas l'envoi d'un nouvel
- * élément entre temps.
- *
- * - soit on intègre le client et celui ci demande des mises à jour
- * collection par collection ; c'est également à lui qui revient le rejet
- * des éléments envoyés en solitaires avant la réception de la base
- * complète.
- *
- * On fait le choix du second scenario ici, du fait de la difficulté
- * de maîtriser facilement la reconstitution d'une liste de clients dans
- * g_cdb_archive_process() depuis un autre flot d'exécution.
- */
-
- /* Ajout dans la liste officielle */
-
- g_mutex_lock(&archive->clients_access);
-
- archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client));
-
- archive->clients[archive->count - 1].ssl_fd = fd;
-
- peer_cert = SSL_get_peer_certificate(fd);
-
- archive->clients[archive->count - 1].user = X509_NAME_oneline(X509_get_subject_name(peer_cert), NULL, -1);
-
- X509_free(peer_cert);
-
- /* Démarrage ou redémarrage du processus d'écoute */
-
- if (archive->process == NULL)
- {
- archive->process = g_thread_new("cdb_process", (GThreadFunc)g_cdb_archive_process, archive);
-
- /* On attend que le processus parallèle soit prêt */
-
- process_id = &archive->process_id;
-
- g_mutex_lock(&archive->id_access);
- while (process_id == 0)
- g_cond_wait(&archive->id_cond, &archive->id_access);
- g_mutex_unlock(&archive->id_access);
-
- }
- else
- pthread_kill(archive->process_id, SIGUSR1);
-
- g_mutex_unlock(&archive->clients_access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : archive = archive à connecter avec un utilisateur. *
-* index = indice de l'utilisateur concerné. *
-* *
-* Description : Dissocie un utilisateur de l'archive. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void _g_cdb_archive_remove_client(GCdbArchive *archive, size_t index)
-{
- cdb_client *client; /* Client à traiter */
-
- assert(!g_mutex_trylock(&archive->clients_access));
-
- client = &archive->clients[index];
-
- SSL_free(client->ssl_fd);
- free(client->user);
-
- if ((index + 1) < archive->count)
- memmove(&archive->clients[index], &archive->clients[index + 1],
- (archive->count - index - 1) * sizeof(cdb_client));
-
- archive->clients = realloc(archive->clients, --archive->count * sizeof(cdb_client));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : archive = archive à connecter avec un utilisateur. *
-* index = indice de l'utilisateur concerné. *
-* *
-* Description : Dissocie un utilisateur de l'archive. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_cdb_archive_remove_client(GCdbArchive *archive, size_t index)
-{
- g_mutex_lock(&archive->clients_access);
-
- _g_cdb_archive_remove_client(archive, index);
-
- g_mutex_unlock(&archive->clients_access);
-
-}