diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/analysis/db/cdb.c | 16 | ||||
| -rw-r--r-- | src/analysis/db/cdb.h | 3 | ||||
| -rw-r--r-- | src/analysis/db/client.c | 138 | ||||
| -rw-r--r-- | src/analysis/db/keymgn.c | 5 | ||||
| -rw-r--r-- | src/analysis/db/keymgn.h | 3 | ||||
| -rw-r--r-- | src/analysis/db/server.c | 163 | ||||
| -rw-r--r-- | src/common/packed.c | 79 | ||||
| -rw-r--r-- | src/common/packed.h | 7 | ||||
| -rw-r--r-- | src/core/core.c | 8 | 
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(); +  } | 
