summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2022-02-21 06:54:10 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2022-02-21 06:54:10 (GMT)
commit8bf77ba6e5ef40d8bb936dc952ac2c8cc30aab3e (patch)
tree934661f2f30e0b8d23793f52084c736052e85f7c
parent8ce244d136b32b43d8553866747c68b503b2d10a (diff)
Make the server drive the network exchanges.
-rw-r--r--plugins/pychrysalide/analysis/db/analyst.c4
-rw-r--r--plugins/pychrysalide/analysis/db/constants.c43
-rw-r--r--plugins/pychrysalide/analysis/db/constants.h3
-rw-r--r--src/analysis/db/analyst.c140
-rw-r--r--src/analysis/db/analyst.h14
-rw-r--r--src/analysis/db/cdb.c133
-rw-r--r--src/analysis/db/protocol.h31
-rw-r--r--src/analysis/db/server.c4
-rw-r--r--tests/analysis/db/analyst.py188
-rw-r--r--tests/analysis/db/conn.py43
10 files changed, 559 insertions, 44 deletions
diff --git a/plugins/pychrysalide/analysis/db/analyst.c b/plugins/pychrysalide/analysis/db/analyst.c
index 289db31..c55f34a 100644
--- a/plugins/pychrysalide/analysis/db/analyst.c
+++ b/plugins/pychrysalide/analysis/db/analyst.c
@@ -36,6 +36,7 @@
#include "client.h"
#include "collection.h"
+#include "constants.h"
#include "../content.h"
#include "../loaded.h"
#include "../../access.h"
@@ -901,6 +902,9 @@ bool ensure_python_analyst_client_is_registered(void)
if (!register_class_for_pygobject(dict, G_TYPE_ANALYST_CLIENT, type, get_python_hub_client_type()))
return false;
+ if (!define_loading_status_hint_constants(type))
+ return false;
+
}
return true;
diff --git a/plugins/pychrysalide/analysis/db/constants.c b/plugins/pychrysalide/analysis/db/constants.c
index 8e7765a..5e8c20d 100644
--- a/plugins/pychrysalide/analysis/db/constants.c
+++ b/plugins/pychrysalide/analysis/db/constants.c
@@ -25,6 +25,7 @@
#include "constants.h"
+#include <analysis/db/analyst.h>
#include <analysis/db/item.h>
#include <analysis/db/server.h>
@@ -152,3 +153,45 @@ bool define_hub_server_constants(PyTypeObject *type)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes pour les indications de chargement. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_loading_status_hint_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ values = PyDict_New();
+
+ result = add_const_to_group(values, "READY", LSH_READY);
+ if (result) result = add_const_to_group(values, "ON_WAIT_LIST", LSH_ON_WAIT_LIST);
+ if (result) result = add_const_to_group(values, "NEED_CONTENT", LSH_NEED_CONTENT);
+ if (result) result = add_const_to_group(values, "NEED_FORMAT", LSH_NEED_FORMAT);
+ if (result) result = add_const_to_group(values, "NEED_ARCH", LSH_NEED_ARCH);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type_with_pyg_enum(type, false, "LoadingStatusHint", values,
+ "Indication about a loading process state.",
+ G_TYPE_LOADING_STATUS_HINT);
+
+ exit:
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/db/constants.h b/plugins/pychrysalide/analysis/db/constants.h
index 5f0afeb..ea7a0c0 100644
--- a/plugins/pychrysalide/analysis/db/constants.h
+++ b/plugins/pychrysalide/analysis/db/constants.h
@@ -39,6 +39,9 @@ bool define_db_item_constants(PyTypeObject *);
/* Définit les constantes pour les serveurs de données. */
bool define_hub_server_constants(PyTypeObject *);
+/* Définit les constantes pour les indications de chargement. */
+bool define_loading_status_hint_constants(PyTypeObject *);
+
#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_CONSTANTS_H */
diff --git a/src/analysis/db/analyst.c b/src/analysis/db/analyst.c
index ab12cc1..2e1cc23 100644
--- a/src/analysis/db/analyst.c
+++ b/src/analysis/db/analyst.c
@@ -35,6 +35,17 @@
+
+
+
+
+/* ------------------------- PRISES EN COMPTE DES COMMANDES ------------------------- */
+
+
+
+
+
+
/* Description de client à l'écoute (instance) */
struct _GAnalystClient
{
@@ -65,6 +76,8 @@ struct _GAnalystClientClass
/* Signaux */
+ void (* ready) (GAnalystClient *);
+ void (* server_status_changed) (GAnalystClient *, LoadingStatusHint);
void (* snapshots_updated) (GAnalystClient *);
void (* snapshot_changed) (GAnalystClient *);
@@ -97,6 +110,56 @@ static bool g_analyst_client_update_current_snapshot(GAnalystClient *, packed_bu
+/* ------------------------- PRISES EN COMPTE DES COMMANDES ------------------------- */
+
+
+/* Prend en compte une évolution du statut côté serveur. */
+static bool g_analyst_client_handle_loading_hints(GAnalystClient *, packed_buffer_t *);
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUES POUR LA GLIB */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Définit un type GLib pour l'énumération "LoadingStatusHint". *
+* *
+* Retour : Type GLib enregistré. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GType g_loading_status_hint_type(void)
+{
+ static GType result = 0;
+
+ static const GEnumValue values[] = {
+ { LSH_READY, "LSH_READY", "ready" },
+ { LSH_ON_WAIT_LIST, "LSH_ON_WAIT_LIST", "on_wait_list" },
+ { LSH_NEED_CONTENT, "LSH_NEED_CONTENT", "need_content" },
+ { LSH_NEED_FORMAT, "LSH_NEED_FORMAT", "need_format" },
+ { LSH_NEED_ARCH, "LSH_NEED_ARCH", "need_arch" },
+ { 0, NULL, NULL }
+ };
+
+ if (result == 0)
+ result = g_enum_register_static(g_intern_static_string("LoadingStatusHint"), values);
+
+ return result;
+
+}
+
+
+
+
+
/* Indique le type défini pour une description de client à l'écoute. */
G_DEFINE_TYPE(GAnalystClient, g_analyst_client, G_TYPE_HUB_CLIENT);
@@ -129,6 +192,22 @@ static void g_analyst_client_class_init(GAnalystClientClass *klass)
client->complete_hello = (complete_client_hello_fc)g_analyst_client_complete_hello;
client->recv_func = (GThreadFunc)g_analyst_client_update;
+ g_signal_new("ready",
+ G_TYPE_ANALYST_CLIENT,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GAnalystClientClass, ready),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_signal_new("server-status-changed",
+ G_TYPE_ANALYST_CLIENT,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GAnalystClientClass, server_status_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1, G_TYPE_LOADING_STATUS_HINT);
+
g_signal_new("snapshots-updated",
G_TYPE_ANALYST_CLIENT,
G_SIGNAL_RUN_LAST,
@@ -430,6 +509,11 @@ static void *g_analyst_client_update(GAnalystClient *client)
switch (command)
{
+ case DBC_LOADING_STATUS:
+ status = g_analyst_client_handle_loading_hints(client, &in_pbuf);
+ if (!status) goto gdcu_bad_exchange;
+ break;
+
case DBC_SAVE:
status = extract_packed_buffer(&in_pbuf, &tmp32, sizeof(uint32_t), true);
@@ -1285,3 +1369,59 @@ bool g_analyst_client_remove_snapshot(GAnalystClient *client, const snapshot_id_
return result;
}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PRISES EN COMPTE DES COMMANDES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = archive à connecter avec un utilisateur. *
+* in_pbuf = paquet à consulter. *
+* *
+* Description : Prend en compte une évolution du statut côté serveur. *
+* *
+* Retour : Indication pour le maintien de la communication. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_analyst_client_handle_loading_hints(GAnalystClient *client, packed_buffer_t *in_pbuf)
+{
+ bool result; /* Bilan à retourner */
+ uleb128_t hint; /* Indication du serveur */
+
+ result = unpack_uleb128(&hint, in_pbuf);
+
+ switch (hint)
+ {
+ case LSH_READY:
+ g_signal_emit_by_name(client, "ready");
+ break;
+
+ case LSH_ON_WAIT_LIST:
+ log_simple_message(LMT_INFO, _("Waiting for content from server..."));
+ break;
+
+ case LSH_NEED_CONTENT:
+ case LSH_NEED_FORMAT:
+ case LSH_NEED_ARCH:
+ g_signal_emit_by_name(client, "server-status-changed", hint);
+ break;
+
+ default:
+ log_variadic_message(LMT_ERROR,
+ _("Unknown loaded hint received (%x); unsupported newer protocol?"),
+ hint);
+ result = false;
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/db/analyst.h b/src/analysis/db/analyst.h
index 9f7b32b..459034e 100644
--- a/src/analysis/db/analyst.h
+++ b/src/analysis/db/analyst.h
@@ -38,6 +38,20 @@
+
+/* ------------------------------- GLUES POUR LA GLIB ------------------------------- */
+
+
+#define G_TYPE_LOADING_STATUS_HINT g_loading_status_hint_type()
+
+
+/* Définit un type GLib pour l'énumération "LoadingStatusHint". */
+GType g_loading_status_hint_type(void);
+
+
+
+
+
#define G_TYPE_ANALYST_CLIENT g_analyst_client_get_type()
#define G_ANALYST_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ANALYST_CLIENT, GAnalystClient))
#define G_IS_ANALYST_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ANALYST_CLIENT))
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index c5d3af7..b1e47bc 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -101,9 +101,13 @@ struct _GCdbArchive
char *filename; /* Chemin d'accès à l'archive */
char *tmpdir; /* Répertoire de travail */
- char *cnt_file; /* Fichier de contenu binaire */
char *xml_desc; /* Fichier de description */
+ char *cnt_file; /* Fichier de contenu binaire */
+
+ GMutex loading_access; /* Verrou pour l'accès */
+
+
GList *collections; /* Ensemble de modifications */
GDbSnapshot *snapshot; /* Instantanés de bases SQL */
@@ -189,8 +193,8 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *, packed_buffer_t *)
/* ------------------------- PRISES EN COMPTE DES COMMANDES ------------------------- */
-/* Prépare la réponse à envoyer à un client connecté. */
-static bool setup_server_answer(DBCommand, DBError, packed_buffer_t *);
+/* Prépare une courte réponse à envoyer à un client connecté. */
+static bool craft_server_short_answer(DBCommand, uleb128_t, packed_buffer_t *);
/* Enregistre le contenu binaire lié à une analyse. */
static bool g_cdb_archive_set_content(GCdbArchive *, packed_buffer_t *, packed_buffer_t *);
@@ -218,7 +222,7 @@ static cdb_client *create_cdb_client(SSL *fd, const char *peer_name, const char
{
cdb_client *result; /* Fiche d'entité à retourner */
- result = malloc(sizeof(cdb_client *));
+ result = malloc(sizeof(cdb_client));
result->tls_fd = fd;
@@ -358,9 +362,11 @@ static void g_cdb_archive_init(GCdbArchive *archive)
archive->filename = NULL;
archive->tmpdir = NULL;
- archive->cnt_file = NULL;
archive->xml_desc = NULL;
+ archive->cnt_file = NULL;
+ g_mutex_init(&archive->loading_access);
+
archive->collections = create_collections_list();
archive->snapshot = NULL;
@@ -387,9 +393,11 @@ static void g_cdb_archive_dispose(GCdbArchive *archive)
{
g_server_backend_stop(G_SERVER_BACKEND(archive));
+ g_mutex_clear(&archive->clients_access);
+
g_clear_object(&archive->snapshot);
- g_mutex_clear(&archive->clients_access);
+ g_mutex_clear(&archive->loading_access);
G_OBJECT_CLASS(g_cdb_archive_parent_class)->dispose(G_OBJECT(archive));
@@ -1459,38 +1467,100 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
* *
******************************************************************************/
+static LoadingStatusHint g_cdb_archive_compute_loading_hint(GCdbArchive *archive)
+{
+ LoadingStatusHint result; /* Statut à retourner */
+
+
+ // Try
+ // g_mutex_lock(&archive->loading_access);
+
+
+
+ // cnt_file
+
+ if (archive->cnt_file == NULL)
+ result = LSH_NEED_CONTENT;
+
+ else
+ result = LSH_NEED_FORMAT;
+
+
+
+
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = support pour le suivi d'une connexion. *
+* fd = canal de communication réseau ouvert. *
+* peer_name = désignation de la connexion. *
+* user = désignation de l'utilisateur de la connexion. *
+* *
+* Description : Prend en compte une connexion nouvelle d'un utilisateur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
static void g_cdb_archive_add_client(GCdbArchive *archive, SSL *fd, const char *peer_name, const char *user)
{
cdb_client *client; /* Nouvelle fiche d'entité */
+ packed_buffer_t out_pbuf; /* Tampon d'émission */
+ LoadingStatusHint hint; /* Statut de chargement */
+ bool status; /* Bilan de lecture initiale */
+
+ client = create_cdb_client(fd, peer_name, user);
/**
- * La situation est un peu compliquée lors de l'accueil d'un nouveau client :
- *
- * - soit on envoie tous les éléments à prendre en compte, mais on doit
- * bloquer la base de données jusqu'à l'intégration pleine et entière
- * du client, afin que ce dernier ne loupe pas l'envoi d'un nouvel
- * élément entre temps.
+ * Le verrou encadrant les évolutions des contenus initiaux doit englober
+ * l'extension de la liste des clients.
*
- * - soit on intègre le client et celui ci demande des mises à jour
- * collection par collection ; c'est également à lui que revient le rejet
- * des éléments envoyés en solitaires avant la réception de la base
- * complète.
+ * En effet, une évolution partielle peut intervenir dans la fonction
+ * g_cdb_archive_process(), à un moment au seul le verrou dans les
+ * évolutions sera posé (g_cdb_archive_set_content() par exemple).
*
- * On fait le choix du second scenario ici, du fait de la difficulté
- * de maîtriser facilement la reconstitution d'une liste de clients dans
- * g_cdb_archive_process() depuis un autre flot d'exécution.
+ * Or g_cdb_archive_compute_loading_hint() doit fournir ici un état qui ne
+ * varie pas entre le calcul et l'envoi. Donc verrous sur les clients et
+ * l'état de l'archive doivent englover l'ensemble des traitements ci-après.
*/
- client = create_cdb_client(fd, peer_name, user);
+ g_mutex_lock(&archive->loading_access);
g_mutex_lock(&archive->clients_access);
- archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client *));
+ hint = g_cdb_archive_compute_loading_hint(archive);
+
+ if (hint != LSH_READY)
+ hint = (archive->count == 0 ? hint : LSH_ON_WAIT_LIST);
+
+ init_packed_buffer(&out_pbuf);
+
+ status = craft_server_short_answer(DBC_LOADING_STATUS, hint, &out_pbuf);
+
+ if (status)
+ status = ssl_send_packed_buffer(&out_pbuf, fd);
+
+ exit_packed_buffer(&out_pbuf);
+
+ if (status)
+ {
+ archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client *));
+
+ archive->clients[archive->count - 1] = client;
- archive->clients[archive->count - 1] = client;
+ }
g_mutex_unlock(&archive->clients_access);
+ g_mutex_unlock(&archive->loading_access);
+
}
@@ -1694,10 +1764,10 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *archive, packed_buff
/******************************************************************************
* *
* Paramètres : cmd = commande à l'origine d'un traitement. *
-* error = bilan de traitement à communiquer. *
+* value = valeur à communiquer. *
* out_pbuf = paquet à consituer pour un retour au client. [OUT]*
* *
-* Description : Prépare la réponse à envoyer à un client connecté. *
+* Description : Prépare une courte réponse à envoyer à un client connecté. *
* *
* Retour : Indication pour le maintien de la communication. *
* *
@@ -1705,7 +1775,7 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *archive, packed_buff
* *
******************************************************************************/
-static bool setup_server_answer(DBCommand cmd, DBError error, packed_buffer_t *out_pbuf)
+static bool craft_server_short_answer(DBCommand cmd, uleb128_t value, packed_buffer_t *out_pbuf)
{
bool result; /* Bilan à retourner */
@@ -1714,7 +1784,7 @@ static bool setup_server_answer(DBCommand cmd, DBError error, packed_buffer_t *o
result = extend_packed_buffer(out_pbuf, (uint32_t []) { cmd }, sizeof(uint32_t), true);
if (result)
- result = extend_packed_buffer(out_pbuf, (uint32_t []) { error }, sizeof(uint32_t), true);
+ result = pack_uleb128((uleb128_t []){ value }, out_pbuf);
return result;
@@ -1748,6 +1818,7 @@ static bool g_cdb_archive_set_content(GCdbArchive *archive, packed_buffer_t *in_
const gchar *hash; /* Empreinte de ce contenu */
int fd; /* Flux ouvert en écriture */
bool status; /* Bilan d'une écriture */
+ LoadingStatusHint hint; /* Statut de chargement */
result = true;
error = DBE_NONE;
@@ -1848,7 +1919,15 @@ static bool g_cdb_archive_set_content(GCdbArchive *archive, packed_buffer_t *in_
/* Formulation de la réponse */
- result = setup_server_answer(DBC_SET_CONTENT, error, out_pbuf);
+ result = craft_server_short_answer(DBC_SET_CONTENT, error, out_pbuf);
+
+ if (result && error == DBE_NONE)
+ {
+ hint = g_cdb_archive_compute_loading_hint(archive);
+
+ result = craft_server_short_answer(DBC_LOADING_STATUS, hint, out_pbuf);
+
+ }
free_and_exit:
diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h
index 17263c8..7707058 100644
--- a/src/analysis/db/protocol.h
+++ b/src/analysis/db/protocol.h
@@ -76,14 +76,21 @@ typedef enum _ServerPrivLevels
+/**
+ * Précisions pour la commande DBC_LOADING_STATUS.
+ */
+
+
/* Eléments de base nécessaires */
-typedef enum _RequiredBasics
+typedef enum _LoadingStatusHint
{
- RBS_NONE = 0x0, /* (Plus) rien n'est requis */
- RBS_CONTENT = 0x1, /* Contenu binaire à analyser */
- RBS_LOADED = 0x2, /* Contenu binaire analysé */
+ LSH_READY = 0, /* (Plus) rien n'est requis */
+ LSH_ON_WAIT_LIST = 1, /* Concurrence des connexions */
+ LSH_NEED_CONTENT = 2, /* Suppléments nécessaires */
+ LSH_NEED_FORMAT = 3, /* Suppléments nécessaires */
+ LSH_NEED_ARCH = 4, /* Suppléments nécessaires */
-} RequiredBasics;
+} LoadingStatusHint;
@@ -135,6 +142,8 @@ typedef enum _DBAction
*/
typedef enum _DBCommand
{
+ /* ------------------------- Commandes à portée générale ------------------------- */
+
/**
* Le client envoie un tout premier paquet de la forme suivante :
*
@@ -176,6 +185,18 @@ typedef enum _DBCommand
/* ------------------------ Commandes pour analyste ------------------------ */
/**
+ * Gestion de la commande 'DBC_LOADING_STATUS'.
+ *
+ * Le serveur envoie un statut de prise en charge au début d'une connexion :
+ *
+ * [ Indication du serveur : DBC_LOADING_STATUS]
+ * [ Statut courant ; cf. LoadingStatusHint ]
+ *
+ */
+
+ DBC_LOADING_STATUS, /* Indications initiales */
+
+ /**
* Gestion de la commande 'DBC_SET_CONTENT'.
*
* Le client connecté envoie un paquet de la forme suivante :
diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c
index 5c6fd18..79d5df1 100644
--- a/src/analysis/db/server.c
+++ b/src/analysis/db/server.c
@@ -1088,6 +1088,8 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu
/* Fin de réception des données envoyées */
+ setup_empty_rle_string(&hash);
+
status = unpack_rle_string(&hash, in_pbuf);
if (!status)
{
@@ -1101,6 +1103,8 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu
goto wrong_receiving_0;
}
+ setup_empty_rle_string(&class);
+
status = unpack_rle_string(&class, in_pbuf);
if (!status)
{
diff --git a/tests/analysis/db/analyst.py b/tests/analysis/db/analyst.py
new file mode 100644
index 0000000..7347810
--- /dev/null
+++ b/tests/analysis/db/analyst.py
@@ -0,0 +1,188 @@
+
+from chrysacase import ChrysalideTestCase
+import pychrysalide
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.analysis.db import certs
+from pychrysalide.analysis.db import AdminClient, AnalystClient
+from pychrysalide.analysis.db import HubServer
+import os
+import shutil
+import sys
+import tempfile
+import threading
+
+
+class TestDbConnection(ChrysalideTestCase):
+ """TestCase for analysis.db."""
+
+ @classmethod
+ def setUpClass(cls):
+
+ super(TestDbConnection, cls).setUpClass()
+
+ cls.log('Compile binary "strings" if needed...')
+
+ fullname = sys.modules[cls.__module__].__file__
+ dirpath = os.path.dirname(fullname)
+
+ cls._bin_path = os.path.realpath(dirpath + '/../../format/elf/')
+
+ os.system('make -C %s strings > /dev/null 2>&1' % cls._bin_path)
+
+ cls._tmp_path = tempfile.mkdtemp()
+
+ cls._server_path = '%s/.chrysalide/servers/localhost-9999/' % cls._tmp_path
+ os.makedirs(cls._server_path)
+
+ cls._server_authorized_path = '%s/authorized/' % cls._server_path
+ os.makedirs(cls._server_authorized_path)
+
+ cls._client_path = '%s/.chrysalide/clients/' % cls._tmp_path
+ os.makedirs(cls._client_path)
+
+ cls._client_cert_path = '%s/localhost-9999/' % cls._client_path
+ os.makedirs(cls._client_cert_path)
+
+ cls.log('Using temporary directory "%s"' % cls._tmp_path)
+
+
+ @classmethod
+ def tearDownClass(cls):
+
+ super(TestDbConnection, cls).tearDownClass()
+
+ cls.log('Delete built binaries...')
+
+ os.system('make -C %s clean > /dev/null 2>&1' % cls._bin_path)
+
+ ## os.system('ls -laihR %s' % cls._tmp_path)
+
+ cls.log('Delete directory "%s"' % cls._tmp_path)
+
+ shutil.rmtree(cls._tmp_path)
+
+
+ def testServerListening(self):
+ """List binaries available from server."""
+
+
+ from pychrysalide import core
+ core.set_verbosity(0)
+
+
+
+ identity = {
+
+ 'C': 'FR',
+ 'CN': 'Test authority'
+
+ }
+
+ ret = certs.build_keys_and_ca(self._server_path, 'ca', 3650 * 24 * 60 * 60, identity)
+ self.assertTrue(ret)
+
+ identity = {
+
+ 'C': 'FR',
+ 'CN': 'Test server'
+
+ }
+
+ ret = certs.build_keys_and_request(self._server_path, 'server', identity);
+ self.assertTrue(ret)
+
+
+ ret = certs.sign_cert('%s/server-csr.pem' % self._server_path, '%s/ca-cert.pem' % self._server_path, \
+ '%s/ca-key.pem' % self._server_path, '%s/server-cert.pem' % self._server_path, \
+ 3650 * 24 * 60 * 60)
+ self.assertTrue(ret)
+
+ identity = {
+
+ 'C': 'FR',
+ 'CN': 'Test admin'
+
+ }
+
+ ret = certs.build_keys_and_request(self._client_path, 'client', identity);
+ self.assertTrue(ret)
+
+ ret = certs.sign_cert('%s/client-csr.pem' % self._client_path, '%s/ca-cert.pem' % self._server_path, \
+ '%s/ca-key.pem' % self._server_path, '%s/client-cert.pem' % self._client_cert_path, \
+ 3650 * 24 * 60 * 60)
+ self.assertTrue(ret)
+
+ shutil.copy('%s/ca-cert.pem' % self._server_path,
+ '%s/ca-cert.pem' % self._client_cert_path)
+
+ shutil.copy('%s/client-cert.pem' % self._client_cert_path,
+ '%s/client-cert.pem' % self._server_authorized_path)
+
+
+ os.environ['XDG_CONFIG_HOME'] = self._tmp_path
+ os.environ['HOME'] = self._tmp_path
+
+ server = HubServer('localhost', '9999')
+
+ #print(server)
+
+ ret = server.start()
+
+ #print(ret)
+
+
+
+
+ # admin = AdminClient()
+
+ # ret = admin.start('localhost', '9999')
+ # self.assertTrue(ret)
+
+ # def _on_existing_binaries_updated(adm, evt):
+ # evt.set()
+
+ # event = threading.Event()
+
+ # admin.connect('existing-binaries-updated', _on_existing_binaries_updated, event)
+
+ # ret = admin.request_existing_binaries()
+ # self.assertTrue(ret)
+
+ # event.wait()
+
+ # self.assertEqual(len(admin.existing_binaries), 0)
+
+
+
+ cnt = MemoryContent(b'A' * 400 * 1024)
+
+
+
+ analyst = AnalystClient(cnt.checksum, "elf", [])
+
+
+
+ def _on_server_status_changed(analyst, hint, evt):
+ print(hint)
+ evt.set()
+
+
+ event = threading.Event()
+
+ analyst.connect('server-status-changed', _on_server_status_changed, event)
+
+
+
+ ret = analyst.start('localhost', '9999')
+ self.assertTrue(ret)
+
+
+ event.wait()
+
+ event.clear()
+
+ ret = analyst.send_content(cnt)
+ self.assertTrue(ret)
+
+
+ event.wait()
diff --git a/tests/analysis/db/conn.py b/tests/analysis/db/conn.py
index f388f60..248a036 100644
--- a/tests/analysis/db/conn.py
+++ b/tests/analysis/db/conn.py
@@ -1,7 +1,8 @@
from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
from pychrysalide.analysis.db import certs
-from pychrysalide.analysis.db import AdminClient
+from pychrysalide.analysis.db import AdminClient, AnalystClient
from pychrysalide.analysis.db import HubServer
import os
import shutil
@@ -51,7 +52,7 @@ class TestDbConnection(ChrysalideTestCase):
from pychrysalide import core
- #core.set_verbosity(0)
+ core.set_verbosity(0)
@@ -117,21 +118,39 @@ class TestDbConnection(ChrysalideTestCase):
- admin = AdminClient()
+ # admin = AdminClient()
- ret = admin.start('localhost', '9999')
- self.assertTrue(ret)
+ # ret = admin.start('localhost', '9999')
+ # self.assertTrue(ret)
+
+ # def _on_existing_binaries_updated(adm, evt):
+ # evt.set()
+
+ # event = threading.Event()
+
+ # admin.connect('existing-binaries-updated', _on_existing_binaries_updated, event)
+
+ # ret = admin.request_existing_binaries()
+ # self.assertTrue(ret)
+
+ # event.wait()
- def _on_existing_binaries_updated(adm, evt):
- evt.set()
+ # self.assertEqual(len(admin.existing_binaries), 0)
- event = threading.Event()
- admin.connect('existing-binaries-updated', _on_existing_binaries_updated, event)
- ret = admin.request_existing_binaries()
+ cnt = MemoryContent(b'A' * 400 * 1024)
+
+ print(cnt)
+
+ print(len(cnt.data))
+
+
+ analyst = AnalystClient(cnt.checksum, [])
+
+ ret = analyst.start('localhost', '9999')
self.assertTrue(ret)
- event.wait()
- self.assertEqual(len(admin.existing_binaries), 0)
+ ret = analyst.send_content(cnt)
+ self.assertTrue(ret)