summaryrefslogtreecommitdiff
path: root/src/analysis/db/client.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-12-01 11:16:12 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-12-01 11:16:12 (GMT)
commit29eae5126251eb0f10d02700bb87dac9893bb445 (patch)
tree34e8906f0d6f3948b80cf59b86f2d5179fa379ad /src/analysis/db/client.c
parent09f07c9a523dce7b8d7e013857f988f727f1a72b (diff)
Encrypted all communications using TLS.
Diffstat (limited to 'src/analysis/db/client.c')
-rw-r--r--src/analysis/db/client.c138
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);