diff options
Diffstat (limited to 'src/analysis/db/client.c')
-rw-r--r-- | src/analysis/db/client.c | 138 |
1 files changed, 111 insertions, 27 deletions
diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 5999b70..2256a21 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -24,11 +24,14 @@ #include "client.h" +#include <assert.h> #include <netdb.h> #include <poll.h> #include <stdio.h> #include <string.h> #include <unistd.h> +#include <openssl/err.h> +#include <openssl/ssl.h> #include <i18n.h> @@ -49,14 +52,19 @@ struct _GDbClient GObject parent; /* A laisser en premier */ char *author; /* Utilisateur représenté */ - char *key_file; /* Accès sa la clef privée */ + //char *key_file; /* Accès sa la clef privée */ const char *name; /* Désignation du binaire */ rle_string hash; /* Empreinte du binaire lié */ GList *collections; /* Collections d'un binaire */ + SSL_CTX *tls_ctx; /* Contexte du chiffrement */ + char *cert_file; /* Fichier du certificat */ + char *key_file; /* Fichier de la clef privée */ + int fd; /* Canal de communication */ + SSL *tls_fd; /* Même canal, mais sécurisé */ GMutex sending_lock; /* Concurrence des envois */ GThread *update; /* Procédure de traitement */ @@ -129,7 +137,12 @@ static void g_db_client_class_init(GDbClientClass *klass) static void g_db_client_init(GDbClient *client) { + client->tls_ctx = NULL; + client->cert_file = NULL; + client->key_file = NULL; + client->fd = -1; + client->tls_fd = NULL; } @@ -153,6 +166,16 @@ static void g_db_client_finalize(GDbClient *client) unset_rle_string(&client->hash); + assert(client->tls_ctx == NULL); + + if (client->cert_file != NULL) + free(client->cert_file); + + if (client->key_file != NULL) + free(client->key_file); + + assert(client->tls_fd == NULL); + G_OBJECT_CLASS(g_db_client_parent_class)->finalize(G_OBJECT(client)); } @@ -342,6 +365,8 @@ bool g_db_client_start_remote(GDbClient *client, const char *host, unsigned shor static bool g_db_client_start_common(GDbClient *client, const char *desc) { + const SSL_METHOD *method; /* Mode du canal sécurisé */ + int ret; /* Bilan d'un appel */ packed_buffer out_pbuf; /* Tampon d'émission */ bool status; /* Bilan d'une opération */ rle_string user; /* Nom d'utilisateur associé */ @@ -354,6 +379,38 @@ static bool g_db_client_start_common(GDbClient *client, const char *desc) DBError error; /* Validation de la connexion */ /** + * Mise en place d'un environnement sécurisé. + */ + + method = TLS_client_method(); + + client->tls_ctx = SSL_CTX_new(method); + + if (client->tls_ctx == NULL) + { + LOG_ERROR_OPENSSL; + goto quick_error; + } + + client->tls_fd = SSL_new(client->tls_ctx); + + if (client->tls_fd == NULL) + { + LOG_ERROR_OPENSSL; + goto tls_error; + } + + SSL_set_fd(client->tls_fd, client->fd); + + ret = SSL_connect(client->tls_fd); + + if (ret != 1) + { + LOG_ERROR_OPENSSL; + goto tls_error; + } + + /** * On réalise l'envoi initial ; le premier paquet doit contenir : * - la commande 'DBC_HELO'. * - le numéro de version du client. @@ -367,18 +424,18 @@ static bool g_db_client_start_common(GDbClient *client, const char *desc) init_packed_buffer(&out_pbuf); status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_HELO }, sizeof(uint32_t), true); - if (!status) goto gdcs_error; + if (!status) goto setup_error; status = extend_packed_buffer(&out_pbuf, (uint32_t []) { CDB_PROTOCOL_VERSION }, sizeof(uint32_t), true); - if (!status) goto gdcs_error; + if (!status) goto setup_error; status = pack_rle_string(&client->hash, &out_pbuf); - if (!status) goto gdcs_error; + if (!status) goto setup_error; dup_into_rle_string(&user, client->author); /* FIXME : src ? */ status = pack_rle_string(&user, &out_pbuf); - if (!status) goto gdcs_error; + if (!status) goto setup_error; checksum = g_checksum_new(G_CHECKSUM_MD5); g_checksum_update(checksum, (guchar *)get_rle_string(&user), get_rle_length(&user)); @@ -386,18 +443,21 @@ static bool g_db_client_start_common(GDbClient *client, const char *desc) g_checksum_free(checksum); key = load_rsa_key(client->key_file, true); - if (key == NULL) goto gdcs_error; + if (key == NULL) goto setup_error; if (!sign_md5_hash(key, md5_digest, sig)) - goto gdcs_error; + { + RSA_free(key); + goto setup_error; + } RSA_free(key); status = extend_packed_buffer(&out_pbuf, sig, RSA_USED_SIZE, false); - if (!status) goto gdcs_error; + if (!status) goto setup_error; - status = send_packed_buffer(&out_pbuf, client->fd); - if (!status) goto gdcs_error; + status = ssl_send_packed_buffer(&out_pbuf, client->tls_fd); + if (!status) goto setup_error; /** * Le serveur doit répondre pour un message type : @@ -408,20 +468,20 @@ static bool g_db_client_start_common(GDbClient *client, const char *desc) init_packed_buffer(&in_pbuf); - status = recv_packed_buffer(&in_pbuf, client->fd); - if (!status) goto gdsc_error; + status = ssl_recv_packed_buffer(&in_pbuf, client->tls_fd); + if (!status) goto comm_error; status = extract_packed_buffer(&in_pbuf, &data, sizeof(uint32_t), true); - if (!status) goto gdsc_error; + if (!status) goto comm_error; if (data != DBC_WELCOME) { log_variadic_message(LMT_ERROR, _("The server '%s' did not welcome us!"), desc); - goto gdsc_error; + goto comm_error; } status = extract_packed_buffer(&in_pbuf, &data, sizeof(uint32_t), true); - if (!status) goto gdsc_error; + if (!status) goto comm_error; error = data; @@ -434,25 +494,25 @@ static bool g_db_client_start_common(GDbClient *client, const char *desc) case DBE_WRONG_VERSION: log_variadic_message(LMT_ERROR, _("The server '%s' does not use our protocol version (0x%08x)..."), desc, CDB_PROTOCOL_VERSION); - goto gdsc_error; + goto comm_error; break; case DBE_XML_VERSION_ERROR: log_variadic_message(LMT_ERROR, _("The archive from the server '%s' does not use our protocol version (0x%08x)..."), desc, CDB_PROTOCOL_VERSION); - goto gdsc_error; + goto comm_error; break; case DBE_DB_LOADING_ERROR: log_variadic_message(LMT_ERROR, _("The server '%s' got into troubles while loading the database...."), desc); - goto gdsc_error; + goto comm_error; break; default: log_variadic_message(LMT_ERROR, _("The server '%s' has run into an error (%u)..."), desc, error); - goto gdsc_error; + goto comm_error; break; } @@ -462,7 +522,7 @@ static bool g_db_client_start_common(GDbClient *client, const char *desc) { log_variadic_message(LMT_ERROR, _("Failed to start a listening thread for the server '%s'!"), desc); - goto gdsc_error; + goto comm_error; } exit_packed_buffer(&out_pbuf); @@ -470,16 +530,23 @@ static bool g_db_client_start_common(GDbClient *client, const char *desc) return true; - gdsc_error: + comm_error: exit_packed_buffer(&in_pbuf); - gdcs_error: + setup_error: exit_packed_buffer(&out_pbuf); unset_rle_string(&user); + tls_error: + + SSL_CTX_free(client->tls_ctx); + client->tls_ctx = NULL; + + quick_error: + close(client->fd); client->fd = -1; @@ -529,7 +596,7 @@ static void *g_db_client_update(GDbClient *client) { reset_packed_buffer(&in_pbuf); - status = recv_packed_buffer(&in_pbuf, fds.fd); + status = ssl_recv_packed_buffer(&in_pbuf, client->tls_fd); if (!status) goto gdcu_bad_exchange; status = extract_packed_buffer(&in_pbuf, &command, sizeof(uint32_t), true); @@ -607,14 +674,28 @@ static void *g_db_client_update(GDbClient *client) void g_db_client_stop(GDbClient *client) { + int ret; /* Bilan d'un appel */ + + /* Canal de communication */ + if (client->fd != -1) + { + assert(client->tls_ctx == NULL); return; + } - close(client->fd); - client->fd = -1; + ret = close(client->fd); + if (ret == -1) perror("close"); g_thread_join(client->update); + client->fd = -1; + + /* Environnement TLS */ + + SSL_CTX_free(client->tls_ctx); + client->tls_ctx = NULL; + } @@ -673,10 +754,13 @@ void g_db_client_put_fd(GDbClient *client) bool g_db_client_save(GDbClient *client) { bool result; /* Bilan partiel à remonter */ + int sent; /* Quantité de données traitées*/ g_db_client_get_fd(client); - result = safe_send(client->fd, (uint32_t []) { htobe32(DBC_SAVE) }, sizeof(uint32_t), 0); + sent = SSL_write(client->tls_fd, (uint32_t []) { htobe32(DBC_SAVE) }, sizeof(uint32_t)); + + result = (sent == sizeof(uint32_t)); g_db_client_put_fd(client); @@ -715,7 +799,7 @@ bool g_db_client_set_last_active(GDbClient *client, timestamp_t timestamp) g_db_client_put_fd(client); if (result) - result = send_packed_buffer(&out_pbuf, client->fd); + result = ssl_send_packed_buffer(&out_pbuf, client->tls_fd); exit_packed_buffer(&out_pbuf); |