From 73f5d359d6a0cc15ce463aa4b5595bd7112dec45 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 14 Nov 2021 21:58:40 +0100 Subject: Prevent usage of removed clients. --- src/analysis/db/cdb.c | 228 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 187 insertions(+), 41 deletions(-) diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 08410c4..c5d3af7 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -59,7 +59,7 @@ -/* ------------------------- COEUR DE LA GESTION D'ARCHIVES ------------------------- */ +/* -------------------------- LIEN VERS UN CLIENT CONNECTE -------------------------- */ /* Informations relatives à un client */ @@ -69,11 +69,28 @@ typedef struct _cdb_client char *peer_name; /* Désignation du correspondant*/ char *user; /* Utilisateur à l'autre bout */ - uint64_t last_time; /* Date de dernier envoi */ + gint ref_count; /* Décompte d'utilisation */ } cdb_client; +/* Met en place le suivi d'une connexion de client. */ +static cdb_client *create_cdb_client(SSL *, const char *, const char *); + +/* Supprime le suivi d'une connexion de client. */ +static void delete_cdb_client(cdb_client *); + +/* Augmente le décompte d'utilisation d'un suivi de connexion. */ +static void ref_cdb_client(cdb_client *); + +/* Diminue le décompte d'utilisation d'un suivi de connexion. */ +static void unref_cdb_client(cdb_client *); + + + +/* ------------------------- COEUR DE LA GESTION D'ARCHIVES ------------------------- */ + + /* Description d'une archive d'éléments utilisateur (instance) */ struct _GCdbArchive { @@ -92,7 +109,7 @@ struct _GCdbArchive GDbSnapshot *snapshot; /* Instantanés de bases SQL */ sqlite3 *db; /* Base de données à manipuler */ - cdb_client *clients; /* Connexions en place */ + cdb_client **clients; /* Connexions en place */ size_t count; /* Quantité de clients */ GMutex clients_access; /* Verrou pour l'accès */ @@ -180,6 +197,107 @@ static bool g_cdb_archive_set_content(GCdbArchive *, packed_buffer_t *, packed_b +/* -------------------------- LIEN VERS UN CLIENT CONNECTE -------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : fd = canal de communication réseau ouvert. * +* peer_name = désignation de la connexion. * +* user = désignation de l'utilisateur de la connexion. * +* * +* Description : Met en place le suivi d'une connexion de client. * +* * +* Retour : Structure dédiée construite. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static cdb_client *create_cdb_client(SSL *fd, const char *peer_name, const char *user) +{ + cdb_client *result; /* Fiche d'entité à retourner */ + + result = malloc(sizeof(cdb_client *)); + + result->tls_fd = fd; + + result->peer_name = strdup(peer_name); + result->user = strdup(user); + + g_atomic_int_set(&result->ref_count, 1); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = informations de suivi à libérer de la mémoire. * +* * +* Description : Supprime le suivi d'une connexion de client. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void delete_cdb_client(cdb_client *client) +{ + assert(g_atomic_int_get(&client->ref_count) == 0); + + SSL_free(client->tls_fd); + + free(client->peer_name); + free(client->user); + + free(client); + +} + + +/****************************************************************************** +* * +* Paramètres : client = informations de suivi à libérer de la mémoire. * +* * +* Description : Augmente le décompte d'utilisation d'un suivi de connexion. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void ref_cdb_client(cdb_client *client) +{ + g_atomic_int_inc(&client->ref_count); + +} + + +/****************************************************************************** +* * +* Paramètres : client = informations de suivi à libérer de la mémoire. * +* * +* Description : Diminue le décompte d'utilisation d'un suivi de connexion. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void unref_cdb_client(cdb_client *client) +{ + if (g_atomic_int_dec_and_test(&client->ref_count)) + delete_cdb_client(client); + +} + + + /* ---------------------------------------------------------------------------------- */ /* COEUR DE LA GESTION D'ARCHIVES */ /* ---------------------------------------------------------------------------------- */ @@ -246,6 +364,7 @@ static void g_cdb_archive_init(GCdbArchive *archive) archive->collections = create_collections_list(); archive->snapshot = NULL; + archive->db = NULL; g_mutex_init(&archive->clients_access); @@ -882,7 +1001,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].tls_fd); + status = ssl_send_packed_buffer(&pbuf, archive->clients[i]->tls_fd); if (!status) LOG_ERROR(LMT_ERROR, _("Failed to send some DB update")); @@ -911,6 +1030,8 @@ static void on_collection_extended(GDbCollection *collec, GDbItem *item, GCdbArc static void *g_cdb_archive_process(GCdbArchive *archive) { GServerBackend *base; /* Base de l'instance */ + cdb_client **clients; /* Clients surveillés */ + size_t last_count; /* Quantité de ces clients */ struct pollfd *fds; /* Surveillance des flux */ nfds_t nfds; /* Quantité de ces flux */ nfds_t i; /* Boucle de parcours */ @@ -927,20 +1048,38 @@ static void *g_cdb_archive_process(GCdbArchive *archive) base = G_SERVER_BACKEND(archive); + clients = NULL; + last_count = 0; + fds = NULL; while (1) { + /* Réinitialisation ? */ + + for (i = 0; i < last_count; i++) + unref_cdb_client(clients[i]); + /* Reconstitution d'une liste à jour */ g_mutex_lock(&archive->clients_access); - nfds = archive->count + 2; + last_count = archive->count; + + clients = realloc(clients, last_count * sizeof(cdb_client)); + + for (i = 0; i < last_count; i++) + { + clients[i] = archive->clients[i]; + ref_cdb_client(clients[i]); + } + + nfds = last_count + 2; fds = realloc(fds, nfds * sizeof(struct pollfd)); for (i = 0; i < (nfds - 2); i++) { - fds[i].fd = SSL_get_fd(archive->clients[i].tls_fd); + fds[i].fd = SSL_get_fd(clients[i]->tls_fd); fds[i].events = POLLIN | POLLPRI; } @@ -993,7 +1132,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive) { init_packed_buffer(&in_pbuf); - status = ssl_recv_packed_buffer(&in_pbuf, archive->clients[i].tls_fd); + status = ssl_recv_packed_buffer(&in_pbuf, clients[i]->tls_fd); if (!status) goto gcap_bad_exchange; next_command: @@ -1003,17 +1142,12 @@ static void *g_cdb_archive_process(GCdbArchive *archive) command = tmp32; + init_packed_buffer(&out_pbuf); + switch (command) { case DBC_SET_CONTENT: - status = g_cdb_archive_set_content(archive, &in_pbuf, &out_pbuf); - if (!status) goto gcap_bad_reply; - - status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd); - if (!status) goto gcap_bad_reply; - - exit_packed_buffer(&out_pbuf); break; @@ -1022,7 +1156,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive) error = g_cdb_archive_write(archive); - init_packed_buffer(&out_pbuf); + //init_packed_buffer(&out_pbuf); status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SAVE }, sizeof(uint32_t), true); @@ -1031,7 +1165,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].tls_fd); + status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd); if (!status) goto gcap_bad_reply; exit_packed_buffer(&out_pbuf); @@ -1072,10 +1206,10 @@ 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].tls_fd); - if (!status) goto gcap_bad_reply; + //status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd); + //if (!status) goto gcap_bad_reply; - exit_packed_buffer(&out_pbuf); + //exit_packed_buffer(&out_pbuf); break; @@ -1094,7 +1228,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].tls_fd); + status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd); if (!status) goto gcap_bad_reply; exit_packed_buffer(&out_pbuf); @@ -1106,10 +1240,12 @@ 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].tls_fd); - if (!status) goto gcap_bad_reply; + status = true; - exit_packed_buffer(&out_pbuf); + //status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd); + //if (!status) goto gcap_bad_reply; + + //exit_packed_buffer(&out_pbuf); break; @@ -1118,10 +1254,10 @@ 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].tls_fd); - if (!status) goto gcap_bad_reply; + //status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd); + //if (!status) goto gcap_bad_reply; - exit_packed_buffer(&out_pbuf); + //exit_packed_buffer(&out_pbuf); break; @@ -1240,6 +1376,17 @@ static void *g_cdb_archive_process(GCdbArchive *archive) } + if (!status) + goto gcap_bad_reply; + + if (get_packed_buffer_payload_length(&out_pbuf) > 0) + { + status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd); + if (!status) goto gcap_bad_reply; + } + + exit_packed_buffer(&out_pbuf); + if (has_more_data_in_packed_buffer(&in_pbuf)) goto next_command; @@ -1283,6 +1430,12 @@ static void *g_cdb_archive_process(GCdbArchive *archive) g_server_backend_stop(G_SERVER_BACKEND(archive)); + for (i = 0; i < last_count; i++) + unref_cdb_client(clients[i]); + + if (clients != NULL) + free(clients); + if (fds != NULL) free(fds); @@ -1328,15 +1481,13 @@ static void g_cdb_archive_add_client(GCdbArchive *archive, SSL *fd, const char * * g_cdb_archive_process() depuis un autre flot d'exécution. */ - g_mutex_lock(&archive->clients_access); + client = create_cdb_client(fd, peer_name, user); - archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client)); + g_mutex_lock(&archive->clients_access); - client = &archive->clients[archive->count - 1]; + archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client *)); - client->tls_fd = fd; - client->peer_name = strdup(peer_name); - client->user = strdup(user); + archive->clients[archive->count - 1] = client; g_mutex_unlock(&archive->clients_access); @@ -1358,20 +1509,15 @@ static void g_cdb_archive_add_client(GCdbArchive *archive, SSL *fd, const char * 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); + unref_cdb_client(archive->clients[index]); if ((index + 1) < archive->count) memmove(&archive->clients[index], &archive->clients[index + 1], - (archive->count - index - 1) * sizeof(cdb_client)); + (archive->count - index - 1) * sizeof(cdb_client *)); - archive->clients = realloc(archive->clients, --archive->count * sizeof(cdb_client)); + archive->clients = realloc(archive->clients, --archive->count * sizeof(cdb_client *)); } @@ -1422,7 +1568,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].tls_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); -- cgit v0.11.2-87-g4458