diff options
Diffstat (limited to 'src/analysis/db')
-rw-r--r-- | src/analysis/db/Makefile.am | 8 | ||||
-rw-r--r-- | src/analysis/db/analyst-int.h | 76 | ||||
-rw-r--r-- | src/analysis/db/analyst.c | 245 | ||||
-rw-r--r-- | src/analysis/db/analyst.h | 20 | ||||
-rw-r--r-- | src/analysis/db/cdb.c | 380 | ||||
-rw-r--r-- | src/analysis/db/cdb.h | 6 | ||||
-rw-r--r-- | src/analysis/db/items/Makefile.am | 11 | ||||
-rw-r--r-- | src/analysis/db/items/comment.c | 2 | ||||
-rw-r--r-- | src/analysis/db/items/move.c | 12 | ||||
-rw-r--r-- | src/analysis/db/misc/Makefile.am | 11 | ||||
-rw-r--r-- | src/analysis/db/protocol.h | 31 | ||||
-rw-r--r-- | src/analysis/db/server.c | 36 |
12 files changed, 676 insertions, 162 deletions
diff --git a/src/analysis/db/Makefile.am b/src/analysis/db/Makefile.am index 8f8242c..b9325e0 100644 --- a/src/analysis/db/Makefile.am +++ b/src/analysis/db/Makefile.am @@ -21,20 +21,16 @@ libanalysisdb_la_SOURCES = \ server.h server.c \ snapshot.h snapshot.c +libanalysisdb_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE_CFLAGS) $(LIBSSL_CFLAGS) + libanalysisdb_la_LIBADD = \ items/libanalysisdbitems.la \ misc/libanalysisdbmisc.la -libanalysisdb_la_LDFLAGS = $(LIBSSL_LIBS) - devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) dev_HEADERS = $(libanalysisdb_la_SOURCES:%c=) -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE_CFLAGS) $(LIBSSL_CFLAGS) - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) - SUBDIRS = items misc diff --git a/src/analysis/db/analyst-int.h b/src/analysis/db/analyst-int.h new file mode 100644 index 0000000..4f76eff --- /dev/null +++ b/src/analysis/db/analyst-int.h @@ -0,0 +1,76 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * analyst-int.h - prototypes pour la définition interne des connexions en analyste à un serveur Chrysalide + * + * Copyright (C) 2022 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DB_ANALYST_INT_H +#define _ANALYSIS_DB_ANALYST_INT_H + + +#include "analyst.h" +#include "client-int.h" + + + +/* Description de client à l'écoute (instance) */ +struct _GAnalystClient +{ + GHubClient parent; /* A laisser en premier */ + + char *cnt_hash; /* Empreinte du binaire lié */ + char *cnt_class; /* Interprétation du contenu */ + + GLoadedContent *loaded; /* Contenu chargé */ + GList *collections; /* Collections d'un binaire */ + + bool can_get_updates; /* Réception de maj possibles ?*/ + + snapshot_info_t *snapshots; /* Liste des instantanés */ + size_t snap_count; /* Taille de cette liste */ + GMutex snap_lock; /* Concurrence des accès */ + + snapshot_id_t current; /* Instantané courant */ + bool has_current; /* Validité de l'identifiant */ + GMutex cur_lock; /* Concurrence des accès */ + +}; + +/* Description de client à l'écoute (classe) */ +struct _GAnalystClientClass +{ + GHubClientClass parent; /* A laisser en premier */ + + /* Signaux */ + + void (* ready) (GAnalystClient *); + void (* server_status_changed) (GAnalystClient *, LoadingStatusHint); + void (* snapshots_updated) (GAnalystClient *); + void (* snapshot_changed) (GAnalystClient *); + +}; + + +/* Prépare un client pour une connexion à une BD. */ +bool g_analyst_client_setup(GAnalystClient *, const char *, const char *, GList *, GLoadedContent *); + + + +#endif /* _ANALYSIS_DB_ANALYST_INT_H */ diff --git a/src/analysis/db/analyst.c b/src/analysis/db/analyst.c index 49585c2..43fb840 100644 --- a/src/analysis/db/analyst.c +++ b/src/analysis/db/analyst.c @@ -29,43 +29,13 @@ #include <string.h> -#include "client-int.h" +#include "analyst-int.h" #include "../storage/storage.h" #include "../../core/logs.h" -/* Description de client à l'écoute (instance) */ -struct _GAnalystClient -{ - GHubClient parent; /* A laisser en premier */ - - char *hash; /* Empreinte du binaire lié */ - GList *collections; /* Collections d'un binaire */ - - bool can_get_updates; /* Réception de maj possibles ?*/ - - snapshot_info_t *snapshots; /* Liste des instantanés */ - size_t snap_count; /* Taille de cette liste */ - GMutex snap_lock; /* Concurrence des accès */ - - snapshot_id_t current; /* Instantané courant */ - bool has_current; /* Validité de l'identifiant */ - GMutex cur_lock; /* Concurrence des accès */ - -}; - -/* Description de client à l'écoute (classe) */ -struct _GAnalystClientClass -{ - GHubClientClass parent; /* A laisser en premier */ - - /* Signaux */ - - void (* snapshots_updated) (GAnalystClient *); - void (* snapshot_changed) (GAnalystClient *); - -}; +/* ----------------------- DEFINITION D'ANALYSTE COMME CLIENT ----------------------- */ /* Initialise la classe des descriptions de fichier binaire. */ @@ -94,6 +64,58 @@ static bool g_analyst_client_update_current_snapshot(GAnalystClient *, packed_bu +/* ------------------------- PRISES EN COMPTE DES COMMANDES ------------------------- */ + + +/* Prend en compte une évolution du statut côté serveur. */ +static bool g_analyst_client_handle_loading_hints(GAnalystClient *, packed_buffer_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUES POUR LA GLIB */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Définit un type GLib pour l'énumération "LoadingStatusHint". * +* * +* Retour : Type GLib enregistré. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GType g_loading_status_hint_type(void) +{ + static GType result = 0; + + static const GEnumValue values[] = { + { LSH_READY, "LSH_READY", "ready" }, + { LSH_ON_WAIT_LIST, "LSH_ON_WAIT_LIST", "on_wait_list" }, + { LSH_NEED_CONTENT, "LSH_NEED_CONTENT", "need_content" }, + { LSH_NEED_FORMAT, "LSH_NEED_FORMAT", "need_format" }, + { LSH_NEED_ARCH, "LSH_NEED_ARCH", "need_arch" }, + { 0, NULL, NULL } + }; + + if (result == 0) + result = g_enum_register_static(g_intern_static_string("LoadingStatusHint"), values); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'ANALYSTE COMME CLIENT */ +/* ---------------------------------------------------------------------------------- */ + + /* Indique le type défini pour une description de client à l'écoute. */ G_DEFINE_TYPE(GAnalystClient, g_analyst_client, G_TYPE_HUB_CLIENT); @@ -126,6 +148,22 @@ static void g_analyst_client_class_init(GAnalystClientClass *klass) client->complete_hello = (complete_client_hello_fc)g_analyst_client_complete_hello; client->recv_func = (GThreadFunc)g_analyst_client_update; + g_signal_new("ready", + G_TYPE_ANALYST_CLIENT, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GAnalystClientClass, ready), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_signal_new("server-status-changed", + G_TYPE_ANALYST_CLIENT, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GAnalystClientClass, server_status_changed), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, G_TYPE_LOADING_STATUS_HINT); + g_signal_new("snapshots-updated", G_TYPE_ANALYST_CLIENT, G_SIGNAL_RUN_LAST, @@ -159,7 +197,10 @@ static void g_analyst_client_class_init(GAnalystClientClass *klass) static void g_analyst_client_init(GAnalystClient *client) { - client->hash = NULL; + client->cnt_hash = NULL; + client->cnt_class = NULL; + + client->loaded = NULL; client->collections = NULL; client->can_get_updates = false; @@ -195,6 +236,8 @@ static void g_analyst_client_dispose(GAnalystClient *client) g_mutex_clear(&client->snap_lock); + g_clear_object(&client->loaded); + G_OBJECT_CLASS(g_analyst_client_parent_class)->dispose(G_OBJECT(client)); } @@ -216,8 +259,11 @@ static void g_analyst_client_finalize(GAnalystClient *client) { size_t i; /* Boucle de parcours */ - if (client->hash != NULL) - free(client->hash); + if (client->cnt_hash != NULL) + free(client->cnt_hash); + + if (client->cnt_class != NULL) + free(client->cnt_class); if (client->snapshots != NULL) { @@ -236,9 +282,11 @@ static void g_analyst_client_finalize(GAnalystClient *client) /****************************************************************************** * * * Paramètres : hash = empreinte d'un binaire en cours d'analyse. * +* class = nature de l'interprétation de ce contenu. * * collections = ensemble de collections existantes. * +* loaded = éventuel élément local préchargé. * * * -* Description : Prépare un client pour une connexion à une BD. * +* Description : Met en place un client pour une connexion à une BD. * * * * Retour : Structure mise en place ou NULL en cas d'échec. * * * @@ -246,14 +294,54 @@ static void g_analyst_client_finalize(GAnalystClient *client) * * ******************************************************************************/ -GAnalystClient *g_analyst_client_new(const char *hash, GList *collections) +GAnalystClient *g_analyst_client_new(const char *hash, const char *class, GList *collections, GLoadedContent *loaded) { GAnalystClient *result; /* Adresse à retourner */ + bool status; /* Bilan de l'initialisation */ result = g_object_new(G_TYPE_ANALYST_CLIENT, NULL); - result->hash = strdup(hash); - result->collections = collections; + status = g_analyst_client_setup(result, hash, class, collections, loaded); + + assert(status); + + if (!status) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à initialiser. * +* hash = empreinte d'un binaire en cours d'analyse. * +* class = nature de l'interprétation de ce contenu. * +* collections = ensemble de collections existantes. * +* loaded = éventuel élément local préchargé. * +* * +* Description : Prépare un client pour une connexion à une BD. * +* * +* Retour : Structure mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_analyst_client_setup(GAnalystClient *client, const char *hash, const char *class, GList *collections, GLoadedContent *loaded) +{ + bool result; /* Bilan à retourner */ + + result = true; + + client->cnt_hash = strdup(hash); + client->cnt_class = strdup(class); + + client->loaded = loaded; + if (loaded != NULL) g_object_ref(G_OBJECT(loaded)); + + client->collections = collections; return result; @@ -278,7 +366,13 @@ static bool g_analyst_client_complete_hello(GAnalystClient *client, packed_buffe bool result; /* Bilan à retourner */ rle_string str; /* Chaîne à communiquer */ - init_static_rle_string(&str, client->hash); + init_static_rle_string(&str, client->cnt_hash); + + result = pack_rle_string(&str, pbuf); + + exit_rle_string(&str); + + init_static_rle_string(&str, client->cnt_class); result = pack_rle_string(&str, pbuf); @@ -406,6 +500,11 @@ static void *g_analyst_client_update(GAnalystClient *client) switch (command) { + case DBC_LOADING_STATUS: + status = g_analyst_client_handle_loading_hints(client, &in_pbuf); + if (!status) goto gdcu_bad_exchange; + break; + case DBC_SAVE: status = extract_packed_buffer(&in_pbuf, &tmp32, sizeof(uint32_t), true); @@ -414,10 +513,10 @@ static void *g_analyst_client_update(GAnalystClient *client) error = tmp32; if (error == DBE_NONE) - log_variadic_message(LMT_INFO, _("Archive saved for binary '%s'"), client->hash); + log_variadic_message(LMT_INFO, _("Archive saved for binary '%s'"), client->cnt_hash); else log_variadic_message(LMT_ERROR, _("Failed to save the archive for binary '%s'"), - client->hash); + client->cnt_hash); break; @@ -669,10 +768,10 @@ bool g_analyst_client_send_content(GAnalystClient *client, GBinContent *content) hash = g_binary_content_get_checksum(content); - if (strcmp(hash, client->hash) != 0) + if (strcmp(hash, client->cnt_hash) != 0) { log_variadic_message(LMT_ERROR, _("Provided ontent does not match client content (hash: '%s')"), - client->hash); + client->cnt_hash); goto exit; } @@ -680,7 +779,7 @@ bool g_analyst_client_send_content(GAnalystClient *client, GBinContent *content) init_packed_buffer(&cnt_pbuf); - storage = g_object_storage_new(client->hash); + storage = g_object_storage_new(client->cnt_hash); result = g_object_storage_store_object(storage, "contents", G_SERIALIZABLE_OBJECT(content), &pos); if (!result) goto exit_with_failure; @@ -1261,3 +1360,59 @@ bool g_analyst_client_remove_snapshot(GAnalystClient *client, const snapshot_id_ return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* PRISES EN COMPTE DES COMMANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : archive = archive à connecter avec un utilisateur. * +* in_pbuf = paquet à consulter. * +* * +* Description : Prend en compte une évolution du statut côté serveur. * +* * +* Retour : Indication pour le maintien de la communication. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_analyst_client_handle_loading_hints(GAnalystClient *client, packed_buffer_t *in_pbuf) +{ + bool result; /* Bilan à retourner */ + uleb128_t hint; /* Indication du serveur */ + + result = unpack_uleb128(&hint, in_pbuf); + + switch (hint) + { + case LSH_READY: + g_signal_emit_by_name(client, "ready"); + break; + + case LSH_ON_WAIT_LIST: + log_simple_message(LMT_INFO, _("Waiting for content from server...")); + break; + + case LSH_NEED_CONTENT: + case LSH_NEED_FORMAT: + case LSH_NEED_ARCH: + g_signal_emit_by_name(client, "server-status-changed", hint); + break; + + default: + log_variadic_message(LMT_ERROR, + _("Unknown loaded hint received (%x); unsupported newer protocol?"), + hint); + result = false; + break; + + } + + return result; + +} diff --git a/src/analysis/db/analyst.h b/src/analysis/db/analyst.h index 7b11f53..ff189ba 100644 --- a/src/analysis/db/analyst.h +++ b/src/analysis/db/analyst.h @@ -34,9 +34,25 @@ #include "collection.h" #include "misc/snapshot.h" #include "../content.h" +#include "../loaded.h" + +/* ------------------------------- GLUES POUR LA GLIB ------------------------------- */ + + +#define G_TYPE_LOADING_STATUS_HINT g_loading_status_hint_type() + + +/* Définit un type GLib pour l'énumération "LoadingStatusHint". */ +GType g_loading_status_hint_type(void); + + + +/* ----------------------- DEFINITION D'ANALYSTE COMME CLIENT ----------------------- */ + + #define G_TYPE_ANALYST_CLIENT g_analyst_client_get_type() #define G_ANALYST_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ANALYST_CLIENT, GAnalystClient)) #define G_IS_ANALYST_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ANALYST_CLIENT)) @@ -55,8 +71,8 @@ typedef struct _GAnalystClientClass GAnalystClientClass; /* Indique le type défini pour une description de client à l'écoute. */ GType g_analyst_client_get_type(void); -/* Prépare un client pour une connexion à une BD. */ -GAnalystClient *g_analyst_client_new(const char *, GList *); +/* Met en place un client pour une connexion à une BD. */ +GAnalystClient *g_analyst_client_new(const char *, const char *, GList *, GLoadedContent *); /* Envoie un contenu binaire pour conservation côté serveur. */ bool g_analyst_client_send_content(GAnalystClient *, GBinContent *); diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 62de6a7..6d4b84d 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -38,8 +38,8 @@ #include <sys/stat.h> -#include <i18n.h> #include <config.h> +#include <i18n.h> #include "backend-int.h" @@ -59,7 +59,7 @@ -/* ------------------------- COEUR DE LA GESTION D'ARCHIVES ------------------------- */ +/* -------------------------- LIEN VERS UN CLIENT CONNECTE -------------------------- */ /* Informations relatives à un client */ @@ -69,29 +69,51 @@ 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 { GServerBackend parent; /* A laisser en premier */ rle_string hash; /* Empreinte cryptographique */ + rle_string class; /* Nature du contenu analysé */ char *filename; /* Chemin d'accès à l'archive */ char *tmpdir; /* Répertoire de travail */ - char *cnt_file; /* Fichier de contenu binaire */ char *xml_desc; /* Fichier de description */ + char *cnt_file; /* Fichier de contenu binaire */ + + GMutex loading_access; /* Verrou pour l'accès */ + + GList *collections; /* Ensemble de modifications */ 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 */ @@ -171,14 +193,115 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *, packed_buffer_t *) /* ------------------------- PRISES EN COMPTE DES COMMANDES ------------------------- */ -/* Prépare la réponse à envoyer à un client connecté. */ -static bool setup_server_answer(DBCommand, DBError, packed_buffer_t *); +/* Prépare une courte réponse à envoyer à un client connecté. */ +static bool craft_server_short_answer(DBCommand, uleb128_t, packed_buffer_t *); /* Enregistre le contenu binaire lié à une analyse. */ static bool g_cdb_archive_set_content(GCdbArchive *, packed_buffer_t *, packed_buffer_t *); +/* -------------------------- 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 */ /* ---------------------------------------------------------------------------------- */ @@ -235,15 +358,19 @@ static void g_cdb_archive_class_init(GCdbArchiveClass *klass) static void g_cdb_archive_init(GCdbArchive *archive) { setup_empty_rle_string(&archive->hash); + setup_empty_rle_string(&archive->class); archive->filename = NULL; archive->tmpdir = NULL; - archive->cnt_file = NULL; archive->xml_desc = NULL; + archive->cnt_file = NULL; + g_mutex_init(&archive->loading_access); + archive->collections = create_collections_list(); archive->snapshot = NULL; + archive->db = NULL; g_mutex_init(&archive->clients_access); @@ -266,9 +393,11 @@ static void g_cdb_archive_dispose(GCdbArchive *archive) { g_server_backend_stop(G_SERVER_BACKEND(archive)); + g_mutex_clear(&archive->clients_access); + g_clear_object(&archive->snapshot); - g_mutex_clear(&archive->clients_access); + g_mutex_clear(&archive->loading_access); G_OBJECT_CLASS(g_cdb_archive_parent_class)->dispose(G_OBJECT(archive)); @@ -315,6 +444,7 @@ static void g_cdb_archive_finalize(GCdbArchive *archive) if (archive->filename != NULL) free(archive->filename); + exit_rle_string(&archive->class); exit_rle_string(&archive->hash); G_OBJECT_CLASS(g_cdb_archive_parent_class)->finalize(G_OBJECT(archive)); @@ -327,6 +457,7 @@ static void g_cdb_archive_finalize(GCdbArchive *archive) * Paramètres : basedir = répertoire de stockage des enregistrements. * * tmpdir = répertoire de travail temporaire. * * hash = empreinte du binaire à représenter. * +* class = nature du contenu analysé associé. * * error = indication éventuelle en cas d'échec. [OUT] * * * * Description : Définit ou ouvre une archive d'éléments utilisateur. * @@ -338,7 +469,7 @@ static void g_cdb_archive_finalize(GCdbArchive *archive) * * ******************************************************************************/ -GCdbArchive *g_cdb_archive_new(const char *basedir, const char *tmpdir, const rle_string *hash, DBError *error) +GCdbArchive *g_cdb_archive_new(const char *basedir, const char *tmpdir, const rle_string *hash, const rle_string *class, DBError *error) { GCdbArchive *result; /* Adresse à retourner */ int ret; /* Retour d'un appel */ @@ -347,13 +478,16 @@ GCdbArchive *g_cdb_archive_new(const char *basedir, const char *tmpdir, const rl result = g_object_new(G_TYPE_CDB_ARCHIVE, NULL); dup_into_rle_string(&result->hash, get_rle_string(hash)); + dup_into_rle_string(&result->class, get_rle_string(class)); *error = DBE_SYS_ERROR; /* Chemin de l'archive */ result->filename = strdup(basedir); - result->filename = stradd(result->filename, hash->data); + result->filename = stradd(result->filename, get_rle_string(hash)); + result->filename = stradd(result->filename, "-"); + result->filename = stradd(result->filename, get_rle_string(class)); result->filename = stradd(result->filename, ".cdb.tar.xz"); if (!mkpath(result->filename)) @@ -679,18 +813,26 @@ DBError g_cdb_archive_write(const GCdbArchive *archive) * * * Paramètres : archive = informations quant à l'archive à consulter. * * hash = empreinte extérieure à comparer. * +* class = nature du contenu analysé. * * * -* Description : Détermine si une empreinte correspond à celle d'une archive. * +* Description : Détermine l'archive correspond à une cible recherchée. * * * -* Retour : Résultat de la comparaison : -1, 0 ou 1. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -int g_cdb_archive_compare_hash(const GCdbArchive *archive, const rle_string *hash) +bool g_cdb_archive_compare_is_suitable_for(const GCdbArchive *archive, const rle_string *hash, const rle_string *class) { - return cmp_rle_string(&archive->hash, hash); + bool result; /* Bilan à retourner */ + + result = (cmp_rle_string(&archive->hash, hash) == 0); + + if (result) + result = (cmp_rle_string(&archive->class, class) == 0); + + return result; } @@ -867,7 +1009,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")); @@ -896,6 +1038,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 */ @@ -912,20 +1056,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; } @@ -978,7 +1140,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: @@ -988,17 +1150,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; @@ -1007,7 +1164,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); @@ -1016,7 +1173,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); @@ -1057,10 +1214,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; @@ -1079,7 +1236,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); @@ -1091,10 +1248,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; @@ -1103,10 +1262,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; @@ -1225,6 +1384,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; @@ -1268,6 +1438,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); @@ -1291,40 +1467,100 @@ static void *g_cdb_archive_process(GCdbArchive *archive) * * ******************************************************************************/ +static LoadingStatusHint g_cdb_archive_compute_loading_hint(GCdbArchive *archive) +{ + LoadingStatusHint result; /* Statut à retourner */ + + + // Try + // g_mutex_lock(&archive->loading_access); + + + + // cnt_file + + if (archive->cnt_file == NULL) + result = LSH_NEED_CONTENT; + + else + result = LSH_NEED_FORMAT; + + + + + + return result; + +} + + +/****************************************************************************** +* * +* 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é */ + packed_buffer_t out_pbuf; /* Tampon d'émission */ + LoadingStatusHint hint; /* Statut de chargement */ + bool status; /* Bilan de lecture initiale */ + + client = create_cdb_client(fd, peer_name, user); /** - * 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. + * Le verrou encadrant les évolutions des contenus initiaux doit englober + * l'extension de la liste des clients. * - * - 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. + * En effet, une évolution partielle peut intervenir dans la fonction + * g_cdb_archive_process(), à un moment au seul le verrou dans les + * évolutions sera posé (g_cdb_archive_set_content() par exemple). * - * 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. + * Or g_cdb_archive_compute_loading_hint() doit fournir ici un état qui ne + * varie pas entre le calcul et l'envoi. Donc verrous sur les clients et + * l'état de l'archive doivent englover l'ensemble des traitements ci-après. */ + g_mutex_lock(&archive->loading_access); + g_mutex_lock(&archive->clients_access); - archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client)); + hint = g_cdb_archive_compute_loading_hint(archive); + + if (hint != LSH_READY) + hint = (archive->count == 0 ? hint : LSH_ON_WAIT_LIST); + + init_packed_buffer(&out_pbuf); + + status = craft_server_short_answer(DBC_LOADING_STATUS, hint, &out_pbuf); + + if (status) + status = ssl_send_packed_buffer(&out_pbuf, fd); + + exit_packed_buffer(&out_pbuf); + + if (status) + { + archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client *)); - client = &archive->clients[archive->count - 1]; + archive->clients[archive->count - 1] = client; - client->tls_fd = fd; - client->peer_name = strdup(peer_name); - client->user = strdup(user); + } g_mutex_unlock(&archive->clients_access); + g_mutex_unlock(&archive->loading_access); + } @@ -1343,20 +1579,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 *)); } @@ -1407,7 +1638,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); @@ -1533,10 +1764,10 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *archive, packed_buff /****************************************************************************** * * * Paramètres : cmd = commande à l'origine d'un traitement. * -* error = bilan de traitement à communiquer. * +* value = valeur à communiquer. * * out_pbuf = paquet à consituer pour un retour au client. [OUT]* * * -* Description : Prépare la réponse à envoyer à un client connecté. * +* Description : Prépare une courte réponse à envoyer à un client connecté. * * * * Retour : Indication pour le maintien de la communication. * * * @@ -1544,7 +1775,7 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *archive, packed_buff * * ******************************************************************************/ -static bool setup_server_answer(DBCommand cmd, DBError error, packed_buffer_t *out_pbuf) +static bool craft_server_short_answer(DBCommand cmd, uleb128_t value, packed_buffer_t *out_pbuf) { bool result; /* Bilan à retourner */ @@ -1553,7 +1784,7 @@ static bool setup_server_answer(DBCommand cmd, DBError error, packed_buffer_t *o result = extend_packed_buffer(out_pbuf, (uint32_t []) { cmd }, sizeof(uint32_t), true); if (result) - result = extend_packed_buffer(out_pbuf, (uint32_t []) { error }, sizeof(uint32_t), true); + result = pack_uleb128((uleb128_t []){ value }, out_pbuf); return result; @@ -1587,6 +1818,7 @@ static bool g_cdb_archive_set_content(GCdbArchive *archive, packed_buffer_t *in_ const gchar *hash; /* Empreinte de ce contenu */ int fd; /* Flux ouvert en écriture */ bool status; /* Bilan d'une écriture */ + LoadingStatusHint hint; /* Statut de chargement */ result = true; error = DBE_NONE; @@ -1687,7 +1919,15 @@ static bool g_cdb_archive_set_content(GCdbArchive *archive, packed_buffer_t *in_ /* Formulation de la réponse */ - result = setup_server_answer(DBC_SET_CONTENT, error, out_pbuf); + result = craft_server_short_answer(DBC_SET_CONTENT, error, out_pbuf); + + if (result && error == DBE_NONE) + { + hint = g_cdb_archive_compute_loading_hint(archive); + + result = craft_server_short_answer(DBC_LOADING_STATUS, hint, out_pbuf); + + } free_and_exit: diff --git a/src/analysis/db/cdb.h b/src/analysis/db/cdb.h index b2c3fc3..7a557f2 100644 --- a/src/analysis/db/cdb.h +++ b/src/analysis/db/cdb.h @@ -54,7 +54,7 @@ typedef struct _GCdbArchiveClass GCdbArchiveClass; GType g_cdb_archive_get_type(void); /* Prépare un client pour une connexion à une BD. */ -GCdbArchive *g_cdb_archive_new(const char *, const char *, const rle_string *, DBError *); +GCdbArchive *g_cdb_archive_new(const char *, const char *, const rle_string *, const rle_string *, DBError *); /* Construit un chemin pour un fichier propre à l'archive. */ char *g_cdb_archive_get_tmp_filename(const GCdbArchive *, const char *); @@ -62,8 +62,8 @@ char *g_cdb_archive_get_tmp_filename(const GCdbArchive *, const char *); /* Enregistre une archive avec tous les éléments à conserver. */ DBError g_cdb_archive_write(const GCdbArchive *); -/* Détermine si une empreinte correspond à celle d'une archive. */ -int g_cdb_archive_compare_hash(const GCdbArchive *, const rle_string *); +/* Détermine l'archive correspond à une cible recherchée. */ +bool g_cdb_archive_compare_is_suitable_for(const GCdbArchive *, const rle_string *, const rle_string *); diff --git a/src/analysis/db/items/Makefile.am b/src/analysis/db/items/Makefile.am index b9ce117..f8f70d5 100644 --- a/src/analysis/db/items/Makefile.am +++ b/src/analysis/db/items/Makefile.am @@ -7,18 +7,9 @@ libanalysisdbitems_la_SOURCES = \ move.h move.c \ switcher.h switcher.c -libanalysisdbitems_la_LIBADD = - -libanalysisdbitems_la_LDFLAGS = +libanalysisdbitems_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBSQLITE_CFLAGS) devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) dev_HEADERS = $(libanalysisdbitems_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE_CFLAGS) - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) - -SUBDIRS = diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index da7a4c0..fb27f60 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -39,9 +39,9 @@ #include "../../human/asm/lang.h" #include "../../../common/array.h" #include "../../../common/extstr.h" +#include "../../../core/columns.h" #include "../../../glibext/gbinarycursor.h" #include "../../../glibext/linegen-int.h" -#include "../../../gtkext/gtkblockdisplay.h" diff --git a/src/analysis/db/items/move.c b/src/analysis/db/items/move.c index af1c8c1..e4f503b 100644 --- a/src/analysis/db/items/move.c +++ b/src/analysis/db/items/move.c @@ -35,9 +35,13 @@ #include "../collection-int.h" #include "../item-int.h" -#include "../../../gui/core/global.h" +#ifdef INCLUDE_GTK_SUPPORT +# include "../../../gui/core/global.h" +#endif #include "../../../glibext/gbinarycursor.h" -#include "../../../glibext/gloadedpanel.h" +#ifdef INCLUDE_GTK_SUPPORT +# include "../../../glibext/gloadedpanel.h" +#endif @@ -410,6 +414,8 @@ static char *g_db_move_build_label(GDbMove *move) static bool g_db_move_run(const GDbMove *move, GLineCursor *cursor) { +#ifdef INCLUDE_GTK_SUPPORT + GLoadedPanel *panel; /* Afficheur effectif de code */ typedef struct _move_params @@ -465,6 +471,8 @@ static bool g_db_move_run(const GDbMove *move, GLineCursor *cursor) if (panel != NULL) g_object_unref(G_OBJECT(panel)); +#endif + return true; } diff --git a/src/analysis/db/misc/Makefile.am b/src/analysis/db/misc/Makefile.am index 6d4af6c..fc3cab2 100644 --- a/src/analysis/db/misc/Makefile.am +++ b/src/analysis/db/misc/Makefile.am @@ -6,18 +6,7 @@ libanalysisdbmisc_la_SOURCES = \ snapshot.h snapshot.c \ timestamp.h timestamp.c -libanalysisdbmisc_la_LIBADD = - -libanalysisdbmisc_la_LDFLAGS = - devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) dev_HEADERS = $(libanalysisdbmisc_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE_CFLAGS) - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) - -SUBDIRS = diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index 17263c8..7707058 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -76,14 +76,21 @@ typedef enum _ServerPrivLevels +/** + * Précisions pour la commande DBC_LOADING_STATUS. + */ + + /* Eléments de base nécessaires */ -typedef enum _RequiredBasics +typedef enum _LoadingStatusHint { - RBS_NONE = 0x0, /* (Plus) rien n'est requis */ - RBS_CONTENT = 0x1, /* Contenu binaire à analyser */ - RBS_LOADED = 0x2, /* Contenu binaire analysé */ + LSH_READY = 0, /* (Plus) rien n'est requis */ + LSH_ON_WAIT_LIST = 1, /* Concurrence des connexions */ + LSH_NEED_CONTENT = 2, /* Suppléments nécessaires */ + LSH_NEED_FORMAT = 3, /* Suppléments nécessaires */ + LSH_NEED_ARCH = 4, /* Suppléments nécessaires */ -} RequiredBasics; +} LoadingStatusHint; @@ -135,6 +142,8 @@ typedef enum _DBAction */ typedef enum _DBCommand { + /* ------------------------- Commandes à portée générale ------------------------- */ + /** * Le client envoie un tout premier paquet de la forme suivante : * @@ -176,6 +185,18 @@ typedef enum _DBCommand /* ------------------------ Commandes pour analyste ------------------------ */ /** + * Gestion de la commande 'DBC_LOADING_STATUS'. + * + * Le serveur envoie un statut de prise en charge au début d'une connexion : + * + * [ Indication du serveur : DBC_LOADING_STATUS] + * [ Statut courant ; cf. LoadingStatusHint ] + * + */ + + DBC_LOADING_STATUS, /* Indications initiales */ + + /** * Gestion de la commande 'DBC_SET_CONTENT'. * * Le client connecté envoie un paquet de la forme suivante : diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c index b08962c..79d5df1 100644 --- a/src/analysis/db/server.c +++ b/src/analysis/db/server.c @@ -1028,7 +1028,7 @@ static GServerBackend *g_hub_server_handle_admin(GHubServer *server, packed_buff if (has_more_data_in_packed_buffer(in_pbuf)) { - log_variadic_message(LMT_ERROR, _("The client from '%s' provided to much data!"), peer_name); + log_variadic_message(LMT_ERROR, _("The client from '%s' provided too much data!"), peer_name); result = NULL; @@ -1074,6 +1074,7 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu { GCdbArchive *result; /* Support de suivi à retourner*/ rle_string hash; /* Empreinte du binaire visé */ + rle_string class; /* Nature du contenu visé */ bool status; /* Bilan d'une opération */ GList *iter; /* Boucle de parcours */ GCdbArchive *archive; /* Destinataire final du client*/ @@ -1087,6 +1088,8 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu /* Fin de réception des données envoyées */ + setup_empty_rle_string(&hash); + status = unpack_rle_string(&hash, in_pbuf); if (!status) { @@ -1097,13 +1100,28 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu if (is_rle_string_empty(&hash)) { log_variadic_message(LMT_ERROR, _("The submitted binary hash from '%s' is empty!"), peer_name); - goto wrong_receiving; + goto wrong_receiving_0; + } + + setup_empty_rle_string(&class); + + status = unpack_rle_string(&class, in_pbuf); + if (!status) + { + log_variadic_message(LMT_ERROR, _("Error while getting the content class from '%s'..."), peer_name); + goto wrong_receiving_0; + } + + if (is_rle_string_empty(&class)) + { + log_variadic_message(LMT_ERROR, _("The submitted content class from '%s' is empty!"), peer_name); + goto wrong_receiving_1; } if (has_more_data_in_packed_buffer(in_pbuf)) { - log_variadic_message(LMT_ERROR, _("The client from '%s' provided to much data!"), peer_name); - goto wrong_receiving; + log_variadic_message(LMT_ERROR, _("The client from '%s' provided too much data!"), peer_name); + goto wrong_receiving_1; } /* Recherche d'un support existant adapté */ @@ -1114,7 +1132,7 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu { archive = G_CDB_ARCHIVE(iter->data); - if (g_cdb_archive_compare_hash(archive, &hash) == 0) + if (g_cdb_archive_compare_is_suitable_for(archive, &hash, &class)) break; } @@ -1137,7 +1155,7 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu tmpdir = strdup(server->working); tmpdir = stradd(tmpdir, "tmp" G_DIR_SEPARATOR_S); - result = g_cdb_archive_new(basedir, tmpdir, &hash, error); + result = g_cdb_archive_new(basedir, tmpdir, &hash, &class, error); free(tmpdir); free(basedir); @@ -1146,7 +1164,11 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu } - wrong_receiving: + wrong_receiving_1: + + exit_rle_string(&class); + + wrong_receiving_0: exit_rle_string(&hash); |