summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analysis/db/cdb.c16
-rw-r--r--src/analysis/db/cdb.h3
-rw-r--r--src/analysis/db/client.c138
-rw-r--r--src/analysis/db/keymgn.c5
-rw-r--r--src/analysis/db/keymgn.h3
-rw-r--r--src/analysis/db/server.c163
-rw-r--r--src/common/packed.c79
-rw-r--r--src/common/packed.h7
-rw-r--r--src/core/core.c8
9 files changed, 351 insertions, 71 deletions
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index bfe6238..fd1f5cf 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -56,7 +56,7 @@
/* Informations relatives à un client */
typedef struct _cdb_client
{
- int fd; /* Canal de communication */
+ SSL *ssl_fd; /* Canal de communication */
rle_string user; /* Utilisateur à l'autre bout */
uint64_t last_time; /* Date de dernier envoi */
@@ -779,7 +779,7 @@ static void on_collection_changed(GDbCollection *collec, DBAction action, GDbIte
g_mutex_lock(&archive->clients_access);
for (i = 0; i < archive->count && status; i++)
- status = send_packed_buffer(&pbuf, archive->clients[i].fd);
+ status = ssl_send_packed_buffer(&pbuf, archive->clients[i].ssl_fd);
g_mutex_unlock(&archive->clients_access);
@@ -849,7 +849,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
for (i = 0; i < nfds; i++)
{
- fds[i].fd = archive->clients[i].fd;
+ fds[i].fd = SSL_get_fd(archive->clients[i].ssl_fd);
fds[i].events = POLLIN | POLLPRI;
}
@@ -883,7 +883,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
{
init_packed_buffer(&in_pbuf);
- status = recv_packed_buffer(&in_pbuf, fds[i].fd);
+ status = ssl_recv_packed_buffer(&in_pbuf, archive->clients[i].ssl_fd);
if (!status) goto gcap_bad_exchange;
status = extract_packed_buffer(&in_pbuf, &tmp32, sizeof(uint32_t), true);
@@ -906,7 +906,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
status = extend_packed_buffer(&out_pbuf, (uint32_t []) { error }, sizeof(uint32_t), true);
if (!status) goto gcap_bad_reply;
- status = send_packed_buffer(&out_pbuf, fds[i].fd);
+ status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd);
if (!status) goto gcap_bad_reply;
exit_packed_buffer(&out_pbuf);
@@ -1008,7 +1008,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
* *
******************************************************************************/
-DBError g_cdb_archive_add_client(GCdbArchive *archive, int fd, const rle_string *user)
+DBError g_cdb_archive_add_client(GCdbArchive *archive, SSL *fd, const rle_string *user)
{
GList *iter; /* Boucle de parcours */
@@ -1028,7 +1028,7 @@ DBError g_cdb_archive_add_client(GCdbArchive *archive, int fd, const rle_string
archive->clients = (cdb_client *)realloc(archive->clients, ++archive->count * sizeof(cdb_client));
- archive->clients[archive->count - 1].fd = fd;
+ archive->clients[archive->count - 1].ssl_fd = fd;
dup_into_rle_string(&archive->clients[archive->count - 1].user, get_rle_string(user));
/* Démarrage ou redémarrage du processus d'écoute */
@@ -1072,7 +1072,7 @@ DBError g_cdb_archive_add_client(GCdbArchive *archive, int fd, const rle_string
}
if (status && get_packed_buffer_payload_length(&out_pbuf) > 0)
- status = send_packed_buffer(&out_pbuf, fd);
+ status = ssl_send_packed_buffer(&out_pbuf, fd);
exit_packed_buffer(&out_pbuf);
diff --git a/src/analysis/db/cdb.h b/src/analysis/db/cdb.h
index 15f425c..49a18a5 100644
--- a/src/analysis/db/cdb.h
+++ b/src/analysis/db/cdb.h
@@ -27,6 +27,7 @@
#include <glib-object.h>
#include <stdbool.h>
+#include <openssl/ssl.h>
#include "protocol.h"
@@ -66,7 +67,7 @@ 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 *);
+DBError g_cdb_archive_add_client(GCdbArchive *, SSL *, const rle_string *);
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);
diff --git a/src/analysis/db/keymgn.c b/src/analysis/db/keymgn.c
index 5c66e66..4334896 100644
--- a/src/analysis/db/keymgn.c
+++ b/src/analysis/db/keymgn.c
@@ -39,9 +39,6 @@
/* Mémorise en mémoire la définition d'une identité courante. */
static void store_identity(const x509_entries *, bool);
-/* Fournit le répertoire de travail pour les certifications. */
-static char *get_cert_working_directory(const char *, const char *);
-
/******************************************************************************
@@ -219,7 +216,7 @@ static void store_identity(const x509_entries *entries, bool client)
* *
******************************************************************************/
-static char *get_cert_working_directory(const char *type, const char *name)
+char *get_cert_working_directory(const char *type, const char *name)
{
char *result; /* Chemin à retourner */
char *suffix; /* Fin de la destination */
diff --git a/src/analysis/db/keymgn.h b/src/analysis/db/keymgn.h
index be6ce83..df4f1f5 100644
--- a/src/analysis/db/keymgn.h
+++ b/src/analysis/db/keymgn.h
@@ -35,6 +35,9 @@
/* Charge en mémoire la définition de l'identité courante. */
void load_identity(bool, x509_entries *);
+/* Fournit le répertoire de travail pour les certifications. */
+char *get_cert_working_directory(const char *, const char *);
+
/* Définit les certificats utilisés pour les échanges internes. */
bool register_standalone_certs(const x509_entries *);
diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c
index eaf3775..a996360 100644
--- a/src/analysis/db/server.c
+++ b/src/analysis/db/server.c
@@ -31,6 +31,8 @@
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
#include <i18n.h>
@@ -41,6 +43,7 @@
#include "protocol.h"
#include "misc/rlestr.h"
#include "../../common/io.h"
+#include "../../common/pathname.h"
#include "../../common/xdg.h"
#include "../../core/logs.h"
#include "../../core/params.h"
@@ -76,6 +79,10 @@ struct _GDbServer
registered_user *users; /* Liste d'utilisateurs */
size_t users_count; /* Nombre d'enregistrés */
+ 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 */
int domain; /* Domaine du canal */
gen_sockaddr_t addr; /* Adresse d'écoute générique */
@@ -172,6 +179,10 @@ static void g_db_server_class_init(GDbServerClass *klass)
static void g_db_server_init(GDbServer *server)
{
+ server->tls_ctx = NULL;
+ server->cert_file = NULL;
+ server->key_file = NULL;
+
server->fd = -1;
server->basedir = NULL;
@@ -197,6 +208,8 @@ static void g_db_server_dispose(GDbServer *server)
{
GList *iter; /* Boucle de parcours */
+ g_db_server_stop(server);
+
for (iter = g_list_first(server->archives);
iter != NULL;
iter = g_list_first(server->archives))
@@ -230,6 +243,14 @@ static void g_db_server_finalize(GDbServer *server)
free(server->desc);
+ assert(server->tls_ctx == NULL);
+
+ if (server->cert_file != NULL)
+ free(server->cert_file);
+
+ if (server->key_file != NULL)
+ free(server->key_file);
+
if (server->basedir != NULL)
free(server->basedir);
@@ -255,6 +276,7 @@ GDbServer *g_db_server_new_internal(const char *author, char *kfile)
{
GDbServer *result; /* Adresse à retourner */
bool status; /* Bilan d'un chargement */
+ char *working; /* Répertoire par le client */
result = g_object_new(G_TYPE_DB_SERVER, NULL);
@@ -263,6 +285,15 @@ GDbServer *g_db_server_new_internal(const char *author, char *kfile)
status = g_db_server_register_user(result, author, kfile);
if (!status) goto gdsni_error;
+ /* Paramètres de chiffrement */
+
+ working = get_cert_working_directory("servers", "standalone");
+
+ result->cert_file = build_absolute_filename(working, "server-cert.pem");
+ result->key_file = build_absolute_filename(working, "server-key.pem");
+
+ free(working);
+
/* Détermination du point d'écoute */
result->domain = AF_UNIX;
@@ -395,7 +426,7 @@ GDbServer *g_db_server_new_remote(const char *conf)
result->sock_len = sizeof(struct sockaddr_in);
desclen = INET6_ADDRSTRLEN + 1 + 5 + 1;
- result->desc = (char *)calloc(desclen, sizeof(char));
+ result->desc = calloc(desclen, sizeof(char));
ip = inet_ntop(AF_INET, &result->addr.inet_addr.sin_addr, result->desc, INET6_ADDRSTRLEN);
if (ip == NULL)
@@ -480,8 +511,7 @@ static bool g_db_server_register_user(GDbServer *server, const char *author, cha
if (strlen(author) == 0)
return false;
- server->users = (registered_user *)realloc(server->users,
- ++server->users_count * sizeof(registered_user));
+ server->users = realloc(server->users, ++server->users_count * sizeof(registered_user));
dup_into_rle_string(&server->users[server->users_count - 1].author, author); /* FIXME : src ? */
server->users[server->users_count - 1].key_file = kfile;
@@ -563,6 +593,7 @@ static void *g_db_server_listener(GDbServer *server)
int ret; /* Bilan d'un appel */
gen_sockaddr_t peer; /* Adresse cliente */
int fd; /* Canal établi vers un client */
+ SSL *tls_fd; /* Même canal, mais sécurisé */
rle_string hash; /* Empreinte du binaire visé */
rle_string user; /* Nom d'utilisateur du client */
const char *ip; /* Statut de la conversion */
@@ -598,6 +629,24 @@ static void *g_db_server_listener(GDbServer *server)
continue;
}
+ tls_fd = SSL_new(server->tls_ctx);
+
+ if (tls_fd == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto end_of_client;
+ }
+
+ SSL_set_fd(tls_fd, fd);
+
+ ret = SSL_accept(tls_fd);
+
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto invalid_conn;
+ }
+
/* Initialisation à vide pour les sorties en erreur */
init_dynamic_rle_string(&hash, NULL);
@@ -610,13 +659,13 @@ static void *g_db_server_listener(GDbServer *server)
else if (*((sa_family_t *)&peer) == AF_INET)
{
- peer_name = (char *)calloc(INET6_ADDRSTRLEN + 1 + 5 + 1, sizeof(char));
+ peer_name = calloc(INET6_ADDRSTRLEN + 1 + 5 + 1, sizeof(char));
ip = inet_ntop(AF_INET, &peer.inet_addr.sin_addr, peer_name, INET6_ADDRSTRLEN);
if (ip == NULL)
{
perror("inet_ntop");
- goto gdsl_error;
+ goto id_error;
}
snprintf(peer_name + strlen(ip), 1 + 5, ":%hu", ntohs(peer.inet_addr.sin_port));
@@ -624,7 +673,7 @@ static void *g_db_server_listener(GDbServer *server)
}
else
- goto gdsl_invalid;
+ goto invalid_conn;
error = DBE_NONE;
archive = NULL;
@@ -642,13 +691,13 @@ static void *g_db_server_listener(GDbServer *server)
init_packed_buffer(&in_pbuf);
- status = recv_packed_buffer(&in_pbuf, fd);
+ status = ssl_recv_packed_buffer(&in_pbuf, tls_fd);
if (!status)
{
log_variadic_message(LMT_ERROR, _("Error while getting the initial packet from '%s'..."),
peer_name);
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
status = extract_packed_buffer(&in_pbuf, &cmd, sizeof(uint32_t), true);
@@ -657,7 +706,7 @@ static void *g_db_server_listener(GDbServer *server)
log_variadic_message(LMT_ERROR, _("Error while getting the initial command from '%s'..."),
peer_name);
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
status = extract_packed_buffer(&in_pbuf, &version, sizeof(uint32_t), true);
@@ -666,7 +715,7 @@ static void *g_db_server_listener(GDbServer *server)
log_variadic_message(LMT_ERROR, _("Error while getting the protocol version from '%s'..."),
peer_name);
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
status = unpack_rle_string(&hash, &in_pbuf);
@@ -675,7 +724,7 @@ static void *g_db_server_listener(GDbServer *server)
log_variadic_message(LMT_ERROR, _("Error while getting the binary hash from '%s'..."),
peer_name);
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
status = unpack_rle_string(&user, &in_pbuf);
@@ -684,7 +733,7 @@ static void *g_db_server_listener(GDbServer *server)
log_variadic_message(LMT_ERROR, _("Error while getting the user name from '%s'..."),
peer_name);
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
status = extract_packed_buffer(&in_pbuf, sig, RSA_USED_SIZE, false);
@@ -693,7 +742,7 @@ static void *g_db_server_listener(GDbServer *server)
log_variadic_message(LMT_ERROR, _("Error while getting the signature from '%s'..."),
peer_name);
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
if (cmd != DBC_HELO)
@@ -701,7 +750,7 @@ static void *g_db_server_listener(GDbServer *server)
log_variadic_message(LMT_ERROR, _("The client from '%s' did not introduce itself!"),
peer_name);
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
if (version != CDB_PROTOCOL_VERSION)
@@ -709,7 +758,7 @@ static void *g_db_server_listener(GDbServer *server)
log_variadic_message(LMT_ERROR, _("The client from '%s' does not use the same protocol: 0x%08x vs 0x%08x..."),
peer_name, be32toh(version), CDB_PROTOCOL_VERSION);
error = DBE_WRONG_VERSION;
- goto gdsl_error_sending;
+ goto error_sending;
}
if (is_rle_string_empty(&hash))
@@ -717,7 +766,7 @@ static void *g_db_server_listener(GDbServer *server)
log_variadic_message(LMT_ERROR, _("The submitted binary hash from '%s' is empty!"),
peer_name);
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
if (is_rle_string_empty(&user))
@@ -725,14 +774,14 @@ static void *g_db_server_listener(GDbServer *server)
log_variadic_message(LMT_ERROR, _("No user is associated with the client from '%s'..."),
peer_name);
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
if (!g_db_server_is_registered_user(server, &user, sig))
{
log_variadic_message(LMT_ERROR, _("This user is not registered."));
error = DBE_BAD_EXCHANGE;
- goto gdsl_error_sending;
+ goto error_sending;
}
/**
@@ -761,20 +810,20 @@ static void *g_db_server_listener(GDbServer *server)
* ou 'DBE_WRONG_VERSION' ... 'DBE_LOADING_ERROR').
*/
- gdsl_error_sending:
+ error_sending:
exit_packed_buffer(&in_pbuf);
init_packed_buffer(&out_pbuf);
status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_WELCOME }, sizeof(uint32_t), true);
- if (!status) goto gdsl_out_error;
+ if (!status) goto out_error;
status = extend_packed_buffer(&out_pbuf, (uint32_t []) { error }, sizeof(uint32_t), true);
- if (!status) goto gdsl_out_error;
+ if (!status) goto out_error;
- status = send_packed_buffer(&out_pbuf, fd);
- if (!status) goto gdsl_out_error;
+ status = ssl_send_packed_buffer(&out_pbuf, tls_fd);
+ if (!status) goto out_error;
/**
* L'ajout dans la liste des clients connectés provoque un envoi de mises à jour.
@@ -790,7 +839,7 @@ static void *g_db_server_listener(GDbServer *server)
if (iter == NULL)
server->archives = g_list_append(server->archives, archive);
- error = g_cdb_archive_add_client(archive, fd, &user);
+ error = g_cdb_archive_add_client(archive, tls_fd, &user);
exit_packed_buffer(&out_pbuf);
@@ -805,7 +854,7 @@ static void *g_db_server_listener(GDbServer *server)
assert(error != DBE_NONE);
- gdsl_out_error:
+ out_error:
exit_packed_buffer(&out_pbuf);
@@ -813,14 +862,18 @@ static void *g_db_server_listener(GDbServer *server)
if (iter == NULL && archive != NULL)
g_object_unref(G_OBJECT(archive));
- gdsl_error:
+ id_error:
free(peer_name);
exit_rle_string(&hash);
exit_rle_string(&user);
- gdsl_invalid:
+ invalid_conn:
+
+ SSL_free(tls_fd);
+
+ end_of_client:
close(fd);
@@ -847,10 +900,49 @@ static void *g_db_server_listener(GDbServer *server)
bool g_db_server_start(GDbServer *server)
{
+ const SSL_METHOD *method; /* Mode du canal sécurisé */
int ret; /* Bilan d'un appel */
bool status; /* Bilan d'un nettoyage */
int backlog; /* Nombre de connexions maximal*/
+ /* Définition d'un environnement TLS */
+
+ method = TLS_server_method();
+
+ server->tls_ctx = SSL_CTX_new(method);
+
+ if (server->tls_ctx == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto quick_error;
+ }
+
+ ret = SSL_CTX_use_certificate_file(server->tls_ctx, server->cert_file, SSL_FILETYPE_PEM);
+
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto tls_error;
+ }
+
+ ret = SSL_CTX_use_PrivateKey_file(server->tls_ctx, server->key_file, SSL_FILETYPE_PEM);
+
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto tls_error;
+ }
+
+ ret = SSL_CTX_check_private_key(server->tls_ctx);
+
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto tls_error;
+ }
+
+ /* Mise en place d'un canal de communication */
+
server->fd = socket(server->domain, SOCK_STREAM, 0);
if (server->fd == -1)
{
@@ -899,6 +991,13 @@ bool g_db_server_start(GDbServer *server)
close(server->fd);
server->fd = -1;
+ tls_error:
+
+ SSL_CTX_free(server->tls_ctx);
+ server->tls_ctx = NULL;
+
+ quick_error:
+
return false;
}
@@ -920,8 +1019,13 @@ void g_db_server_stop(GDbServer *server)
{
int ret; /* Bilan d'un appel */
+ /* Canal de communication */
+
if (server->fd == -1)
+ {
+ assert(server->tls_ctx == NULL);
return;
+ }
ret = shutdown(server->fd, SHUT_RDWR);
if (ret == -1) perror("shutdown");
@@ -936,6 +1040,9 @@ void g_db_server_stop(GDbServer *server)
if (server->clean_socket != NULL)
server->clean_socket(server);
- /* TODO : s'occuper des archives ouvertes */
+ /* Environnement TLS */
+
+ SSL_CTX_free(server->tls_ctx);
+ server->tls_ctx = NULL;
}
diff --git a/src/common/packed.c b/src/common/packed.c
index d956a42..e06e4bb 100644
--- a/src/common/packed.c
+++ b/src/common/packed.c
@@ -343,7 +343,6 @@ bool write_packed_buffer(packed_buffer *pbuf, int fd)
}
-
/******************************************************************************
* *
* Paramètres : pbuf = paquet de données à constituer. [OUT] *
@@ -409,3 +408,81 @@ bool send_packed_buffer(packed_buffer *pbuf, int fd)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : pbuf = paquet de données à constituer. [OUT] *
+* fd = flux ouvert en lecture. *
+* *
+* Description : Réceptionne des données depuis un flux réseau chiffré. *
+* *
+* Retour : true si toutes les données ont été reçues, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ssl_recv_packed_buffer(packed_buffer *pbuf, SSL *fd)
+{
+ bool result; /* Bilan à retourner */
+ uint32_t used; /* Taille de charge utile */
+ int got; /* Quantité de données traitées*/
+
+ got = SSL_read(fd, &used, sizeof(uint32_t));
+
+ result = (got == sizeof(uint32_t));
+
+ if (result)
+ {
+ assert(pbuf->pos == sizeof(uint32_t));
+
+ if ((pbuf->pos + used) > pbuf->allocated)
+ {
+ pbuf->allocated = pbuf->pos + used;
+ pbuf->data = realloc(pbuf->data, pbuf->allocated * sizeof(uint8_t));
+ }
+
+ pbuf->used = used;
+
+ got = SSL_read(fd, pbuf->data + pbuf->pos, used);
+
+ result = (got == used);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pbuf = paquet de données à émettre. *
+* fd = flux ouvert en écriture. *
+* *
+* Description : Envoie des données au travers un flux réseau chiffré. *
+* *
+* Retour : true si toutes les données ont été émises, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ssl_send_packed_buffer(packed_buffer *pbuf, SSL *fd)
+{
+ bool result; /* Bilan à retourner */
+ int quantity; /* Nombre de données à traiter */
+ int sent; /* Quantité de données traitées*/
+
+ *((uint32_t *)pbuf->data) = pbuf->used;
+
+ quantity = sizeof(uint32_t) + pbuf->used;
+
+ sent = SSL_write(fd, pbuf->data, quantity);
+
+ result = (quantity == sent);
+
+ return result;
+
+}
diff --git a/src/common/packed.h b/src/common/packed.h
index d25c947..5c724e0 100644
--- a/src/common/packed.h
+++ b/src/common/packed.h
@@ -27,6 +27,7 @@
#include <stdbool.h>
#include <stdint.h>
+#include <openssl/ssl.h>
#include <sys/types.h>
@@ -76,6 +77,12 @@ bool recv_packed_buffer(packed_buffer *, int);
/* Envoie des données au travers un flux réseau. */
bool send_packed_buffer(packed_buffer *, int);
+/* Réceptionne des données depuis un flux réseau chiffré. */
+bool ssl_recv_packed_buffer(packed_buffer *, SSL *);
+
+/* Envoie des données au travers un flux réseau chiffré. */
+bool ssl_send_packed_buffer(packed_buffer *, SSL *);
+
#endif /* _COMMON_PACKED_H */
diff --git a/src/core/core.c b/src/core/core.c
index fe8ccbb..cdcfce5 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
+#include <openssl/err.h>
#include <openssl/ssl.h>
@@ -82,11 +83,12 @@ bool load_all_basic_components(void)
(GBoxedCopyFunc)dup_vmpa,
(GBoxedFreeFunc)delete_vmpa);
- result &= load_main_config_parameters();
-
+ ERR_load_crypto_strings();
SSL_load_error_strings();
SSL_library_init();
+ result &= load_main_config_parameters();
+
result &= ensure_user_has_rsa_keys();
result &= g_generic_config_read(get_main_configuration());
@@ -140,4 +142,6 @@ void unload_all_basic_components(void)
unload_main_config_parameters();
+ ERR_free_strings();
+
}