diff options
Diffstat (limited to 'src/analysis/db')
-rwxr-xr-x | src/analysis/db/Makefile.am | 10 | ||||
-rw-r--r-- | src/analysis/db/bookmark.c | 69 | ||||
-rw-r--r-- | src/analysis/db/bookmark.h | 41 | ||||
-rw-r--r-- | src/analysis/db/cdb.c | 427 | ||||
-rw-r--r-- | src/analysis/db/cdb.h | 19 | ||||
-rw-r--r-- | src/analysis/db/client.c | 272 | ||||
-rw-r--r-- | src/analysis/db/client.h | 13 | ||||
-rw-r--r-- | src/analysis/db/collection.c | 491 | ||||
-rw-r--r-- | src/analysis/db/collection.h | 81 | ||||
-rw-r--r-- | src/analysis/db/core.c | 6 | ||||
-rw-r--r-- | src/analysis/db/item-int.h | 68 | ||||
-rw-r--r-- | src/analysis/db/item.c | 356 | ||||
-rw-r--r-- | src/analysis/db/item.h | 68 | ||||
-rw-r--r-- | src/analysis/db/items/Makefile.am | 17 | ||||
-rw-r--r-- | src/analysis/db/items/bookmark.c | 416 | ||||
-rw-r--r-- | src/analysis/db/items/bookmark.h | 79 | ||||
-rw-r--r-- | src/analysis/db/items/comment.c | 398 | ||||
-rw-r--r-- | src/analysis/db/items/comment.h | 77 | ||||
-rwxr-xr-x | src/analysis/db/misc/Makefile.am | 16 | ||||
-rw-r--r-- | src/analysis/db/misc/rlestr.c | 345 | ||||
-rw-r--r-- | src/analysis/db/misc/rlestr.h | 83 | ||||
-rw-r--r-- | src/analysis/db/protocol.h | 101 | ||||
-rw-r--r-- | src/analysis/db/server.c | 262 |
23 files changed, 3423 insertions, 292 deletions
diff --git a/src/analysis/db/Makefile.am b/src/analysis/db/Makefile.am index ef98a24..6852821 100755 --- a/src/analysis/db/Makefile.am +++ b/src/analysis/db/Makefile.am @@ -2,15 +2,19 @@ noinst_LTLIBRARIES = libanalysisdb.la libanalysisdb_la_SOURCES = \ - bookmark.h bookmark.c \ cdb.h cdb.c \ client.h client.c \ collection.h collection.c \ core.h core.c \ + item-int.h \ + item.h item.c \ protocol.h \ server.h server.c -libanalysisdb_la_LIBADD = +libanalysisdb_la_LIBADD = \ + items/libanalysisdbitems.la \ + misc/libanalysisdbmisc.la + libanalysisdb_la_LDFLAGS = @@ -19,4 +23,4 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = +SUBDIRS = items misc diff --git a/src/analysis/db/bookmark.c b/src/analysis/db/bookmark.c deleted file mode 100644 index 9a46a0d..0000000 --- a/src/analysis/db/bookmark.c +++ /dev/null @@ -1,69 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * bookmark.h - prototypes pour la gestion des signets au sein d'un binaire - * - * Copyright (C) 2014 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * OpenIDA 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. - * - * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "bookmark.h" - - -#include <malloc.h> - - - - - - -/****************************************************************************** -* * -* Paramètres : db = accès à la base de données. * -* * -* Description : Crée la table des signets dans une base de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool create_bookmark_db_table(sqlite3 *db) -{ - char *sql; /* Requête à exécuter */ - int ret; /* Bilan de la création */ - char *msg; /* Message d'erreur */ - - sql = "CREATE TABLE Bookmarks (" \ - "id INT PRIMARY KEY NOT NULL, " \ - "user TEXT NOT NULL, " \ - "created INT NOT NULL, " \ - "address INT NOT NULL, " \ - "comment TEXT" \ - ");"; - - ret = sqlite3_exec(db, sql, NULL, NULL, &msg); - if (ret != SQLITE_OK) - { - fprintf(stderr, "sqlite3_exec(): %s\n", msg); - sqlite3_free(msg); - } - - return (ret == SQLITE_OK); - -} diff --git a/src/analysis/db/bookmark.h b/src/analysis/db/bookmark.h deleted file mode 100644 index 5308e92..0000000 --- a/src/analysis/db/bookmark.h +++ /dev/null @@ -1,41 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * bookmark.h - prototypes pour la gestion des signets au sein d'un binaire - * - * Copyright (C) 2014 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * OpenIDA 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. - * - * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _ANALYSIS_DB_BOOKMARK_H -#define _ANALYSIS_DB_BOOKMARK_H - - - -#include <sqlite3.h> -#include <stdbool.h> - - - -/* Crée la table des signets dans une base de données. */ -bool create_bookmark_db_table(sqlite3 *); - - - - - -#endif /* _ANALYSIS_DB_BOOKMARK_H */ diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 7e530ac..563aa40 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -28,7 +28,11 @@ #include <archive_entry.h> #include <errno.h> #include <fcntl.h> +#include <limits.h> #include <malloc.h> +#include <poll.h> +#include <pthread.h> +#include <signal.h> #include <stdio.h> #include <sqlite3.h> #include <string.h> @@ -39,8 +43,9 @@ #include <config.h> -#include "bookmark.h" +#include "collection.h" #include "protocol.h" +#include "items/bookmark.h" #include "../../common/cpp.h" #include "../../common/extstr.h" #include "../../common/io.h" @@ -53,13 +58,26 @@ #define ARCHIVE_RBUF_SIZE 2048 + + + +/* Informations relatives à un client */ +typedef struct _cdb_client +{ + int fd; /* Canal de communication */ + rle_string user; /* Utilisateur à l'autre bout */ + + uint64_t last_time; /* Date de dernier envoi */ + +} cdb_client; + + /* Description d'une archive d'éléments utilisateur (instance) */ struct _GCdbArchive { GObject parent; /* A laisser en premier */ - char hash[65]; /* Empreinte SHA256 */ - + rle_string hash; /* Empreinte cryptographique */ char *filename; /* Chemin d'accès à l'archive */ @@ -71,6 +89,15 @@ struct _GCdbArchive sqlite3 *db; /* Base de données à manipuler */ + GList *collections; /* Ensemble de modifications */ + + cdb_client *clients; /* Connexions en place */ + size_t count; /* Quantité de clients */ + GMutex clients_access; /* Verrou pour l'accès */ + + GThread *process; /* Procédure de traitement */ + pthread_t process_id; /* Identifiant de la procédure */ + }; /* Description d'une archive d'éléments utilisateur (classe) */ @@ -101,7 +128,8 @@ static bool g_cdb_archive_read(GCdbArchive *); /* Crée la description XML correspondant à l'archive. */ -static bool g_cdb_archive_create_xml_desc(GCdbArchive *, const core_db_info *); +static bool g_cdb_archive_create_xml_desc(GCdbArchive *, const rle_string *); + @@ -112,6 +140,22 @@ static bool g_cdb_archive_create_db(const GCdbArchive *, const core_db_info *); +/////////////////////////: + + +/* Crée et remplit les collections à partir de leurs bases. */ +static bool g_cdb_archive_load_collections(GCdbArchive *); + +/* Réagit à une modification au sein d'une collection donnée. */ +static void on_collection_changed(GDbCollection *, DBAction, GDbItem *, GCdbArchive *); + +/* Assure le traitement des requêtes de clients. */ +static void *g_cdb_archive_process(GCdbArchive *); + + + + + /* Indique le type défini pour une une archive d'éléments utilisateur. */ G_DEFINE_TYPE(GCdbArchive, g_cdb_archive, G_TYPE_OBJECT); @@ -155,6 +199,7 @@ static void g_cdb_archive_class_init(GCdbArchiveClass *klass) static void g_cdb_archive_init(GCdbArchive *archive) { + g_mutex_init(&archive->clients_access); } @@ -203,19 +248,21 @@ static void g_cdb_archive_finalize(GCdbArchive *archive) /****************************************************************************** * * -* Paramètres : local = indique si l'enregistrement est local ou non. * -* client = flux ouvert en lecture pour les informations utiles.* -* info = informations de base associées à la requête. * +* Paramètres : owner = description humaine du serveur d'accueil. * +* hash = empreinte du binaire à représenter. * +* user = désignation d'un éventuel nouveau créateur. * +* error = indication éventuelle en cas d'échec. [OUT] * * * * Description : Définit ou ouvre une archive d'éléments utilisateur. * * * * Retour : Structure mise en plae ou NULL en cas d'échec. * * * -* Remarques : - * +* Remarques : Les chaînes sont assurées d'être non vides ; la procédure * +* assume un transfert de propriété. * * * ******************************************************************************/ -GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info *info) +GCdbArchive *g_cdb_archive_new(const char *owner, const rle_string *hash, const rle_string *user, DBError *error) { GCdbArchive *result; /* Adresse à retourner */ char *suffix; /* Fin du nom de fichier */ @@ -224,19 +271,14 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info result = g_object_new(G_TYPE_CDB_ARCHIVE, NULL); - - - strcpy(result->hash, info->hash); - - - + dup_rle_string(&result->hash, hash); /* Chemin de l'archive */ suffix = strdup("chrysalide" G_DIR_SEPARATOR_S); - suffix = stradd(suffix, local ? "local" : "server"); + suffix = stradd(suffix, owner); suffix = stradd(suffix, G_DIR_SEPARATOR_S); - suffix = stradd(suffix, result->hash); + suffix = stradd(suffix, hash->data); suffix = stradd(suffix, ".tar.xz"); result->filename = get_xdg_config_dir(suffix); @@ -253,7 +295,7 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info if (result->xml_desc[strlen(result->xml_desc) - 1] != G_DIR_SEPARATOR) result->xml_desc = stradd(result->xml_desc, G_DIR_SEPARATOR_S); - result->xml_desc = stradd(result->xml_desc, result->hash); + result->xml_desc = stradd(result->xml_desc, result->hash.data); result->xml_desc = stradd(result->xml_desc, "_desc.xml"); result->sql_db = strdup(g_get_tmp_dir()); @@ -261,7 +303,7 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info if (result->sql_db[strlen(result->sql_db) - 1] != G_DIR_SEPARATOR) result->sql_db = stradd(result->sql_db, G_DIR_SEPARATOR_S); - result->sql_db = stradd(result->sql_db, result->hash); + result->sql_db = stradd(result->sql_db, result->hash.data); result->sql_db = stradd(result->sql_db, "_db.sql"); /* Création de l'archive si elle n'existe pas */ @@ -273,8 +315,8 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info /* Le soucis ne vient pas de l'absence du fichier... */ if (errno != ENOENT) goto gcan_error; - g_cdb_archive_create_xml_desc(result, info); - g_cdb_archive_create_db(result, info); + g_cdb_archive_create_xml_desc(result, user); + g_cdb_archive_create_db(result, NULL); if (!g_cdb_archive_write(result)) goto gcan_error; @@ -288,6 +330,11 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info if (!g_cdb_archive_read(result) && 0) goto gcan_error; + /* Chargement des éléments sauvegardés */ + + if (!g_cdb_archive_load_collections(result)) + goto gcan_error; + return result; gcan_error: @@ -301,7 +348,7 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info /****************************************************************************** * * -* Paramètres : archive = information quant à l'archive à interpréter. * +* Paramètres : archive = informations quant à l'archive à interpréter. * * * * Description : Ouvre une archive avec tous les éléments à conserver. * * * @@ -416,7 +463,7 @@ static bool g_cdb_archive_read(GCdbArchive *archive) /****************************************************************************** * * -* Paramètres : archive = information quant à l'archive à créer. * +* Paramètres : archive = informations quant à l'archive à créer. * * * * Description : Enregistre une archive avec tous les éléments à conserver. * * * @@ -497,9 +544,24 @@ bool g_cdb_archive_write(const GCdbArchive *archive) } +/****************************************************************************** +* * +* Paramètres : archive = informations quant à l'archive à consulter. * +* hash = empreinte extérieure à comparer. * +* * +* Description : Détermine si une empreinte correspond à celle d'une archive. * +* * +* Retour : Résultat de la comparaison : -1, 0 ou 1. * +* * +* Remarques : - * +* * +******************************************************************************/ +int g_cdb_archive_compare_hash(const GCdbArchive *archive, const rle_string *hash) +{ + return cmp_rle_string(&archive->hash, hash); - +} @@ -514,7 +576,7 @@ bool g_cdb_archive_write(const GCdbArchive *archive) /****************************************************************************** * * * Paramètres : archive = archive à constituer. * -* info = informations de base associées à la requête. * +* user = désignation d'un éventuel nouveau créateur. * * * * Description : Crée la description XML correspondant à l'archive. * * * @@ -524,7 +586,7 @@ bool g_cdb_archive_write(const GCdbArchive *archive) * * ******************************************************************************/ -static bool g_cdb_archive_create_xml_desc(GCdbArchive *archive, const core_db_info *info) +static bool g_cdb_archive_create_xml_desc(GCdbArchive *archive, const rle_string *user) { bool result; /* Bilan à retourner */ char tmp[sizeof(STR(ULLONG_MAX))]; /* Stockage temporaire */ @@ -536,12 +598,15 @@ static bool g_cdb_archive_create_xml_desc(GCdbArchive *archive, const core_db_in "/ChrysalideBinary/Version", PACKAGE_VERSION); result &= add_content_to_node(archive->xdoc, archive->context, - "/ChrysalideBinary/Hash", archive->hash); + "/ChrysalideBinary/Protocol", XSTR(CDB_PROTOCOL_VERSION)); result &= add_content_to_node(archive->xdoc, archive->context, - "/ChrysalideBinary/Creation/Author", "**me**"); + "/ChrysalideBinary/Hash", archive->hash.data); - snprintf(tmp, sizeof(tmp), "%" PRIu64, (uint64_t)10ull); + result &= add_content_to_node(archive->xdoc, archive->context, + "/ChrysalideBinary/Creation/Author", user->data); + + snprintf(tmp, sizeof(tmp), "%" PRIu64, (uint64_t)time(NULL)); result &= add_content_to_node(archive->xdoc, archive->context, "/ChrysalideBinary/Creation/Date", tmp); @@ -600,3 +665,307 @@ static bool g_cdb_archive_create_db(const GCdbArchive *archive, const core_db_in return result; } + + + + + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/* ACCES A LA BASE DE DONNEES SQL */ +/* ACCES A LA BASE DE DONNEES SQL */ +/* ---------------------------------------------------------------------------------- */ + + + + + + +/****************************************************************************** +* * +* Paramètres : archive = archive dont les collections sont à initialiser. * +* * +* Description : Crée et remplit les collections à partir de leurs bases. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_cdb_archive_load_collections(GCdbArchive *archive) +{ + GList *iter; /* Boucle de parcours */ + + archive->collections = create_collections_list(); + + for (iter = g_list_first(archive->collections); + iter != NULL; + iter = g_list_next(iter)) + { + g_signal_connect(iter->data, "content-changed", G_CALLBACK(on_collection_changed), archive); + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = collection dont le contenu a évolué. * +* action = type d'évolution rencontrée. * +* item = élément ajouté, modifié ou supprimé. * +* archive = centralisation de tous les savoirs. * +* * +* Description : Réagit à une modification au sein d'une collection donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_collection_changed(GDbCollection *collec, DBAction action, GDbItem *item, GCdbArchive *archive) +{ + size_t i; /* Boucle de parcours */ + bool status; /* Bilan d'un envoi de retour */ + + g_mutex_lock(&archive->clients_access); + + for (i = 0; i < archive->count; i++) + { + status = g_db_collection_send(collec, archive->clients[i].fd, action, item); + + if (!status) + { + /* TODO : close() */ + } + + } + + g_mutex_unlock(&archive->clients_access); + + printf("CHANGED !!\n"); + + + + +} + + +/****************************************************************************** +* * +* Paramètres : archive = centralisation de tous les savoirs. * +* * +* Description : Assure le traitement des requêtes de clients. * +* * +* Retour : NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void *g_cdb_archive_process(GCdbArchive *archive) +{ + struct pollfd *fds; /* Surveillance des flux */ + nfds_t nfds; /* Quantité de ces flux */ + nfds_t i; /* Boucle de parcours */ + int ret; /* Bilan d'un appel */ + uint32_t val32; /* Valeur sur 32 bits */ + bool status; /* Bilan de lecture initiale */ + uint32_t command; /* Commande de la requête */ + GDbCollection *collec; /* Collection visée au final */ + + void interrupt_poll_with_sigusr1(int sig) { }; + + signal(SIGUSR1, interrupt_poll_with_sigusr1); + + archive->process_id = pthread_self(); + + fds = NULL; + + while (1) + { + /* Reconstitution d'une liste à jour */ + + g_mutex_lock(&archive->clients_access); + + nfds = archive->count; + fds = (struct pollfd *)realloc(fds, nfds * sizeof(struct pollfd)); + + for (i = 0; i < nfds; i++) + { + fds[i].fd = archive->clients[i].fd; + fds[i].events = POLLIN | POLLPRI; + } + + if (nfds == 0) + goto gcap_no_more_clients; + + g_mutex_unlock(&archive->clients_access); + + /* Lancement d'une phase de surveillance */ + + printf("(%p) POLL %d\n", archive, nfds); + + ret = poll(fds, nfds, -1); + if (ret == -1) + { + if (errno == EINTR) continue; + + perror("poll"); + break; + + } + + /* Traitement des requêtes reçues */ + + for (i = 0; i < nfds; i++) + { + /* Le canal est fermé, une sortie doit être demandée... */ + if (fds[i].revents & POLLNVAL) + goto gcap_bad_exchange; + + /* Données présentes en entrée */ + if (fds[i].revents & (POLLIN | POLLPRI)) + { + status = safe_recv(fds[i].fd, &val32, sizeof(uint32_t), 0); + if (!status) goto gcap_bad_exchange; + + command = be32toh(val32); + + switch (command) + { + case DBC_COLLECTION: + + status = safe_recv(fds[i].fd, &val32, sizeof(uint32_t), 0); + if (!status) goto gcap_bad_exchange; + + collec = find_collection_in_list(archive->collections, be32toh(val32)); + if (collec == NULL) goto gcap_bad_exchange; + + status = g_db_collection_recv(collec, fds[i].fd); + if (!status) goto gcap_bad_exchange; + + printf("## CDB ## Got something for collection %p...\n", collec); + + //GDbCollection *find_collection_in_list(GList *, uint32_t); + + //static GGenConfig *find_collection_in_list(GList *list, uint32_t id) + + break; + + default: + printf("bad command :: 0x%08x\n", command); + goto gcap_bad_exchange; + break; + + } + + continue; + + gcap_bad_exchange: + + printf("Bad exchange...\n"); + + /* TODO : close conn */ + + ; + + + } + + } + + } + + /* On disparaît des écrans... */ + + g_mutex_lock(&archive->clients_access); + + gcap_no_more_clients: + + archive->process = NULL; + archive->process_id = 0; + + g_mutex_unlock(&archive->clients_access); + + if (fds != NULL) + free(fds); + + + return NULL; + +} + + + +/****************************************************************************** +* * +* Paramètres : archive = archive à connecter avec un utilisateur. * +* fd = canal de communication réseau ouvert. * +* user = désignation de l'utilisateur associé. * +* * +* Description : Associe un nouvel utilisateur à l'archive. * +* * +* Retour : Indication d'une éventuelle erreur lors de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +DBError g_cdb_archive_add_client(GCdbArchive *archive, int fd, const rle_string *user) +{ + + volatile pthread_t *process_id; /* Identifiant de la procédure */ + + + + + printf("Add '%s' for archive...\n", user->data); + + + g_mutex_lock(&archive->clients_access); + + /* Ajout dans la liste officielle */ + + archive->clients = (cdb_client *)realloc(archive->clients, ++archive->count * sizeof(cdb_client)); + + archive->clients[archive->count - 1].fd = fd; + dup_rle_string(&archive->clients[archive->count - 1].user, user); + + /* 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 */ + for (process_id = &archive->process_id; *process_id == 0; ); + + } + else + pthread_kill(archive->process_id, SIGUSR1); + + g_mutex_unlock(&archive->clients_access); + + /* Envoi des mises à jour au nouveau client... */ + + + /* TODO */ + + + + return DBE_NONE; + +} + + + diff --git a/src/analysis/db/cdb.h b/src/analysis/db/cdb.h index a093039..17327f5 100644 --- a/src/analysis/db/cdb.h +++ b/src/analysis/db/cdb.h @@ -29,8 +29,13 @@ #include <stdbool.h> +#include "protocol.h" +#include "misc/rlestr.h" + +////// #include "client.h" #include "core.h" +////////// @@ -52,11 +57,23 @@ 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(bool, GDbClient *, const core_db_info *); +GCdbArchive *g_cdb_archive_new(const char *, const rle_string *, const rle_string *, DBError *); /* Enregistre une archive avec tous les éléments à conserver. */ bool 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 *); + + + + + +/* Associe un nouvel utilisateur à l'archive. */ +DBError g_cdb_archive_add_client(GCdbArchive *, int, const rle_string *); + + + #endif /* _ANALYSIS_DB_CDB_H */ diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 946f202..4b807ae 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -33,6 +33,9 @@ #include "protocol.h" +#include "misc/rlestr.h" +#include "../../common/io.h" +#include "../../gui/panels/log.h" @@ -41,9 +44,12 @@ struct _GDbClient { GObject parent; /* A laisser en premier */ - int fd; - struct sockaddr_in addr; /* Adresse d'écoute */ + rle_string hash; /* Empreinte du binaire lié */ + GList *collections; /* Collections d'un binaire */ + int fd; /* Canal de communication */ + + GMutex sending_lock; /* Concurrence des envois */ GThread *update; /* Procédure de traitement */ }; @@ -118,7 +124,7 @@ static void g_db_client_init(GDbClient *client) /****************************************************************************** * * -* Paramètres : binary = instance d'objet GLib à traiter. * +* Paramètres : client = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -128,19 +134,19 @@ static void g_db_client_init(GDbClient *client) * * ******************************************************************************/ -static void g_db_client_finalize(GDbClient *binary) +static void g_db_client_finalize(GDbClient *client) { - //free(binary->filename); + unset_rle_string(&client->hash); - G_OBJECT_CLASS(g_db_client_parent_class)->finalize(G_OBJECT(binary)); + G_OBJECT_CLASS(g_db_client_parent_class)->finalize(G_OBJECT(client)); } /****************************************************************************** * * -* Paramètres : host = hôte à représenter pour le service. * -* port = port de connexion pour les clients. * +* Paramètres : hash = empreinte d'un binaire en cours d'analyse. * +* collections = ensemble de collections existantes. * * * * Description : Prépare un client pour une connexion à une BD. * * * @@ -150,28 +156,155 @@ static void g_db_client_finalize(GDbClient *binary) * * ******************************************************************************/ -GDbClient *g_db_client_new(const char *host, short port) +GDbClient *g_db_client_new(const char *hash, GDbCollection *collections) { GDbClient *result; /* Adresse à retourner */ - struct hostent *hp; /* Informations sur l'hôte */ result = g_object_new(G_TYPE_DB_CLIENT, NULL); + set_rle_string(&result->hash, hash); + result->collections = collections; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* host = hôte à représenter pour le service. * +* port = port de connexion pour les clients. * +* username = utilisateur effectuant les évolutions. * +* * +* Description : Démarre la connexion à la base de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_client_start(GDbClient *client, const char *host, unsigned short port, const char *username) +{ + struct hostent *hp; /* Informations sur l'hôte */ + struct sockaddr_in addr; /* Adresse de transmission */ + int ret; /* Bilan d'un appel */ + rle_string user; /* Nom d'utilisateur associé */ + uint32_t data; /* Mot de données lues */ + DBError error; /* Validation de la connexion */ + + /* Identification du serveur à contacter */ + hp = gethostbyname(host); - if (hp == NULL) goto gdsn_error; + if (hp == NULL) return false; - result->addr.sin_family = hp->h_addrtype; - memcpy(&result->addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); + addr.sin_family = hp->h_addrtype; + memcpy(&addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); - result->addr.sin_port = htons(port); + addr.sin_port = htons(port); - return result; + /* Création d'un canal de communication */ + + client->fd = socket(AF_INET, SOCK_STREAM, 0); + if (client->fd == -1) + { + perror("socket"); + return false; + } + + ret = connect(client->fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); + if (ret == -1) + { + perror("connect"); + goto gdcs_no_listening; + } - gdsn_error: + /* Préparation du nom d'utilisateur à diffuser */ - g_object_unref(G_OBJECT(result)); + init_rle_string(&user, username); - return NULL; + /** + * On réalise l'envoi initial ; le premier paquet doit contenir : + * - la commande 'DBC_HELO'. + * - le numéro de version du client. + * - l'empreinte du binaire analysé. + * - l'identifiant de l'utilisateur effectuant des modifications. + * + * Tout ceci est à synchroniser avec la fonction g_db_server_listener(). + */ + + if (!safe_send(client->fd, (uint32_t []) { htobe32(DBC_HELO) }, sizeof(uint32_t), MSG_MORE)) + goto gdcs_error; + + if (!safe_send(client->fd, (uint32_t []) { htobe32(CDB_PROTOCOL_VERSION) }, sizeof(uint32_t), MSG_MORE)) + goto gdcs_error; + + if (!send_rle_string(&client->hash, client->fd, MSG_MORE)) + goto gdcs_error; + + if (!send_rle_string(&user, client->fd, 0)) + goto gdcs_error; + + /** + * Le serveur doit répondre pour un message type : + * - la commande 'DBC_WELCOME'. + * - un identifiant d'erreur ('DBE_NONE' ou 'DBE_WRONG_VERSION'). + */ + + if (!safe_recv(client->fd, &data, sizeof(uint32_t), 0)) + goto gdcs_error; + + if (be32toh(data) != DBC_WELCOME) + { + log_variadic_message(LMT_ERROR, _("The server '%s:%hu' did not welcome us!"), host, port); + goto gdcs_error; + } + + if (!safe_recv(client->fd, &data, sizeof(uint32_t), 0)) + goto gdcs_error; + + error = be32toh(data); + + switch (error) + { + case DBE_NONE: + log_variadic_message(LMT_INFO, _("Connected to the server '%s:%hu'!"), host, port); + break; + + case DBE_WRONG_VERSION: + log_variadic_message(LMT_ERROR, _("The server '%s:%hu' does not use our protocol version (0x%08x)..."), + host, port, CDB_PROTOCOL_VERSION); + goto gdcs_error; + break; + + default: + log_variadic_message(LMT_ERROR, _("The server '%s:%hu' uses an unknown protocol..."), host, port); + goto gdcs_error; + break; + + } + + client->update = g_thread_try_new("cdb_client", (GThreadFunc)g_db_client_update, client, NULL); + if (client->update == NULL) + { + log_variadic_message(LMT_ERROR, _("Failed to start a listening thread for the server '%s:%hu'!"), + host, port); + goto gdcs_error; + } + + return true; + + gdcs_error: + + unset_rle_string(&user); + + gdcs_no_listening: + + close(client->fd); + client->fd = -1; + + return false; } @@ -192,6 +325,10 @@ static void *g_db_client_update(GDbClient *client) { struct pollfd fds; /* Surveillance des flux */ int ret; /* Bilan d'un appel */ + uint32_t val32; /* Valeur sur 32 bits */ + bool status; /* Bilan d'une opération */ + uint32_t command; /* Commande de la requête */ + GDbCollection *collec; /* Collection visée au final */ fds.fd = client->fd; fds.events = POLLIN | POLLPRI; @@ -209,16 +346,50 @@ static void *g_db_client_update(GDbClient *client) if (fds.revents & (POLLIN | POLLPRI)) { + status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0); + if (!status) goto gdcu_bad_exchange; + + command = be32toh(val32); + + switch (command) + { + case DBC_COLLECTION: + + status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0); + if (!status) goto gdcu_bad_exchange; + + collec = find_collection_in_list(client->collections, be32toh(val32)); + if (collec == NULL) goto gdcu_bad_exchange; + + status = g_db_collection_recv(collec, fds.fd); + if (!status) goto gdcu_bad_exchange; + + + + + printf("## CLIENT ## Got Something to read...\n"); + + break; + + } + + continue; + + gdcu_bad_exchange: + + printf("Bad reception...\n"); + + /* TODO : close conn */ + + ; - /* TODO */ - pause(); } } - g_db_client_stop(client); + //g_db_client_stop(client); return NULL; @@ -229,39 +400,44 @@ static void *g_db_client_update(GDbClient *client) * * * Paramètres : client = client pour les accès distants à manipuler. * * * -* Description : Démarre la connexion à la base de données. * +* Description : Arrête la connexion à la base de données. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool g_db_client_start(GDbClient *client) +void g_db_client_stop(GDbClient *client) { - int ret; /* Bilan d'un appel */ + if (client->fd != -1) + return; - client->fd = socket(AF_INET, SOCK_STREAM, 0); - if (client->fd == -1) - { - perror("socket"); - return false; - } + close(client->fd); + client->fd = -1; - ret = connect(client->fd, (struct sockaddr *)&client->addr, sizeof(struct sockaddr_in)); - if (ret == -1) - { - perror("connect"); - close(client->fd); - client->fd = -1; - return false; - } + g_thread_join(client->update); - //client->update = g_thread_new("cdb_listener", (GThreadFunc)g_db_client_update, client); +} - send(client->fd, "A", 1, 0); - return true; +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* * +* Description : Identifie le canal de communication pour envois au serveur. * +* * +* Retour : Descripteur de flux normalement ouvert. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_db_client_get_fd(GDbClient *client) +{ + g_mutex_lock(&client->sending_lock); + + return client->fd; } @@ -270,7 +446,7 @@ bool g_db_client_start(GDbClient *client) * * * Paramètres : client = client pour les accès distants à manipuler. * * * -* Description : Arrête la connexion à la base de données. * +* Description : Marque le canal de communication comme disponible. * * * * Retour : - * * * @@ -278,14 +454,8 @@ bool g_db_client_start(GDbClient *client) * * ******************************************************************************/ -void g_db_client_stop(GDbClient *client) +void g_db_client_put_fd(GDbClient *client) { - if (client->fd != -1) - return; - - close(client->fd); - client->fd = -1; - - g_thread_join(client->update); + g_mutex_unlock(&client->sending_lock); } diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h index e57a5b6..a1a9f8e 100644 --- a/src/analysis/db/client.h +++ b/src/analysis/db/client.h @@ -29,6 +29,9 @@ #include <stdbool.h> +#include "collection.h" + + #define G_TYPE_DB_CLIENT g_db_client_get_type() #define G_DB_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_client_get_type(), GDbClient)) @@ -48,14 +51,20 @@ typedef struct _GDbClientClass GDbClientClass; GType g_db_client_get_type(void); /* Prépare un client pour une connexion à une BD. */ -GDbClient *g_db_client_new(const char *, short); +GDbClient *g_db_client_new(const char *, GDbCollection *); /* Démarre la connexion à la base de données. */ -bool g_db_client_start(GDbClient *); +bool g_db_client_start(GDbClient *, const char *, unsigned short, const char *); /* Arrête la connexion à la base de données. */ void g_db_client_stop(GDbClient *); +/* Identifie le canal de communication pour envois au serveur. */ +int g_db_client_get_fd(GDbClient *); + +/* Marque le canal de communication comme disponible. */ +void g_db_client_put_fd(GDbClient *); + #endif /* _ANALYSIS_DB_CLIENT_H */ diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index 9ddba48..20b1ff3 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -24,3 +24,494 @@ #include "collection.h" +#include "../../common/io.h" +#include "../../glibext/chrysamarshal.h" + + + +/* Collection générique d'éléments (instance) */ +struct _GDbCollection +{ + GObject parent; /* A laisser en premier */ + + uint32_t featuring; /* Fonctionnalité représentée */ + GType type; /* Identifiant GLib équivalent */ + + GList *items; /* Eléments rassemblés */ + GList *sorted; /* Eléments triés */ + GRWLock params_access; /* Verrou de protection */ + +}; + +/* Collection générique d'éléments (classe) */ +struct _GDbCollectionClass +{ + GObjectClass parent; /* A laisser en premier */ + + /* Signaux */ + + void (* content_changed) (GDbCollection *, DBAction, GDbItem *); + +}; + + + + +/* Initialise la classe des collections génériques d'éléments. */ +static void g_db_collection_class_init(GDbCollectionClass *); + +/* Initialise une collection générique d'éléments. */ +static void g_db_collection_init(GDbCollection *); + +/* Supprime toutes les références externes. */ +static void g_db_collection_dispose(GDbCollection *); + +/* Procède à la libération totale de la mémoire. */ +static void g_db_collection_finalize(GDbCollection *); + + + + +/* Indique le type défini pour une collection générique d'éléments. */ +G_DEFINE_TYPE(GDbCollection, g_db_collection, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des collections génériques d'éléments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_collection_class_init(GDbCollectionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_db_collection_dispose; + object->finalize = (GObjectFinalizeFunc)g_db_collection_finalize; + + g_signal_new("content-changed", + G_TYPE_DB_COLLECTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GDbCollectionClass, content_changed), + NULL, NULL, + g_cclosure_user_marshal_VOID__ENUM_OBJECT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_OBJECT); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance à initialiser. * +* * +* Description : Initialise une collection générique d'éléments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_collection_init(GDbCollection *collec) +{ + g_rw_lock_init(&collec->params_access); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_collection_dispose(GDbCollection *collec) +{ + G_OBJECT_CLASS(g_db_collection_parent_class)->dispose(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_collection_finalize(GDbCollection *collec) +{ + g_rw_lock_clear(&collec->params_access); + + G_OBJECT_CLASS(g_db_collection_parent_class)->finalize(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : id = identifiant réseau des éléments à traiter. * +* type = type GLib des éléments à intégrer dans la collection. * +* * +* Description : Prépare la mise en place d'une nouvelle collection. * +* * +* Retour : Adresse de l'instance ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbCollection *g_db_collection_new(uint32_t id, GType type) +{ + GDbCollection *result; /* Adresse à retourner */ + + result = g_object_new(G_TYPE_DB_COLLECTION, NULL); + + result->featuring = id; + result->type = type; + + return result; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : collec = collection générique d'éléments à consulter. * +* * +* Description : Décrit le type des éléments rassemblées dans une collection. * +* * +* Retour : Identifiant interne des éléments collectionés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint32_t g_db_collection_get_feature(const GDbCollection *collec) +{ + return collec->featuring; + +} + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* fd = flux ouvert en lecture pour la réception de données.* +* * +* Description : Réceptionne et traite une requête réseau pour collection. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : Cette fonction est uniquement destinée aux appels depuis * +* la fonction g_cdb_archive_process() ; une partie des * +* informations ont déjà été tirées des échanges protocolaires. * +* * +******************************************************************************/ + +bool g_db_collection_recv(GDbCollection *collec, int fd) +{ + bool result; /* Bilan à faire remonter */ + uint32_t val32; /* Valeur sur 32 bits */ + bool status; /* Bilan de lecture initiale */ + DBAction action; /* Commande de la requête */ + GDbItem *item; /* Définition d'élément visé */ + + status = safe_recv(fd, &val32, sizeof(uint32_t), 0); + if (!status) return false; + + action = be32toh(val32); + if (action < 0 || action >= DBA_COUNT) return false; + + item = g_object_new(collec->type, NULL); + + status = g_db_item_recv(item, fd, 0); + if (!status) return false; + + result = false; + + switch (action) + { + case DBA_ADD_ITEM: + result = g_db_collection_add_item(collec, item); + break; + + case DBA_REM_ITEM: + break; + + case DBA_MOD_ITEM: + result = g_db_collection_modify_item(collec, item); + break; + + default: + /* Pour GCC : DBA_COUNT */ + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* fd = flux ouvert en écriture pour l'émission de données. * +* action = avenir de l'élément fourni. * +* item = élément de collection à sérialiser. * +* * +* Description : Envoie pour traitement une requête réseau pour collection. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_collection_send(GDbCollection *collec, int fd, DBAction action, GDbItem *item) +{ + bool status; /* Bilan de lecture initiale */ + + status = safe_send(fd, (uint32_t []) { htobe32(DBC_COLLECTION) }, sizeof(uint32_t), MSG_MORE); + if (!status) return false; + + status = safe_send(fd, (uint32_t []) { htobe32(collec->featuring) }, sizeof(uint32_t), MSG_MORE); + if (!status) return false; + + status = safe_send(fd, (uint32_t []) { htobe32(action) }, sizeof(uint32_t), MSG_MORE); + if (!status) return false; + + status = g_db_item_send(item, fd, 0); + if (!status) return false; + + return true; + +} + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : collec = collection à mettre à jour. * +* write = précise le type d'accès prévu (lecture/écriture). * +* lock = indique le sens du verrouillage à mener. * +* * +* Description : Met à disposition un encadrement des accès aux éléments. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_db_collection_lock_unlock(GDbCollection *collec, bool write, bool lock) +{ + if (write) + { + if (lock) g_rw_lock_writer_lock(&collec->params_access); + else g_rw_lock_writer_unlock(&collec->params_access); + } + else + { + if (lock) g_rw_lock_reader_lock(&collec->params_access); + else g_rw_lock_reader_unlock(&collec->params_access); + } + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* * +* Description : Renvoie la liste des éléments rassemblés. * +* * +* Retour : Liste d'éléments à parcourir. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GList *g_db_collection_list_items(const GDbCollection *collec) +{ + /** + * Un verrou doit être posé ! + * Il n'y a pas d'assert() possible pour le vérifier... + */ + + return collec->items; + +} + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* item = élément de collection à manipuler. * +* * +* Description : Procède à l'ajout d'un nouvel élément dans la collection. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : L'appelant reste le propriétaire de l'object transféré. * +* * +******************************************************************************/ + +bool g_db_collection_add_item(GDbCollection *collec, GDbItem *item) +{ + bool result; /* Bilan à faire remonter */ + GList *found; /* Test de présence existante */ + + g_db_collection_wlock(collec); + + found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare); + + if (found != NULL) + result = g_db_collection_modify_item(collec, item); + + else + { + g_object_ref(G_OBJECT(item)); + collec->items = g_list_append(collec->items, item); + + g_object_ref(G_OBJECT(item)); + collec->sorted = g_list_insert_sorted(collec->sorted, item, (GCompareFunc)g_db_item_compare); + + g_signal_emit_by_name(collec, "content-changed", DBA_ADD_ITEM, item); + + result = true; + + } + + g_db_collection_wunlock(collec); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* item = élément de collection à copier. * +* * +* Description : Procède à la modification d'un élément dans la collection. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : L'appelant reste le propriétaire de l'object transféré. * +* * +******************************************************************************/ + +bool g_db_collection_modify_item(GDbCollection *collec, GDbItem *item) +{ + bool result; /* Bilan à faire remonter */ + GList *found; /* Test de présence existante */ + + found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare); + + + + result = true; + + + + + + return result; + +} + + + + +/* ---------------------------------------------------------------------------------- */ +/* CREATION DE L'ABSTRACTION POUR COLLECTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : list = ensemble de collectons à parcourir. * +* id = identifiant interne du type d'éléments groupés. * +* * +* Description : Recherche une collection correspondant à un type donné. * +* * +* Retour : Collection trouvée ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbCollection *find_collection_in_list(GList *list, uint32_t id) +{ + GDbCollection *result; /* Collection trouvée renvoyée */ + GList *iter; /* Boucle de parcours */ + + result = NULL; + + for (iter = g_list_first(list); + iter != NULL; + iter = g_list_next(iter)) + { + result = G_DB_COLLECTION(iter->data); + + if (g_db_collection_get_feature(result) == id) + break; + + } + + return (iter != NULL ? result : NULL); + +} diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h index 715cdc9..75ee7df 100644 --- a/src/analysis/db/collection.h +++ b/src/analysis/db/collection.h @@ -25,6 +25,87 @@ #define _ANALYSIS_DB_COLLECTION_H +#include <glib-object.h> +#include <stdint.h> + + +#include "item.h" +#include "protocol.h" + + + +#define G_TYPE_DB_COLLECTION g_db_collection_get_type() +#define G_DB_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_collection_get_type(), GDbCollection)) +#define G_IS_DB_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_collection_get_type())) +#define G_DB_COLLECTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_db_collection_get_type(), GDbCollectionIface)) +#define G_DB_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_COLLECTION, GDbCollectionClass)) + + +/* Collection générique d'éléments (instance) */ +typedef struct _GDbCollection GDbCollection; + +/* Collection générique d'éléments (classe) */ +typedef struct _GDbCollectionClass GDbCollectionClass; + + +/* Indique le type défini pour une collection générique d'éléments. */ +GType g_db_collection_get_type(void); + +/* Prépare la mise en place d'une nouvelle collection. */ +GDbCollection *g_db_collection_new(uint32_t, GType); + + + +/* Décrit le type des éléments rassemblées dans une collection. */ +uint32_t g_db_collection_get_feature(const GDbCollection *); + + + + +/* Réceptionne et traite une requête réseau pour collection. */ +bool g_db_collection_recv(GDbCollection *, int); + +/* Envoie pour traitement une requête réseau pour collection. */ +bool g_db_collection_send(GDbCollection *, int, DBAction, GDbItem *); + + + + + + +/* Met à disposition un encadrement des accès aux éléments. */ +void g_db_collection_lock_unlock(GDbCollection *, bool, bool); + + +#define g_db_collection_wlock(col) g_db_collection_lock_unlock(col, true, true); +#define g_db_collection_wunlock(col) g_db_collection_lock_unlock(col, true, false); + +#define g_db_collection_rlock(col) g_db_collection_lock_unlock(col, false, true); +#define g_db_collection_runlock(col) g_db_collection_lock_unlock(col, false, false); + + +/* Renvoie la liste des éléments rassemblés. */ +GList *g_db_collection_list_items(const GDbCollection *); + + + + +/* Procède à l'ajout d'un nouvel élément dans la collection. */ +bool g_db_collection_add_item(GDbCollection *, GDbItem *); + +/* Procède à la modification d'un élément dans la collection. */ +bool g_db_collection_modify_item(GDbCollection *, GDbItem *); + + + + + +/* ------------------- CREATION DE L'ABSTRACTION POUR COLLECTIONS ------------------- */ + + +/* Recherche une collection correspondant à un type donné. */ +GDbCollection *find_collection_in_list(GList *, uint32_t); + #endif /* _ANALYSIS_DB_COLLECTION_H */ diff --git a/src/analysis/db/core.c b/src/analysis/db/core.c index 0bc5f50..81ea117 100644 --- a/src/analysis/db/core.c +++ b/src/analysis/db/core.c @@ -142,6 +142,7 @@ void init_core_db_info(core_db_info *info, uint64_t type, const char *user) bool load_core_db_info(core_db_info *info, uint64_t type, int fd) { +#if 0 ssize_t got; /* Quantité de données reçues */ uint64_t val64; /* Valeur sur 64 bits */ @@ -163,7 +164,7 @@ bool load_core_db_info(core_db_info *info, uint64_t type, int fd) info->modified = be64toh(val64); info->saved = info->modified; - +#endif return true; } @@ -184,6 +185,7 @@ bool load_core_db_info(core_db_info *info, uint64_t type, int fd) bool store_core_db_info(core_db_info *info, int fd) { +#if 0 ssize_t got; /* Quantité de données reçues */ got = safe_send(fd, (uint64_t []) { htobe64(info->type) }, sizeof(uint64_t), MSG_WAITALL); @@ -199,7 +201,7 @@ bool store_core_db_info(core_db_info *info, int fd) if (got != sizeof(uint64_t)) return false; info->saved = time(NULL); - +#endif return true; } diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h new file mode 100644 index 0000000..b6d8f9c --- /dev/null +++ b/src/analysis/db/item-int.h @@ -0,0 +1,68 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * item-int.h - prototypes et définitions internes pour les bases d'éléments de collection + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DB_ITEM_INT_H +#define _ANALYSIS_DB_ITEM_INT_H + + +#include "item.h" + + +#include <stdint.h> + + + +/* Importe la définition d'une base d'éléments pour collection. */ +typedef bool (* recv_db_item_fc) (GDbItem *, int, int); + +/* Exporte la définition d'une base d'éléments pour collection. */ +typedef bool (* send_db_item_fc) (const GDbItem *, int, int); + + +/* Base d'un élément pour collection générique (instance) */ +struct _GDbItem +{ + GObject parent; /* A laisser en premier */ + + uint64_t created; /* Date de création */ + uint64_t modified; /* Date de modification */ + + bool is_volatile; /* Pas besoin de sauvegarde ? */ + +}; + +/* Base d'un élément pour collection générique (classe) */ +struct _GDbItemClass +{ + GObjectClass parent; /* A laisser en premier */ + + GCompareFunc cmp; /* Comparaison entre éléments */ + + recv_db_item_fc recv; /* Réception depuis le réseau */ + send_db_item_fc send; /* Emission depuis le réseau */ + +}; + + + +#endif /* _ANALYSIS_DB_ITEM_INT_H */ diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c new file mode 100644 index 0000000..e2fd7f3 --- /dev/null +++ b/src/analysis/db/item.c @@ -0,0 +1,356 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * item.c - gestion d'éléments destinés à une collection générique + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "item.h" + + +#include "item-int.h" +#include "../../common/io.h" + + + +/* Initialise la classe des bases d'éléments pour collection. */ +static void g_db_item_class_init(GDbItemClass *); + +/* Initialise une base d'élément pour collection générique. */ +static void g_db_item_init(GDbItem *); + +/* Supprime toutes les références externes. */ +static void g_db_item_dispose(GDbItem *); + +/* Procède à la libération totale de la mémoire. */ +static void g_db_item_finalize(GDbItem *); + +/* Effectue la comparaison entre deux éléments de collection. */ +static gint g_db_item_cmp(GDbItem *, GDbItem *); + +/* Importe la définition d'une base d'éléments pour collection. */ +static bool g_db_item_recv_from_fd(GDbItem *, int, int); + +/* Exporte la définition d'une base d'éléments pour collection. */ +static bool g_db_item_send_to_fd(const GDbItem *, int, int); + + + + +/* Indique le type défini pour une base d'élément de collection générique. */ +G_DEFINE_TYPE(GDbItem, g_db_item, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des bases d'éléments pour collection. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_item_class_init(GDbItemClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_db_item_dispose; + object->finalize = (GObjectFinalizeFunc)g_db_item_finalize; + + klass->cmp = (GCompareFunc)g_db_item_cmp; + + klass->recv = (recv_db_item_fc)g_db_item_recv_from_fd; + klass->send = (send_db_item_fc)g_db_item_send_to_fd; + +} + + +/****************************************************************************** +* * +* Paramètres : item = instance à initialiser. * +* * +* Description : Initialise une base d'élément pour collection générique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_item_init(GDbItem *item) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : item = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_item_dispose(GDbItem *item) +{ + G_OBJECT_CLASS(g_db_item_parent_class)->dispose(G_OBJECT(item)); + +} + + +/****************************************************************************** +* * +* Paramètres : item = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_item_finalize(GDbItem *item) +{ + G_OBJECT_CLASS(g_db_item_parent_class)->finalize(G_OBJECT(item)); + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier élément à analyser. * +* b = second élément à analyser. * +* * +* Description : Effectue la comparaison entre deux éléments de collection. * +* * +* Retour : Bilan de la comparaison : -1, 0 ou 1. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gint g_db_item_cmp(GDbItem *a, GDbItem *b) +{ + gint result; /* Bilan à retourner */ + + /** + * A n'utiliser qu'en dernier recours, pour départager deux + * éléments par un serveur NTP... + */ + + if (a->modified > b->modified) + result = 1; + + else if (a->modified < b->modified) + result = -1; + + else + { + if (a->created > b->created) + result = 1; + + else if (a->created < b->created) + result = -1; + + else + result = 0; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier élément à analyser. * +* b = second élément à analyser. * +* * +* Description : Effectue la comparaison entre deux éléments de collection. * +* * +* Retour : Bilan de la comparaison : -1, 0 ou 1. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_db_item_compare(GDbItem *a, GDbItem *b) +{ + return G_DB_ITEM_GET_CLASS(a)->cmp(a, b); + +} + + +/****************************************************************************** +* * +* Paramètres : item = base d'éléments à charger. [OUT] * +* fd = flux ouvert en lecture pour l'importation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Importe la définition d'une base d'éléments pour collection. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_item_recv_from_fd(GDbItem *item, int fd, int flags) +{ + uint64_t val64; /* Valeur sur 64 bits */ + bool status; /* Bilan d'une réception */ + + status = safe_recv(fd, &val64, sizeof(uint64_t), flags); + if (!status) return false; + + item->created = be64toh(val64); + + status = safe_recv(fd, &val64, sizeof(uint64_t), flags); + if (!status) return false; + + item->modified = be64toh(val64); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : item = base d'éléments à charger. [OUT] * +* fd = flux ouvert en lecture pour l'importation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Importe la définition d'une base d'éléments pour collection. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_item_recv(GDbItem *item, int fd, int flags) +{ + return G_DB_ITEM_GET_CLASS(item)->recv(item, fd, flags); + +} + + +/****************************************************************************** +* * +* Paramètres : item = informations à sauvegarer. * +* fd = flux ouvert en écriture pour l'exportation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Exporte la définition d'une base d'éléments pour collection. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_item_send_to_fd(const GDbItem *item, int fd, int flags) +{ + bool status; /* Bilan d'une émission */ + + + printf("<sending> FROM %s...\n", __FUNCTION__); + + + status = safe_send(fd, (uint64_t []) { htobe64(item->created) }, sizeof(uint64_t), MSG_MORE | flags); + if (!status) return false; + + status = safe_send(fd, (uint64_t []) { htobe64(item->modified) }, sizeof(uint64_t), flags); + if (!status) return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : item = informations à sauvegarer. * +* fd = flux ouvert en écriture pour l'exportation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Exporte la définition d'une base d'éléments pour collection. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_item_send(const GDbItem *item, int fd, int flags) +{ + return G_DB_ITEM_GET_CLASS(item)->send(item, fd, flags); + +} + + +/****************************************************************************** +* * +* Paramètres : item = base d'éléments à modifier. * +* is_volatile = état du besoin en sauvegarde. * +* * +* Description : Définit si l'élément contient des données à oublier ou non. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_db_item_set_volatile(GDbItem *item, bool is_volatile) +{ + item->is_volatile = is_volatile; + +} + + +/****************************************************************************** +* * +* Paramètres : item = base d'éléments à consulter. * +* * +* Description : Indique si l'élément contient des données à oublier ou non. * +* * +* Retour : Etat du besoin en sauvegarde. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_item_is_volatile(const GDbItem *item) +{ + return item->is_volatile; + +} diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h new file mode 100644 index 0000000..3938610 --- /dev/null +++ b/src/analysis/db/item.h @@ -0,0 +1,68 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * item.h - prototypes pour la gestion d'éléments destinés à une collection générique + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DB_ITEM_H +#define _ANALYSIS_DB_ITEM_H + + +#include <glib-object.h> +#include <stdbool.h> + + + +#define G_TYPE_DB_ITEM g_db_item_get_type() +#define G_DB_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_item_get_type(), GDbItem)) +#define G_IS_DB_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_item_get_type())) +#define G_DB_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_ITEM, GDbItemClass)) +#define G_IS_DB_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_ITEM)) +#define G_DB_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_ITEM, GDbItemClass)) + + +/* Base d'un élément pour collection générique (instance) */ +typedef struct _GDbItem GDbItem; + +/* Base d'un élément pour collection générique (classe) */ +typedef struct _GDbItemClass GDbItemClass; + + +/* Indique le type défini pour une base d'élément de collection générique. */ +GType g_db_item_get_type(void); + +/* Effectue la comparaison entre deux éléments de collection. */ +gint g_db_item_compare(GDbItem *, GDbItem *); + +/* Importe la définition d'une base d'éléments pour collection. */ +bool g_db_item_recv(GDbItem *, int, int); + +/* Exporte la définition d'une base d'éléments pour collection. */ +bool g_db_item_send(const GDbItem *, int, int); + +/* Définit si l'élément contient des données à oublier ou non. */ +void g_db_item_set_volatile(GDbItem *, bool); + +/* Indique si l'élément contient des données à oublier ou non. */ +bool g_db_item_is_volatile(const GDbItem *); + + + +#endif /* _ANALYSIS_DB_ITEM_H */ diff --git a/src/analysis/db/items/Makefile.am b/src/analysis/db/items/Makefile.am new file mode 100644 index 0000000..f026d44 --- /dev/null +++ b/src/analysis/db/items/Makefile.am @@ -0,0 +1,17 @@ + +noinst_LTLIBRARIES = libanalysisdbitems.la + +libanalysisdbitems_la_SOURCES = \ + bookmark.h bookmark.c \ + comment.h comment.c + +libanalysisdbitems_la_LIBADD = + +libanalysisdbitems_la_LDFLAGS = + + +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/bookmark.c b/src/analysis/db/items/bookmark.c new file mode 100644 index 0000000..c28a837 --- /dev/null +++ b/src/analysis/db/items/bookmark.c @@ -0,0 +1,416 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bookmark.h - prototypes pour la gestion des signets au sein d'un binaire + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "bookmark.h" + + +#include <stdio.h> +#include <sys/socket.h> + + +#include "../item-int.h" +#include "../misc/rlestr.h" + + + +/* Signet à l'intérieur d'une zone de texte (instance) */ +struct _GDbBookmark +{ + GDbItem parent; /* A laisser en premier */ + + vmpa2t addr; /* Adresse du signet */ + rle_string comment; /* Eventuel commentaire associé*/ + +}; + +/* Signet à l'intérieur d'une zone de texte (classe) */ +struct _GDbBookmarkClass +{ + GDbItemClass parent; /* A laisser en premier */ + +}; + + + +/* Initialise la classe des signets dans une zone de texte. */ +static void g_db_bookmark_class_init(GDbBookmarkClass *); + +/* Initialise un signet dans une zone de texte. */ +static void g_db_bookmark_init(GDbBookmark *); + +/* Supprime toutes les références externes. */ +static void g_db_bookmark_dispose(GDbBookmark *); + +/* Procède à la libération totale de la mémoire. */ +static void g_db_bookmark_finalize(GDbBookmark *); + + + +/* Effectue la comparaison entre deux signets de collection. */ +static gint g_db_bookmark_cmp(GDbBookmark *, GDbBookmark *); + +/* Importe la définition d'un signet dans un flux réseau. */ +static bool g_db_bookmark_recv_from_fd(GDbBookmark *, int, int); + +/* Exporte la définition d'un signet dans un flux réseau. */ +static bool g_db_bookmark_send_to_fd(const GDbBookmark *, int, int); + + + + +/****************************************************************************** +* * +* Paramètres : db = accès à la base de données. * +* * +* Description : Crée la table des signets dans une base de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool create_bookmark_db_table(sqlite3 *db) +{ + char *sql; /* Requête à exécuter */ + int ret; /* Bilan de la création */ + char *msg; /* Message d'erreur */ + + sql = "CREATE TABLE Bookmarks (" \ + "id INT PRIMARY KEY NOT NULL, " \ + "user TEXT NOT NULL, " \ + "created INT NOT NULL, " \ + "address INT NOT NULL, " \ + "comment TEXT" \ + ");"; + + ret = sqlite3_exec(db, sql, NULL, NULL, &msg); + if (ret != SQLITE_OK) + { + fprintf(stderr, "sqlite3_exec(): %s\n", msg); + sqlite3_free(msg); + } + + return (ret == SQLITE_OK); + +} + + + + + + + + + + +/* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */ +G_DEFINE_TYPE(GDbBookmark, g_db_bookmark, G_TYPE_DB_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des signets dans une zone de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_bookmark_class_init(GDbBookmarkClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDbItemClass *item; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_db_bookmark_dispose; + object->finalize = (GObjectFinalizeFunc)g_db_bookmark_finalize; + + item = G_DB_ITEM_CLASS(klass); + + item->cmp = (GCompareFunc)g_db_bookmark_cmp; + + item->recv = (recv_db_item_fc)g_db_bookmark_recv_from_fd; + item->send = (send_db_item_fc)g_db_bookmark_send_to_fd; + +} + + +/****************************************************************************** +* * +* Paramètres : bookmark = instance à initialiser. * +* * +* Description : Initialise un signet dans une zone de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_bookmark_init(GDbBookmark *bookmark) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : bookmark = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_bookmark_dispose(GDbBookmark *bookmark) +{ + G_OBJECT_CLASS(g_db_bookmark_parent_class)->dispose(G_OBJECT(bookmark)); + +} + + +/****************************************************************************** +* * +* Paramètres : bookmark = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_bookmark_finalize(GDbBookmark *bookmark) +{ + G_OBJECT_CLASS(g_db_bookmark_parent_class)->finalize(G_OBJECT(bookmark)); + +} + + +/****************************************************************************** +* * +* Paramètres : addr = adresse inamovible localisant une position donnée. * +* comment = commentaire construit ou NULL. * +* * +* Description : Crée une définition d'un signet dans une zone de texte. * +* * +* Retour : Signet mis en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbBookmark *g_db_bookmark_new(const vmpa2t *addr, const char *comment) +{ + GDbBookmark *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_DB_BOOKMARK, NULL); + + + + + /* TODO */ + + //dup addr; + + + g_db_bookmark_set_comment(result, comment); + + return result; + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : a = premier élément à analyser. * +* b = second élément à analyser. * +* * +* Description : Effectue la comparaison entre deux signets de collection. * +* * +* Retour : Bilan de la comparaison : -1, 0 ou 1. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gint g_db_bookmark_cmp(GDbBookmark *a, GDbBookmark *b) +{ + gint result; /* Bilan de la comparaison */ + + result = cmp_vmpa_by_phy(&a->addr, &b->addr); + + if (result == 0) + result = cmp_rle_string(&a->comment, &b->comment); + + return 0; + + +} + + +/****************************************************************************** +* * +* Paramètres : bookmark = signet dont les informations sont à charger. [OUT]* +* fd = flux ouvert en lecture pour l'importation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Importe la définition d'un signet dans un flux réseau. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_bookmark_recv_from_fd(GDbBookmark *bookmark, int fd, int flags) +{ + bool status; /* Bilan d'opération initiale */ + + status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->recv(G_DB_ITEM(bookmark), fd, flags); + if (!status) return false; + + if (!recv_vmpa(&bookmark->addr, fd, 0)) + return false; + + if (!recv_rle_string(&bookmark->comment, fd, 0)) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : bookmark = informations à sauvegarder. * +* fd = flux ouvert en écriture pour l'exportation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Exporte la définition d'un signet dans un flux réseau. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int flags) +{ + bool status; /* Bilan d'opération initiale */ + + status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->send(G_DB_ITEM(bookmark), fd, MSG_MORE | flags); + if (!status) return false; + + + printf("<sending> FROM %s...\n", __FUNCTION__); + + + if (!send_vmpa(&bookmark->addr, fd, MSG_MORE | flags)) + return false; + + if (!send_rle_string(&bookmark->comment, fd, flags)) + return false; + + return true; + +} + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : bookmark = informations à consulter. * +* * +* Description : Fournit l'adresse associée à un signet. * +* * +* Retour : Adresse mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +vmpa2t *g_db_bookmark_get_address(GDbBookmark *bookmark) +{ + return &bookmark->addr; + +} + + +/****************************************************************************** +* * +* Paramètres : bookmark = informations à consulter. * +* * +* Description : Fournit le commentaire associé à un signet. * +* * +* Retour : Commentaire existant ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_db_bookmark_get_comment(const GDbBookmark *bookmark) +{ + return get_rle_string(&bookmark->comment); + +} + + +/****************************************************************************** +* * +* Paramètres : bookmark = informations à consulter. * +* comment = commentaire construit ou NULL. * +* * +* Description : Définit le commentaire associé à un signet. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_db_bookmark_set_comment(GDbBookmark *bookmark, const char *comment) +{ + set_rle_string(&bookmark->comment, comment); + +} diff --git a/src/analysis/db/items/bookmark.h b/src/analysis/db/items/bookmark.h new file mode 100644 index 0000000..d1b073c --- /dev/null +++ b/src/analysis/db/items/bookmark.h @@ -0,0 +1,79 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bookmark.h - prototypes pour la gestion des signets au sein d'un binaire + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DB_ITEMS_BOOKMARK_H +#define _ANALYSIS_DB_ITEMS_BOOKMARK_H + + + +#include <glib-object.h> +#include <sqlite3.h> +#include <stdbool.h> + + +#include "../../../arch/vmpa.h" + + + +/* Crée la table des signets dans une base de données. */ +bool create_bookmark_db_table(sqlite3 *); + + + + + + + +#define G_TYPE_DB_BOOKMARK g_db_bookmark_get_type() +#define G_DB_BOOKMARK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_bookmark_get_type(), GDbBookmark)) +#define G_IS_DB_BOOKMARK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_bookmark_get_type())) +#define G_DB_BOOKMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_BOOKMARK, GDbBookmarkClass)) +#define G_IS_DB_BOOKMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_BOOKMARK)) +#define G_DB_BOOKMARK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_BOOKMARK, GDbBookmarkClass)) + + +/* Signet à l'intérieur d'une zone de texte (instance) */ +typedef struct _GDbBookmark GDbBookmark; + +/* Signet à l'intérieur d'une zone de texte (classe) */ +typedef struct _GDbBookmarkClass GDbBookmarkClass; + + +/* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */ +GType g_db_bookmark_get_type(void); + +/* Crée une définition d'un signet dans une zone de texte. */ +GDbBookmark *g_db_bookmark_new(const vmpa2t *, const char *); + +/* Fournit l'adresse associée à un signet. */ +vmpa2t *g_db_bookmark_get_address(GDbBookmark *); + +/* Fournit le commentaire associé à un signet. */ +const char *g_db_bookmark_get_comment(const GDbBookmark *); + +/* Définit le commentaire associé à un signet. */ +void g_db_bookmark_set_comment(GDbBookmark *, const char *); + + + +#endif /* _ANALYSIS_DB_ITEMS_BOOKMARK_H */ diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c new file mode 100644 index 0000000..73a18b0 --- /dev/null +++ b/src/analysis/db/items/comment.c @@ -0,0 +1,398 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * comment.c - gestion des commentaires dans du texte + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "comment.h" + + +#include <stdio.h> +#include <sys/socket.h> + + +#include "../item-int.h" +#include "../misc/rlestr.h" + + + +/* Commentaire à placer dans du texte quelconque (instance) */ +struct _GDbComment +{ + GDbItem parent; /* A laisser en premier */ + + vmpa2t *addr; /* Adresse du commentaire */ + rle_string text; /* Contenu du commentaire */ + +}; + +/* Commentaire à placer dans du texte quelconque (classe) */ +struct _GDbCommentClass +{ + GDbItemClass parent; /* A laisser en premier */ + +}; + + + +/* Initialise la classe des commentaires dans une zone de texte. */ +static void g_db_comment_class_init(GDbCommentClass *); + +/* Initialise un commentaire dans une zone de texte. */ +static void g_db_comment_init(GDbComment *); + +/* Supprime toutes les références externes. */ +static void g_db_comment_dispose(GDbComment *); + +/* Procède à la libération totale de la mémoire. */ +static void g_db_comment_finalize(GDbComment *); + +/* Effectue la comparaison entre deux commentaires enregistrés. */ +static gint g_db_comment_cmp(GDbComment *, GDbComment *); + +/* Importe la définition d'un commentaire dans un flux réseau. */ +static bool g_db_comment_recv_from_fd(GDbComment *, int, int); + +/* Exporte la définition d'un commentaire dans un flux réseau. */ +static bool g_db_comment_send_to_fd(const GDbComment *, int, int); + + + + +/****************************************************************************** +* * +* Paramètres : db = accès à la base de données. * +* * +* Description : Crée la table des commentaires dans une base de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool create_comment_db_table(sqlite3 *db) +{ + char *sql; /* Requête à exécuter */ + int ret; /* Bilan de la création */ + char *msg; /* Message d'erreur */ + + sql = "CREATE TABLE Comments (" \ + "id INT PRIMARY KEY NOT NULL, " \ + "user TEXT NOT NULL, " \ + "created INT NOT NULL, " \ + "address INT NOT NULL, " \ + "comment TEXT" \ + ");"; + + ret = sqlite3_exec(db, sql, NULL, NULL, &msg); + if (ret != SQLITE_OK) + { + fprintf(stderr, "sqlite3_exec(): %s\n", msg); + sqlite3_free(msg); + } + + return (ret == SQLITE_OK); + +} + + + + + + + + + + +/* Indique le type défini pour un commentaire à l'intérieur d'une zone de texte. */ +G_DEFINE_TYPE(GDbComment, g_db_comment, G_TYPE_DB_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des commentaires dans une zone de texte.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_comment_class_init(GDbCommentClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDbItemClass *item; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_db_comment_dispose; + object->finalize = (GObjectFinalizeFunc)g_db_comment_finalize; + + item = G_DB_ITEM_CLASS(klass); + + item->cmp = (GCompareFunc)g_db_comment_cmp; + + item->recv = (recv_db_item_fc)g_db_comment_recv_from_fd; + item->send = (send_db_item_fc)g_db_comment_send_to_fd; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = instance à initialiser. * +* * +* Description : Initialise un commentaire dans une zone de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_comment_init(GDbComment *comment) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : comment = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_comment_dispose(GDbComment *comment) +{ + G_OBJECT_CLASS(g_db_comment_parent_class)->dispose(G_OBJECT(comment)); + +} + + +/****************************************************************************** +* * +* Paramètres : comment = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_comment_finalize(GDbComment *comment) +{ + delete_vmpa(comment->addr); + + exit_rle_string(comment->text); + + G_OBJECT_CLASS(g_db_comment_parent_class)->finalize(G_OBJECT(comment)); + +} + + +/****************************************************************************** +* * +* Paramètres : addr = adresse inamovible localisant une position. * +* text = commentaire construit ou NULL. * +* is_volatile = état du besoin en sauvegarde. * +* * +* Description : Crée une définition de commentaire dans une zone de texte. * +* * +* Retour : Commentaire mis en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbComment *g_db_comment_new(const vmpa2t *addr, const char *text, bool is_volatile) +{ + GDbComment *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_DB_COMMENT, NULL); + + result->addr = dup_vmpa(addr); + + g_db_comment_set_text(result, text); + + g_db_item_set_volatile(G_DB_ITEM(result), is_volatile); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier élément à analyser. * +* b = second élément à analyser. * +* * +* Description : Effectue la comparaison entre deux commentaires enregistrés. * +* * +* Retour : Bilan de la comparaison : -1, 0 ou 1. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gint g_db_comment_cmp(GDbComment *a, GDbComment *b) +{ + gint result; /* Bilan de la comparaison */ + + result = cmp_vmpa_by_phy(a->addr, b->addr); + + if (result == 0) + result = cmp_rle_string(&a->text, &b->text); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = commentaire avec informations sont à charger. [OUT]* +* fd = flux ouvert en lecture pour l'importation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Importe la définition d'un commentaire dans un flux réseau. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_comment_recv_from_fd(GDbComment *comment, int fd, int flags) +{ + bool status; /* Bilan d'opération initiale */ + + status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->recv(G_DB_ITEM(comment), fd, flags); + if (!status) return false; + + if (!recv_vmpa(comment->addr, fd, 0)) + return false; + + if (!recv_rle_string(&comment->text, fd, 0)) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = informations à sauvegarder. * +* fd = flux ouvert en écriture pour l'exportation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Exporte la définition d'un commentaire dans un flux réseau. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags) +{ + bool status; /* Bilan d'opération initiale */ + + status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->send(G_DB_ITEM(comment), fd, MSG_MORE | flags); + if (!status) return false; + + if (!send_vmpa(comment->addr, fd, MSG_MORE | flags)) + return false; + + if (!send_rle_string(&comment->text, fd, flags)) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = informations à consulter. * +* * +* Description : Fournit l'adresse associée à un commentaire. * +* * +* Retour : Adresse mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const vmpa2t *g_db_comment_get_address(GDbComment *comment) +{ + return comment->addr; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = informations à consulter. * +* * +* Description : Fournit le commentaire associé à un commentaire. * +* * +* Retour : Commentaire existant ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_db_comment_get_text(const GDbComment *comment) +{ + return get_rle_string(&comment->text); + +} + + +/****************************************************************************** +* * +* Paramètres : comment = informations à consulter. * +* text = commentaire construit ou NULL. * +* * +* Description : Définit le commentaire associé à un commentaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_db_comment_set_text(GDbComment *comment, const char *text) +{ + set_rle_string(&comment->text, text); + +} diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h new file mode 100644 index 0000000..792fb92 --- /dev/null +++ b/src/analysis/db/items/comment.h @@ -0,0 +1,77 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * comment.h - prototypes pour la gestion des commentaires dans du texte + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DB_ITEMS_COMMENT_H +#define _ANALYSIS_DB_ITEMS_COMMENT_H + + + +#include <glib-object.h> +#include <sqlite3.h> +#include <stdbool.h> + + +#include "../../../arch/vmpa.h" + + + +/* Crée la table des commentaires dans une base de données. */ +bool create_comment_db_table(sqlite3 *); + + + + + +#define G_TYPE_DB_COMMENT g_db_comment_get_type() +#define G_DB_COMMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_comment_get_type(), GDbComment)) +#define G_IS_DB_COMMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_comment_get_type())) +#define G_DB_COMMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_COMMENT, GDbCommentClass)) +#define G_IS_DB_COMMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_COMMENT)) +#define G_DB_COMMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_COMMENT, GDbCommentClass)) + + +/* Commentaire à placer dans du texte quelconque (instance) */ +typedef struct _GDbComment GDbComment; + +/* Commentaire à placer dans du texte quelconque (classe) */ +typedef struct _GDbCommentClass GDbCommentClass; + + +/* Indique le type défini pour un commentaire à l'intérieur d'une zone de texte. */ +GType g_db_comment_get_type(void); + +/* Crée une définition de commentaire dans une zone de texte. */ +GDbComment *g_db_comment_new(const vmpa2t *, const char *, bool); + +/* Fournit l'adresse associée à un commentaire. */ +const vmpa2t *g_db_comment_get_address(GDbComment *); + +/* Fournit le commentaire associé à un commentaire. */ +const char *g_db_comment_get_text(const GDbComment *); + +/* Définit le commentaire associé à un commentaire. */ +void g_db_comment_set_text(GDbComment *, const char *); + + + +#endif /* _ANALYSIS_DB_ITEMS_COMMENT_H */ diff --git a/src/analysis/db/misc/Makefile.am b/src/analysis/db/misc/Makefile.am new file mode 100755 index 0000000..b3829e3 --- /dev/null +++ b/src/analysis/db/misc/Makefile.am @@ -0,0 +1,16 @@ + +noinst_LTLIBRARIES = libanalysisdbmisc.la + +libanalysisdbmisc_la_SOURCES = \ + rlestr.h rlestr.c + +libanalysisdbmisc_la_LIBADD = + +libanalysisdbmisc_la_LDFLAGS = + + +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/misc/rlestr.c b/src/analysis/db/misc/rlestr.c new file mode 100644 index 0000000..d75e7ab --- /dev/null +++ b/src/analysis/db/misc/rlestr.c @@ -0,0 +1,345 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * rlestr.c - encodage par plage unique d'une chaîne de caractères + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "rlestr.h" + + +#include <endian.h> +#include <malloc.h> +#include <string.h> + + +#include "../../../common/io.h" + + + + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> + +#include <time.h> +#include <unistd.h> + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : str = représentation de chaîne à traiter. * +* data = données à conserver en mémoire. * +* * +* Description : Définit une représentation de chaîne de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void init_rle_string(rle_string *str, const char *data) +{ + if (data != NULL) + { + str->data = strdup(data); + str->length = strlen(data); + } + else + { + str->data = NULL; + str->length = 0; + } + +} + + +/****************************************************************************** +* * +* Paramètres : str = représentation de chaîne à traiter. * +* data = données à conserver en mémoire. * +* * +* Description : Constitue une représentation de chaîne de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_rle_string(rle_string *str, const char *data) +{ + if (str->data != NULL) + unset_rle_string(str); + + if (data != NULL) + { + str->data = strdup(data); + str->length = strlen(data); + } + +} + + +/****************************************************************************** +* * +* Paramètres : str = représentation de chaîne à traiter. * +* * +* Description : Libère la mémoire associée à la représentation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unset_rle_string(rle_string *str) +{ + if (str->data != NULL) + { + free(str->data); + str->data = NULL; + + str->length = 0; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : s1 = première chaîne à comparer. * +* s2 = seconde chaîne à comparer. * +* * +* Description : Effectue la comparaison entre deux chaînes de caractères. * +* * +* Retour : Résultat de la comparaison : -1, 0 ou 1. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int cmp_rle_string(const rle_string *s1, const rle_string *s2) +{ + int result; /* Bilan à retourner */ + + if (s1->length < s2->length) + result = -1; + + else if (s1->length > s2->length) + result = 1; + + else + { + if (s1->data == NULL && s2->data == NULL) + result = 0; + + else if (s1->data != NULL && s2->data == NULL) + result = 1; + + else if (s1->data == NULL && s2->data != NULL) + result = -1; + + else + result = strcmp(s1->data, s2->data); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : str = informations à constituer. [OUT] * +* fd = flux ouvert en lecture pour l'importation. * +* * +* Description : Importe la définition d'une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_rle_string(rle_string *str, int fd) +{ +#if 0 + uint32_t val32; /* Valeur sur 32 bits */ + ssize_t got; /* Quantité de données reçues */ + + got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL); + if (got != sizeof(uint32_t)) return false; + + str->length = le32toh(val32); + + if (str->length > 0) + { + str->data = (char *)malloc(str->length + 1); + + got = safe_recv(fd, str->data, str->length + 1, MSG_WAITALL); + if (got != (str->length + 1)) + { + unset_rle_string(str); + return false; + } + + str->data[str->length] = '\0'; + + } +#endif + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : str = informations à sauvegarer. * +* fd = flux ouvert en écriture pour l'exportation. * +* * +* Description : Exporte la définition d'une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool store_rle_string(const rle_string *str, int fd) +{ +#if 0 + ssize_t got; /* Quantité de données reçues */ + + got = safe_send(fd, (uint32_t []) { htole32(str->length) }, sizeof(uint32_t), MSG_WAITALL); + if (got != sizeof(uint32_t)) return false; + + if (str->length > 0) + { + got = safe_send(fd, str->data, str->length + 1, MSG_WAITALL); + if (got != (str->length + 1)) return false; + } +#endif + return true; + +} + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : str = informations à constituer. [OUT] * +* fd = flux ouvert en lecture pour l'importation. * +* flags = éventuelles options de réception supplémentaires. * +* * +* Description : Importe la définition d'une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool recv_rle_string(rle_string *str, int fd, int flags) +{ + uint32_t val32; /* Valeur sur 32 bits */ + bool status; /* Bilan d'une opération */ + + str->data = NULL; + str->length = 0; + + status = safe_recv(fd, &val32, sizeof(uint32_t), flags); + if (!status) return false; + + str->length = be32toh(val32); + + if (str->length > 0) + { + str->data = (char *)malloc(str->length + 1); + + status = safe_recv(fd, str->data, str->length + 1, flags); + if (!status) + { + unset_rle_string(str); + return false; + } + + str->data[str->length] = '\0'; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : str = informations à sauvegarer. * +* fd = flux ouvert en écriture pour l'exportation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Exporte la définition d'une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool send_rle_string(const rle_string *str, int fd, int flags) +{ + bool status; /* Bilan d'une opération */ + + status = safe_send(fd, (uint32_t []) { htobe32(str->length) }, sizeof(uint32_t), flags); + if (!status) return false; + + if (str->length > 0) + { + status = safe_send(fd, str->data, str->length + 1, flags); + if (!status) return false; + } + + return true; + +} diff --git a/src/analysis/db/misc/rlestr.h b/src/analysis/db/misc/rlestr.h new file mode 100644 index 0000000..2aa863f --- /dev/null +++ b/src/analysis/db/misc/rlestr.h @@ -0,0 +1,83 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * rlestr.h - prototypes pour l'encodage par plage unique d'une chaîne de caractères + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DB_MISC_RLESTR_H +#define _ANALYSIS_DB_MISC_RLESTR_H + + +#include <stdbool.h> +#include <stdint.h> +#include <sys/types.h> + + + +/* Informations de base pour tout élément ajouté */ +typedef struct _rle_string +{ + char *data; /* Chaîne de caractères */ + uint32_t length; /* Taille de la chaîne */ + +} rle_string; + + +/* Définit une représentation de chaîne de caractères. */ +void init_rle_string(rle_string *, const char *); + +#define exit_rle_string(rle) /* TODO */ + +#define dup_rle_string(dst, src) init_rle_string(dst, (src)->data); + +#define get_rle_string(rle) (rle)->data + +/* Constitue une représentation de chaîne de caractères. */ +void set_rle_string(rle_string *, const char *); + +/* Libère la mémoire associée à la représentation. */ +void unset_rle_string(rle_string *); + +/* Effectue la comparaison entre deux chaînes de caractères. */ +int cmp_rle_string(const rle_string *, const rle_string *); + + + +/* Importe la définition d'une chaîne de caractères. */ +bool load_rle_string(rle_string *, int); + +/* Exporte la définition d'une chaîne de caractères. */ +bool store_rle_string(const rle_string *, int); + + + +#define is_rle_string_empty(rle) ((rle)->data == NULL) + + + +/* Importe la définition d'une chaîne de caractères. */ +bool recv_rle_string(rle_string *, int, int); + +/* Exporte la définition d'une chaîne de caractères. */ +bool send_rle_string(const rle_string *, int, int); + + + +#endif /* _ANALYSIS_DB_MISC_RLESTR_H */ diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index b1cdfaf..05b559e 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -27,10 +27,12 @@ /** - * Nombre maximal de connexions à un serveur. - * cf. listen(). + * Version de la définition courante du protocole. */ -#define CDB_SEVER_BACKLOG 100 +#define CDB_PROTOCOL_VERSION 0xc0de0001 + + + /** * Délai maximal de réaction pour les coupures de flux (en ms). @@ -41,27 +43,102 @@ -/* Fonctionnalités offertes */ +/* Comportement vis à vis des éléments */ +typedef enum _DBStorage +{ + DBS_ALL_LOCAL = 0x01, /* Enregistrements locaux */ + DBS_ALL_REMOTE = 0x02, /* Enregistrements distants */ + DBS_LOCAL_AND_REMOTE = 0x03, /* Enreg. locaux + infos dists.*/ + + DBS_MAX = 3 + +} DBStorage; + + + + + + + + + + + + +/** + * Une fois la connexion établie, les paquets ont tous la forme suivante : + + + + + + * + * [ type de collection visée ; cf. DBFeatures ] + * [ action à mener ; cf. DBAction ] + * [ élément de type GDbItem sérialisé... ] + * + */ + +/* Fonctionnalités offertes nativement */ typedef enum _DBFeatures { + DBF_BOOKMARKS, /* Signets dans le code */ DBF_COMMENTS, /* Commentaires ajoutés */ DBF_SEGMENTS_DISPLAY, /* Choix d'affichage */ - DBF_BOOKMARKS, /* Signets dans le code */ DBF_COUNT } DBFeatures; -/* Comportement vis à vis des éléments */ -typedef enum _DBStorage +/* Interactions disponibles vis à vis d'une collection. */ +typedef enum _DBAction { - DBS_ALL_LOCAL = 0x01, /* Enregistrements locaux */ - DBS_ALL_REMOTE = 0x02, /* Enregistrements distants */ - DBS_LOCAL_AND_REMOTE = 0x03, /* Enreg. locaux + infos dists.*/ + DBA_ADD_ITEM, /* Ajout d'un élément */ + DBA_REM_ITEM, /* Suppression d'un élément */ + DBA_MOD_ITEM, /* Modification de l'existant */ + + DBA_COUNT + +} DBAction; + + + + + + +/** + * Commandes envoyées d'un côté à un autre. + */ +typedef enum _DBCommand +{ + DBC_HELO, /* Connexion initiale C -> S */ + DBC_WELCOME, /* Réponse initiale S -> C */ + DBC_COLLECTION, /* Implication d'une collection*/ + + DBC_COUNT + +} DBCommand; + + + + + + + +/** + * Erreurs pouvant survenir... + */ +typedef enum _DBError +{ + DBE_NONE, /* Succès d'une opération */ + DBE_WRONG_VERSION, /* Proto Client != Serveur */ + + DBE_COUNT + +} DBError; + - DBS_MAX = 3 -} DBStorage; diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c index 3d75b71..42688c8 100644 --- a/src/analysis/db/server.c +++ b/src/analysis/db/server.c @@ -29,10 +29,15 @@ #include <poll.h> #include <string.h> #include <unistd.h> +#include <arpa/inet.h> #include <sys/socket.h> +#include "cdb.h" #include "protocol.h" +#include "misc/rlestr.h" +#include "../../common/io.h" +#include "../../core/params.h" #include "../../gui/panels/log.h" @@ -56,10 +61,12 @@ struct _GDbServer int fd; /* Canal de communication */ char *hostname; /* Désignation humaine */ + char *desc; /* Désignation du serveur */ struct sockaddr_in addr; /* Adresse d'écoute */ GThread *listener; /* Procédure de traitement */ + GList *archives; /* Liste des binaires ouverts */ cdb_client **clients; /* Connexions en place */ size_t count; /* Quantité de clients */ GMutex mutex; /* Verrou pour l'accès */ @@ -87,7 +94,7 @@ static void g_db_server_finalize(GDbServer *); static void *g_db_server_listener(GDbServer *); /* Assure le traitement des requêtes de clients. */ -static void *g_db_server_process(cdb_client **); +//static void *g_db_server_process(cdb_client **); @@ -177,19 +184,38 @@ GDbServer *g_db_server_new(const char *host, short port) { GDbServer *result; /* Adresse à retourner */ struct hostent *hp; /* Informations sur l'hôte */ + size_t desclen; /* Taille de désignation */ + + const char *ip; /* Adresse IPv4 ou IPv6 */ result = g_object_new(G_TYPE_DB_SERVER, NULL); result->hostname = strdup(host); hp = gethostbyname(host); - if (hp == NULL) goto gdsn_error; + if (hp == NULL) + { + perror("gethostbyname"); + goto gdsn_error; + } result->addr.sin_family = hp->h_addrtype; memcpy(&result->addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); result->addr.sin_port = htons(port); + desclen = INET6_ADDRSTRLEN + 1 + 5 + 1; + result->desc = (char *)calloc(desclen, sizeof(char)); + + ip = inet_ntop(AF_INET, &result->addr.sin_addr, result->desc, INET6_ADDRSTRLEN); + if (ip == NULL) + { + perror("inet_ntop"); + goto gdsn_error; + } + + snprintf(result->desc + strlen(ip), 1 + 5, ":%hu", port); + return result; gdsn_error: @@ -219,7 +245,27 @@ static void *g_db_server_listener(GDbServer *server) int ret; /* Bilan d'un appel */ struct sockaddr_in peer; /* Adresse cliente */ int fd; /* Canal établi vers un client */ - cdb_client *client; /* Mémorisation pour poursuite */ + char source[INET6_ADDRSTRLEN]; /* Adresse du client (IPv4/6) */ + const char *ip; /* Statut de la conversion */ + + + DBError error; /* Validation de la connexion */ + + uint32_t data; /* Mot de données lues */ + + + rle_string hash; /* Empreinte du binaire visé */ + rle_string user; /* Nom d'utilisateur du client */ + + GList *iter; /* Boucle de parcours */ + GCdbArchive *archive; /* Destinataire final du client*/ + + + + //cdb_client *client; /* Mémorisation pour poursuite */ + + + fds.fd = server->fd; fds.events = POLLIN | POLLPRI; @@ -236,8 +282,122 @@ static void *g_db_server_listener(GDbServer *server) if (fds.revents & (POLLIN | POLLPRI)) { fd = accept(server->fd, &peer, (socklen_t []) { sizeof(struct sockaddr_in) }); - if (fd == -1) continue; + if (fd == -1) + { + perror("accept"); + continue; + } + + ip = inet_ntop(AF_INET, &peer.sin_addr, source, sizeof(source)); + if (ip == NULL) + { + perror("inet_ntop"); + goto gdsl_error; + } + + error = DBE_NONE; + + /** + * Le premier "paquet" reçu de la part d'un client doit contenir les informations suivantes : + * - la commande 'DBC_HELO'. + * - le numéro de version du client. + * - l'empreinte du binaire analysé. + * - l'identifiant de l'utilisateur effectuant des modifications. + * + * Tout ceci est à synchroniser avec la fonction g_db_client_start(). + */ + + if (!safe_recv(fd, &data, sizeof(uint32_t), 0)) + goto gdsl_error; + + if (be32toh(data) != DBC_HELO) + { + log_variadic_message(LMT_ERROR, _("The client from '%s:%hu' did not introduce itself!"), + source, ntohs(peer.sin_port)); + goto gdsl_error; + } + + if (!safe_recv(fd, &data, sizeof(uint32_t), 0)) + goto gdsl_error; + + if (be32toh(data) != CDB_PROTOCOL_VERSION) + { + log_variadic_message(LMT_ERROR, _("The client from '%s:%hu' does not use the same protocol: 0x%08x vs 0x%08x..."), + source, ntohs(peer.sin_port), be32toh(data), CDB_PROTOCOL_VERSION); + error = DBE_WRONG_VERSION; + goto gdsl_error_sending; + } + + if (!recv_rle_string(&hash, fd, 0) || is_rle_string_empty(&hash)) + { + log_variadic_message(LMT_ERROR, _("Error while getting the binary hash from '%s:%hu'..."), + source, ntohs(peer.sin_port)); + goto gdsl_error; + } + + if (!recv_rle_string(&user, fd, 0) || is_rle_string_empty(&user)) + { + log_variadic_message(LMT_ERROR, _("Error while getting the user name from '%s:%hu'..."), + source, ntohs(peer.sin_port)); + goto gdsl_error; + } + + /** + * On met en place le maximum ici, de manière à pouvoir indiquer une erreur + * en cas d'échec, et être le plus précis possible dans la courte réponse. + */ + + for (iter = g_list_first(server->archives); + iter != NULL; + iter = g_list_next(iter)) + { + archive = G_CDB_ARCHIVE(iter->data); + if (g_cdb_archive_compare_hash(archive, &hash) == 0) + break; + } + + if (iter == NULL) + { + archive = g_cdb_archive_new(server->desc, &hash, &user, &error); + + if (archive != NULL) + server->archives = g_list_append(server->archives, archive); + + } + + if (archive != NULL) + error = g_cdb_archive_add_client(archive, fd, &user); + + /** + * Le serveur doit répondre pour un message type : + * - la commande 'DBC_WELCOME'. + * - un identifiant d'erreur ('DBE_NONE' ou 'DBE_WRONG_VERSION'). + */ + + gdsl_error_sending: + + if (!safe_send(fd, (uint32_t []) { htobe32(DBC_WELCOME) }, sizeof(uint32_t), MSG_MORE)) + goto gdsl_error; + + if (!safe_send(fd, (uint32_t []) { htobe32(error) }, sizeof(uint32_t), 0)) + goto gdsl_error; + + if (error == DBE_NONE) continue; + + gdsl_error: + + + /* free RLE !!!! */ + + close(fd); + + } + + + + +#if 0 g_mutex_lock(&server->mutex); client = (cdb_client *)calloc(1, sizeof(cdb_client)); @@ -256,80 +416,13 @@ static void *g_db_server_listener(GDbServer *server) &server->clients[server->count - 1]); g_mutex_unlock(&server->mutex); +#endif - } - } - return NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : client = informations sur une connexion établie à utiliser. * -* * -* Description : Assure le traitement des requêtes de clients. * -* * -* Retour : NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void *g_db_server_process(cdb_client **client) -{ - struct pollfd fds; /* Surveillance des flux */ - int ret; /* Bilan d'un appel */ - GDbServer *server; /* Accès facile en mémoire */ - size_t index; /* Indice courant du client */ - size_t remaining; /* Quantité à déplacer */ - - fds.fd = (*client)->fd; - fds.events = POLLIN | POLLPRI; - - while (1) - { - ret = poll(&fds, 1, -1); - if (ret != 1) continue; - - printf("fds.revents :: %x\n", fds.revents); - - /* Le canal est fermé, une sortie doit être demandée... */ - if (fds.revents & POLLNVAL) - break; - - if (fds.revents & (POLLIN | POLLPRI)) - { - - /* TODO */ - pause(); - - - } } - /* Retrait de la liste avant la terminaison */ - - server = (*client)->server; - - g_mutex_lock(&server->mutex); - - index = (client - server->clients); - remaining = server->count - index - 1; - - if (remaining > 0) - memmove(&server->clients[index], &server->clients[index + 1], - remaining * sizeof(cdb_client *)); - - g_object_unref(G_OBJECT(server)); - - free(*client); - - g_mutex_unlock(&server->mutex); - return NULL; } @@ -350,6 +443,7 @@ static void *g_db_server_process(cdb_client **client) bool g_db_server_start(GDbServer *server) { int ret; /* Bilan d'un appel */ + int backlog; /* Nombre de connexions maximal*/ server->fd = socket(AF_INET, SOCK_STREAM, 0); if (server->fd == -1) @@ -362,27 +456,24 @@ bool g_db_server_start(GDbServer *server) if (ret == -1) { perror("setsockopt"); - close(server->fd); - server->fd = -1; - return false; + goto gdss_error; } ret = bind(server->fd, (struct sockaddr *)&server->addr, sizeof(struct sockaddr_in)); if (ret == -1) { perror("bind"); - close(server->fd); - server->fd = -1; - return false; + goto gdss_error; } - ret = listen(server->fd, CDB_SEVER_BACKLOG); + if (!g_generic_config_get_value(get_main_configuration(), MPK_SERVER_BACKLOG, &backlog)) + goto gdss_error; + + ret = listen(server->fd, backlog); if (ret == -1) { perror("listen"); - close(server->fd); - server->fd = -1; - return false; + goto gdss_error; } server->listener = g_thread_new("cdb_listener", (GThreadFunc)g_db_server_listener, server); @@ -392,6 +483,13 @@ bool g_db_server_start(GDbServer *server) return true; + gdss_error: + + close(server->fd); + server->fd = -1; + + return false; + } |