summaryrefslogtreecommitdiff
path: root/src/analysis/db/server.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-04-09 22:59:38 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-04-09 22:59:38 (GMT)
commit5ad85cf30b2355ca727904d1a0d25240283813b3 (patch)
tree1e1fdce3b7be4bf878161b4e9001686dd0d89ba3 /src/analysis/db/server.c
parent865be356c53afc3bdeae21c640bf0c3d5433fc4b (diff)
Signed and verified the MD5 hash of a given user name.
Diffstat (limited to 'src/analysis/db/server.c')
-rw-r--r--src/analysis/db/server.c169
1 files changed, 162 insertions, 7 deletions
diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c
index 3107231..360b266 100644
--- a/src/analysis/db/server.c
+++ b/src/analysis/db/server.c
@@ -35,6 +35,7 @@
#include "cdb.h"
+#include "keymgn.h"
#include "protocol.h"
#include "misc/rlestr.h"
#include "../../common/io.h"
@@ -43,6 +44,14 @@
+/* Utilisateur enregistré */
+typedef struct _registered_user
+{
+ rle_string author; /* Désignation d'utilisateur */
+ char *key_file; /* Chemin vers sa clef publique*/
+
+} registered_user;
+
/* Informations relatives à un client */
typedef struct _cdb_client
{
@@ -60,6 +69,9 @@ struct _GDbServer
{
GObject parent; /* A laisser en premier */
+ registered_user *users; /* Liste d'utilisateurs */
+ size_t users_count; /* Nombre d'enregistrés */
+
int fd; /* Canal de communication */
char *hostname; /* Désignation humaine */
char *desc; /* Désignation du serveur */
@@ -91,12 +103,18 @@ static void g_db_server_init(GDbServer *);
/* Procède à la libération totale de la mémoire. */
static void g_db_server_finalize(GDbServer *);
+/* Supprime toute trace d'utilisateur inscrit. */
+static void g_db_server_unregister_all_user(GDbServer *);
+
+/* Inscrit un nouvel utilisateur comme étant enregistré. */
+static bool g_db_server_register_user(GDbServer *, const char *, char *);
+
+/* Inscrit un nouvel utilisateur comme étant enregistré. */
+static bool g_db_server_is_registered_user(GDbServer *, const rle_string *, unsigned char *);
+
/* Assure l'accueil des nouveaux clients. */
static void *g_db_server_listener(GDbServer *);
-/* Assure le traitement des requêtes de clients. */
-//static void *g_db_server_process(cdb_client **);
-
/* Indique le type défini pour une description de serveur à l'écoute. */
@@ -161,6 +179,8 @@ static void g_db_server_init(GDbServer *server)
static void g_db_server_finalize(GDbServer *server)
{
+ g_db_server_unregister_all_user(server);
+
free(server->hostname);
G_OBJECT_CLASS(g_db_server_parent_class)->finalize(G_OBJECT(server));
@@ -170,27 +190,30 @@ static void g_db_server_finalize(GDbServer *server)
/******************************************************************************
* *
-* Paramètres : host = hôte à représenter pour le service. *
+* Paramètres : author = utilisateur à représenter via le client. *
+* kfile = clef menant à sa clef publique. *
+* host = hôte à représenter pour le service. *
* port = port de connexion pour les clients. *
* *
* Description : Prépare un serveur de BD pour les clients. *
* *
-* Retour : Structure mise en plae ou NULL en cas d'échec. *
+* Retour : Structure mise en place ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-GDbServer *g_db_server_new(const char *host, short port)
+GDbServer *g_db_server_new(const char *author, char *kfile, const char *host, short port)
{
GDbServer *result; /* Adresse à retourner */
struct hostent *hp; /* Informations sur l'hôte */
size_t desclen; /* Taille de désignation */
-
const char *ip; /* Adresse IPv4 ou IPv6 */
result = g_object_new(G_TYPE_DB_SERVER, NULL);
+ /* ... =*/g_db_server_register_user(result, author, kfile);
+
result->hostname = strdup(host);
hp = gethostbyname(host);
@@ -232,6 +255,121 @@ GDbServer *g_db_server_new(const char *host, short port)
* *
* Paramètres : server = serveur pour les accès distants à manipuler. *
* *
+* Description : Supprime toute trace d'utilisateur inscrit. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_server_unregister_all_user(GDbServer *server)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < server->users_count; i++)
+ {
+ exit_rle_string(&server->users[i].author);
+ free(server->users[i].key_file);
+ }
+
+ if (server->users != NULL)
+ free(server->users);
+
+ server->users = NULL;
+ server->users_count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : server = serveur pour les accès distants à manipuler. *
+* author = utilisateur à représenter via le client. *
+* kfile = clef menant à sa clef publique. *
+* *
+* Description : Inscrit un nouvel utilisateur comme étant enregistré. *
+* *
+* Retour : Bilan de l'inscription. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_server_register_user(GDbServer *server, const char *author, char *kfile)
+{
+ if (strlen(author) == 0)
+ return false;
+
+ server->users = (registered_user *)realloc(server->users,
+ ++server->users_count * sizeof(registered_user));
+
+ init_rle_string(&server->users[server->users_count - 1].author, author);
+ server->users[server->users_count - 1].key_file = kfile;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : server = serveur pour les accès distants à manipuler. *
+* author = utilisateur à représenter via le client. *
+* sig = signature d'utilisateur à valider. *
+* *
+* Description : Inscrit un nouvel utilisateur comme étant enregistré. *
+* *
+* Retour : true si l'utilisateur est bien enregistré, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_server_is_registered_user(GDbServer *server, const rle_string *author, unsigned char *sig)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ GChecksum *checksum; /* Empreinte MD5 à signer */
+ unsigned char md5_digest[16]; /* Empreinte MD5 calculée */
+ RSA *key; /* Clef pour la signature */
+
+ result = false;
+
+ /* Recherche de l'utilisateur */
+
+ for (i = 0; i < server->users_count; i++)
+ if (cmp_rle_string(&server->users[i].author, author) == 0)
+ break;
+
+ if (i == server->users_count)
+ goto gdsiru_exit;
+
+ /* Validation de la signature présentée */
+
+ checksum = g_checksum_new(G_CHECKSUM_MD5);
+ g_checksum_update(checksum, (guchar *)get_rle_string(author), get_rle_length(author));
+ g_checksum_get_digest(checksum, (guint8 *)md5_digest, (gsize []) { sizeof(md5_digest) });
+ g_checksum_free(checksum);
+
+ key = load_rsa_key(server->users[i].key_file, false);
+ if (key == NULL) goto gdsiru_exit;
+
+ result = verify_md5_hash(key, md5_digest, sig);
+
+ RSA_free(key);
+
+ gdsiru_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : server = serveur pour les accès distants à manipuler. *
+* *
* Description : Assure l'accueil des nouveaux clients. *
* *
* Retour : NULL. *
@@ -254,6 +392,7 @@ static void *g_db_server_listener(GDbServer *server)
uint32_t version; /* Version du client lue */
rle_string hash; /* Empreinte du binaire visé */
rle_string user; /* Nom d'utilisateur du client */
+ unsigned char sig[RSA_USED_SIZE]; /* Signature effectuée */
GList *iter; /* Boucle de parcours */
fds.fd = server->fd;
@@ -293,6 +432,7 @@ static void *g_db_server_listener(GDbServer *server)
* - le numéro de version du client.
* - l'empreinte du binaire analysé.
* - l'identifiant de l'utilisateur effectuant des modifications.
+ * - la signature de l'empreinte MD5 de l'identifiant.
*
* Tout ceci est à synchroniser avec la fonction g_db_client_start().
*/
@@ -329,6 +469,14 @@ static void *g_db_server_listener(GDbServer *server)
goto gdsl_error_sending;
}
+ if (!safe_recv(fd, sig, RSA_USED_SIZE, 0))
+ {
+ log_variadic_message(LMT_ERROR, _("Error while getting the signature from '%s:%hu'..."),
+ source, ntohs(peer.sin_port));
+ error = DBE_BAD_EXCHANGE;
+ goto gdsl_error_sending;
+ }
+
if (be32toh(cmd) != DBC_HELO)
{
log_variadic_message(LMT_ERROR, _("The client from '%s:%hu' did not introduce itself!"),
@@ -361,6 +509,13 @@ static void *g_db_server_listener(GDbServer *server)
goto gdsl_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;
+ }
+
/**
* On met en place le maximum ici, de manière à pouvoir indiquer une erreur
* en cas d'échec, et être le plus précis possible dans la courte réponse.