diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2021-05-29 10:13:16 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2021-05-29 10:13:16 (GMT) |
commit | 3c493d4cd2c9e91a2cee08c80e3629ea75788605 (patch) | |
tree | 6d9483d4c8e2c3914ca47bb9e17d31201d266f30 /src/analysis/db/controller.c | |
parent | ab7c898c87a1f235af6966941823cab502c550f6 (diff) |
Define roles for allowed connections to servers.
Diffstat (limited to 'src/analysis/db/controller.c')
-rw-r--r-- | src/analysis/db/controller.c | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/src/analysis/db/controller.c b/src/analysis/db/controller.c new file mode 100644 index 0000000..46b628d --- /dev/null +++ b/src/analysis/db/controller.c @@ -0,0 +1,449 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * controller.h - prototypes pour la gestion d'un ensemble d'archives au format CDB + * + * Copyright (C) 2021 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "controller.h" + + +#include <assert.h> +#include <errno.h> +#include <malloc.h> +#include <poll.h> +#include <pthread.h> +#include <string.h> + + +#include <i18n.h> + + +#include "backend-int.h" +#include "../../common/packed.h" +#include "../../core/logs.h" + + + +/* Description d'un contrôleur d'archives (instance) */ +struct _GCdbController +{ + GServerBackend parent; /* A laisser en premier */ + + char *basedir; /* Répertoire du serveur */ + + SSL *tls_fd; /* Canal de communication */ + char *peer_name; /* Désignation du correspondant*/ + char *user; /* Utilisateur connecté */ + +}; + +/* Description d'un contrôleur d'archives (classe) */ +struct _GCdbControllerClass +{ + GServerBackendClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des contrôleurs d'archives. */ +static void g_cdb_controller_class_init(GCdbControllerClass *); + +/* Initialise un contrôleur d'archives. */ +static void g_cdb_controller_init(GCdbController *); + +/* Supprime toutes les références externes. */ +static void g_cdb_controller_dispose(GCdbController *); + +/* Procède à la libération totale de la mémoire. */ +static void g_cdb_controller_finalize(GCdbController *); + +/* Assure le traitement des requêtes de contrôle. */ +static void *g_cdb_controller_process(GCdbController *); + +/* Prend en compte une connexion nouvelle d'un utilisateur. */ +static void g_cdb_controller_add_client(GCdbController *, SSL *, const char *, const char *); + + + +/* Indique le type défini pour une gestion d'archives. */ +G_DEFINE_TYPE(GCdbController, g_cdb_controller, G_TYPE_SERVER_BACKEND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contrôleurs d'archives. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_cdb_controller_class_init(GCdbControllerClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GServerBackendClass *backend; /* Classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_cdb_controller_dispose; + object->finalize = (GObjectFinalizeFunc)g_cdb_controller_finalize; + + backend = G_SERVER_BACKEND_CLASS(klass); + + backend->thread_name = "cdb_controller"; + backend->thread_func = (GThreadFunc)g_cdb_controller_process; + + backend->add_client = (add_backend_client_fc)g_cdb_controller_add_client; + +} + + +/****************************************************************************** +* * +* Paramètres : controller = instance à initialiser. * +* * +* Description : Initialise un contrôleur d'archives. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_cdb_controller_init(GCdbController *controller) +{ + controller->basedir = NULL; + + controller->tls_fd = NULL; + controller->peer_name = NULL; + controller->user = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : controller = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_cdb_controller_dispose(GCdbController *controller) +{ + g_server_backend_stop(G_SERVER_BACKEND(controller)); + + G_OBJECT_CLASS(g_cdb_controller_parent_class)->dispose(G_OBJECT(controller)); + +} + + +/****************************************************************************** +* * +* Paramètres : controller = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_cdb_controller_finalize(GCdbController *controller) +{ + if (controller->basedir != NULL) + free(controller->basedir); + + if (controller->tls_fd != NULL) + SSL_free(controller->tls_fd); + + if (controller->peer_name != NULL) + free(controller->peer_name); + + if (controller->user != NULL) + free(controller->user); + + G_OBJECT_CLASS(g_cdb_controller_parent_class)->finalize(G_OBJECT(controller)); + +} + + +/****************************************************************************** +* * +* Paramètres : basedir = répertoire de stockage des enregistrements. * +* 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 : - * +* * +******************************************************************************/ + +GCdbController *g_cdb_controller_new(const char *basedir, DBError *error) +{ + GCdbController *result; /* Adresse à retourner */ + + result = g_object_new(G_TYPE_CDB_CONTROLLER, NULL); + + result->basedir = strdup(basedir); + + *error = DBE_NONE; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : controller = centralisation de tous les savoirs. * +* * +* Description : Assure le traitement des requêtes de contrôle. * +* * +* Retour : NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void *g_cdb_controller_process(GCdbController *controller) +{ + GServerBackend *base; /* Base de l'instance */ + struct pollfd fds[3]; /* Surveillance des flux */ + int ret; /* Bilan d'un appel */ + packed_buffer in_pbuf; /* Tampon de réception */ + uint32_t tmp32; /* Valeur sur 32 bits */ + bool status; /* Bilan de lecture initiale */ + uint32_t command; /* Commande de la requête */ + DBError error; /* Bilan d'une opération */ + packed_buffer out_pbuf; /* Tampon d'émission */ + char *msg; /* Erreur à faire remonter */ + + base = G_SERVER_BACKEND(controller); + + fds[0].fd = base->stop_ctrl[0]; + fds[0].events = POLLIN | POLLPRI; + + fds[1].fd = base->refresh_ctrl[0]; + fds[1].events = POLLIN | POLLPRI; + + fds[2].fd = SSL_get_fd(controller->tls_fd); + fds[2].events = POLLIN | POLLPRI; + + while (1) + { + /* Lancement d'une phase de surveillance */ + + ret = poll(fds, 3, -1); + if (ret == -1) + { + if (errno == EINTR) continue; + + LOG_ERROR_N("poll"); + break; + + } + + /* Demande expresse d'arrêt des procédures */ + if (fds[0].revents) + break; + + /* Demande d'actualisation ?! */ + assert(fds[1].revents == 0); + + /* Le canal est fermé, une sortie doit être demandée... */ + if (fds[2].revents & POLLNVAL) + goto closed_exchange; + + /** + * Même chose, cf. "TCP: When is EPOLLHUP generated?" + * https://stackoverflow.com/questions/52976152/tcp-when-is-epollhup-generated/52976327#52976327 + */ + + if (fds[2].revents & (POLLHUP | POLLRDHUP)) + goto closed_exchange; + + /* Données présentes en entrée */ + if (fds[2].revents & (POLLIN | POLLPRI)) + { + init_packed_buffer(&in_pbuf); + + status = ssl_recv_packed_buffer(&in_pbuf, controller->tls_fd); + if (!status) goto bad_exchange; + + next_command: + + status = extract_packed_buffer(&in_pbuf, &command, sizeof(uint32_t), true); + if (!status) goto bad_exchange; + + switch (command) + { + case DBC_LIST_ARCHIVES: + + /* + error = g_cdb_controller_write(archive); + + init_packed_buffer(&out_pbuf); + + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SAVE }, + sizeof(uint32_t), true); + if (!status) goto reply_error; + + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { error }, sizeof(uint32_t), true); + if (!status) goto reply_error; + + status = ssl_send_packed_buffer(&out_pbuf, controller->tls_fd); + if (!status) goto reply_error; + */ + + exit_packed_buffer(&out_pbuf); + + break; + + default: + asprintf(&msg, _("Bad protocol command: 0x%08x"), command); + LOG_ERROR(LMT_ERROR, msg); + free(msg); + goto bad_exchange; + break; + + } + + if (has_more_data_in_packed_buffer(&in_pbuf)) + goto next_command; + + exit_packed_buffer(&in_pbuf); + + continue; + + reply_error: + + exit_packed_buffer(&out_pbuf); + + bad_exchange: + + LOG_ERROR(LMT_ERROR, _("Bad exchange")); + + assert(0); + + exit_packed_buffer(&in_pbuf); + + closed_exchange: + + break; + + } + + } + + /* On disparaît des écrans... */ + + g_server_backend_stop(G_SERVER_BACKEND(controller)); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : controller = support pour le suivi d'une connexion. * +* fd = canal de communication réseau ouvert. * +* peer_name = désignation de la connexion. * +* user = désignation de l'utilisateur de la connexion. * +* * +* Description : Prend en compte une connexion nouvelle d'un utilisateur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_cdb_controller_add_client(GCdbController *controller, SSL *fd, const char *peer_name, const char *user) +{ + controller->tls_fd = fd; + + controller->peer_name = strdup(peer_name); + controller->user = strdup(user); + +} + + + + + +#if 0 +/****************************************************************************** +* * +* Paramètres : controller = archive à connecter avec un utilisateur. * +* pbuf = paquet à consituer pour un envoi unique. [OUT] * +* * +* Description : Envoie à tous les clients la nouvelle liste d'instantanés. * +* * +* Retour : Bilan de constitution de la réponse. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_cdb_controller_send_snapshot_update(GCdbController *controller, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + bool do_send; /* Réalisation de l'émission */ + packed_buffer out_pbuf; /* Tampon d'émission */ + + do_send = (pbuf == NULL); + + if (pbuf == NULL) + pbuf = &out_pbuf; + + init_packed_buffer(pbuf); + + result = extend_packed_buffer(pbuf, (uint32_t []) { DBC_SNAPSHOTS_UPDATED }, + sizeof(uint32_t), true); + if (!result) goto bad_reply; + + result = g_db_snapshot_pack_all(archive->snapshot, pbuf); + if (!result) goto bad_reply; + + result = extend_packed_buffer(pbuf, SNAPSHOT_END_MARK, SNAP_ID_HEX_SZ, false); + if (!result) goto bad_reply; + + bad_reply: + + if (do_send || !result) + exit_packed_buffer(pbuf); + + return result; + +} + +#endif |