summaryrefslogtreecommitdiff
path: root/src/analysis/db/server.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-08-18 21:55:24 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-08-18 21:55:24 (GMT)
commita0a7b6c1e05c78ae433f353d15e3366107b67d03 (patch)
treebca0b187778cf016c6131bfc982b08c67a38442b /src/analysis/db/server.c
parent161c0f8ab227af5033b1b6456607b9b9c3bc60df (diff)
Inserted storages and collections into loaded binaries (first steps).
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@389 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/db/server.c')
-rw-r--r--src/analysis/db/server.c262
1 files changed, 180 insertions, 82 deletions
diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c
index 3d75b71..42688c8 100644
--- a/src/analysis/db/server.c
+++ b/src/analysis/db/server.c
@@ -29,10 +29,15 @@
#include <poll.h>
#include <string.h>
#include <unistd.h>
+#include <arpa/inet.h>
#include <sys/socket.h>
+#include "cdb.h"
#include "protocol.h"
+#include "misc/rlestr.h"
+#include "../../common/io.h"
+#include "../../core/params.h"
#include "../../gui/panels/log.h"
@@ -56,10 +61,12 @@ struct _GDbServer
int fd; /* Canal de communication */
char *hostname; /* Désignation humaine */
+ char *desc; /* Désignation du serveur */
struct sockaddr_in addr; /* Adresse d'écoute */
GThread *listener; /* Procédure de traitement */
+ GList *archives; /* Liste des binaires ouverts */
cdb_client **clients; /* Connexions en place */
size_t count; /* Quantité de clients */
GMutex mutex; /* Verrou pour l'accès */
@@ -87,7 +94,7 @@ static void g_db_server_finalize(GDbServer *);
static void *g_db_server_listener(GDbServer *);
/* Assure le traitement des requêtes de clients. */
-static void *g_db_server_process(cdb_client **);
+//static void *g_db_server_process(cdb_client **);
@@ -177,19 +184,38 @@ GDbServer *g_db_server_new(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);
result->hostname = strdup(host);
hp = gethostbyname(host);
- if (hp == NULL) goto gdsn_error;
+ if (hp == NULL)
+ {
+ perror("gethostbyname");
+ goto gdsn_error;
+ }
result->addr.sin_family = hp->h_addrtype;
memcpy(&result->addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
result->addr.sin_port = htons(port);
+ desclen = INET6_ADDRSTRLEN + 1 + 5 + 1;
+ result->desc = (char *)calloc(desclen, sizeof(char));
+
+ ip = inet_ntop(AF_INET, &result->addr.sin_addr, result->desc, INET6_ADDRSTRLEN);
+ if (ip == NULL)
+ {
+ perror("inet_ntop");
+ goto gdsn_error;
+ }
+
+ snprintf(result->desc + strlen(ip), 1 + 5, ":%hu", port);
+
return result;
gdsn_error:
@@ -219,7 +245,27 @@ static void *g_db_server_listener(GDbServer *server)
int ret; /* Bilan d'un appel */
struct sockaddr_in peer; /* Adresse cliente */
int fd; /* Canal établi vers un client */
- cdb_client *client; /* Mémorisation pour poursuite */
+ char source[INET6_ADDRSTRLEN]; /* Adresse du client (IPv4/6) */
+ const char *ip; /* Statut de la conversion */
+
+
+ DBError error; /* Validation de la connexion */
+
+ uint32_t data; /* Mot de données lues */
+
+
+ rle_string hash; /* Empreinte du binaire visé */
+ rle_string user; /* Nom d'utilisateur du client */
+
+ GList *iter; /* Boucle de parcours */
+ GCdbArchive *archive; /* Destinataire final du client*/
+
+
+
+ //cdb_client *client; /* Mémorisation pour poursuite */
+
+
+
fds.fd = server->fd;
fds.events = POLLIN | POLLPRI;
@@ -236,8 +282,122 @@ static void *g_db_server_listener(GDbServer *server)
if (fds.revents & (POLLIN | POLLPRI))
{
fd = accept(server->fd, &peer, (socklen_t []) { sizeof(struct sockaddr_in) });
- if (fd == -1) continue;
+ if (fd == -1)
+ {
+ perror("accept");
+ continue;
+ }
+
+ ip = inet_ntop(AF_INET, &peer.sin_addr, source, sizeof(source));
+ if (ip == NULL)
+ {
+ perror("inet_ntop");
+ goto gdsl_error;
+ }
+
+ error = DBE_NONE;
+
+ /**
+ * Le premier "paquet" reçu de la part d'un client doit contenir les informations suivantes :
+ * - la commande 'DBC_HELO'.
+ * - le numéro de version du client.
+ * - l'empreinte du binaire analysé.
+ * - l'identifiant de l'utilisateur effectuant des modifications.
+ *
+ * Tout ceci est à synchroniser avec la fonction g_db_client_start().
+ */
+
+ if (!safe_recv(fd, &data, sizeof(uint32_t), 0))
+ goto gdsl_error;
+
+ if (be32toh(data) != DBC_HELO)
+ {
+ log_variadic_message(LMT_ERROR, _("The client from '%s:%hu' did not introduce itself!"),
+ source, ntohs(peer.sin_port));
+ goto gdsl_error;
+ }
+
+ if (!safe_recv(fd, &data, sizeof(uint32_t), 0))
+ goto gdsl_error;
+
+ if (be32toh(data) != CDB_PROTOCOL_VERSION)
+ {
+ log_variadic_message(LMT_ERROR, _("The client from '%s:%hu' does not use the same protocol: 0x%08x vs 0x%08x..."),
+ source, ntohs(peer.sin_port), be32toh(data), CDB_PROTOCOL_VERSION);
+ error = DBE_WRONG_VERSION;
+ goto gdsl_error_sending;
+ }
+
+ if (!recv_rle_string(&hash, fd, 0) || is_rle_string_empty(&hash))
+ {
+ log_variadic_message(LMT_ERROR, _("Error while getting the binary hash from '%s:%hu'..."),
+ source, ntohs(peer.sin_port));
+ goto gdsl_error;
+ }
+
+ if (!recv_rle_string(&user, fd, 0) || is_rle_string_empty(&user))
+ {
+ log_variadic_message(LMT_ERROR, _("Error while getting the user name from '%s:%hu'..."),
+ source, ntohs(peer.sin_port));
+ goto gdsl_error;
+ }
+
+ /**
+ * 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.
+ */
+
+ for (iter = g_list_first(server->archives);
+ iter != NULL;
+ iter = g_list_next(iter))
+ {
+ archive = G_CDB_ARCHIVE(iter->data);
+ if (g_cdb_archive_compare_hash(archive, &hash) == 0)
+ break;
+ }
+
+ if (iter == NULL)
+ {
+ archive = g_cdb_archive_new(server->desc, &hash, &user, &error);
+
+ if (archive != NULL)
+ server->archives = g_list_append(server->archives, archive);
+
+ }
+
+ if (archive != NULL)
+ error = g_cdb_archive_add_client(archive, fd, &user);
+
+ /**
+ * Le serveur doit répondre pour un message type :
+ * - la commande 'DBC_WELCOME'.
+ * - un identifiant d'erreur ('DBE_NONE' ou 'DBE_WRONG_VERSION').
+ */
+
+ gdsl_error_sending:
+
+ if (!safe_send(fd, (uint32_t []) { htobe32(DBC_WELCOME) }, sizeof(uint32_t), MSG_MORE))
+ goto gdsl_error;
+
+ if (!safe_send(fd, (uint32_t []) { htobe32(error) }, sizeof(uint32_t), 0))
+ goto gdsl_error;
+
+ if (error == DBE_NONE) continue;
+
+ gdsl_error:
+
+
+ /* free RLE !!!! */
+
+ close(fd);
+
+ }
+
+
+
+
+#if 0
g_mutex_lock(&server->mutex);
client = (cdb_client *)calloc(1, sizeof(cdb_client));
@@ -256,80 +416,13 @@ static void *g_db_server_listener(GDbServer *server)
&server->clients[server->count - 1]);
g_mutex_unlock(&server->mutex);
+#endif
- }
- }
- return NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : client = informations sur une connexion établie à utiliser. *
-* *
-* Description : Assure le traitement des requêtes de clients. *
-* *
-* Retour : NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void *g_db_server_process(cdb_client **client)
-{
- struct pollfd fds; /* Surveillance des flux */
- int ret; /* Bilan d'un appel */
- GDbServer *server; /* Accès facile en mémoire */
- size_t index; /* Indice courant du client */
- size_t remaining; /* Quantité à déplacer */
-
- fds.fd = (*client)->fd;
- fds.events = POLLIN | POLLPRI;
-
- while (1)
- {
- ret = poll(&fds, 1, -1);
- if (ret != 1) continue;
-
- printf("fds.revents :: %x\n", fds.revents);
-
- /* Le canal est fermé, une sortie doit être demandée... */
- if (fds.revents & POLLNVAL)
- break;
-
- if (fds.revents & (POLLIN | POLLPRI))
- {
-
- /* TODO */
- pause();
-
-
- }
}
- /* Retrait de la liste avant la terminaison */
-
- server = (*client)->server;
-
- g_mutex_lock(&server->mutex);
-
- index = (client - server->clients);
- remaining = server->count - index - 1;
-
- if (remaining > 0)
- memmove(&server->clients[index], &server->clients[index + 1],
- remaining * sizeof(cdb_client *));
-
- g_object_unref(G_OBJECT(server));
-
- free(*client);
-
- g_mutex_unlock(&server->mutex);
-
return NULL;
}
@@ -350,6 +443,7 @@ static void *g_db_server_process(cdb_client **client)
bool g_db_server_start(GDbServer *server)
{
int ret; /* Bilan d'un appel */
+ int backlog; /* Nombre de connexions maximal*/
server->fd = socket(AF_INET, SOCK_STREAM, 0);
if (server->fd == -1)
@@ -362,27 +456,24 @@ bool g_db_server_start(GDbServer *server)
if (ret == -1)
{
perror("setsockopt");
- close(server->fd);
- server->fd = -1;
- return false;
+ goto gdss_error;
}
ret = bind(server->fd, (struct sockaddr *)&server->addr, sizeof(struct sockaddr_in));
if (ret == -1)
{
perror("bind");
- close(server->fd);
- server->fd = -1;
- return false;
+ goto gdss_error;
}
- ret = listen(server->fd, CDB_SEVER_BACKLOG);
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_SERVER_BACKLOG, &backlog))
+ goto gdss_error;
+
+ ret = listen(server->fd, backlog);
if (ret == -1)
{
perror("listen");
- close(server->fd);
- server->fd = -1;
- return false;
+ goto gdss_error;
}
server->listener = g_thread_new("cdb_listener", (GThreadFunc)g_db_server_listener, server);
@@ -392,6 +483,13 @@ bool g_db_server_start(GDbServer *server)
return true;
+ gdss_error:
+
+ close(server->fd);
+ server->fd = -1;
+
+ return false;
+
}