diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2016-04-09 22:59:38 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2016-04-09 22:59:38 (GMT) |
commit | 5ad85cf30b2355ca727904d1a0d25240283813b3 (patch) | |
tree | 1e1fdce3b7be4bf878161b4e9001686dd0d89ba3 /src/analysis/db/server.c | |
parent | 865be356c53afc3bdeae21c640bf0c3d5433fc4b (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.c | 169 |
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. |