summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2021-05-29 10:13:16 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2021-05-29 10:13:16 (GMT)
commit3c493d4cd2c9e91a2cee08c80e3629ea75788605 (patch)
tree6d9483d4c8e2c3914ca47bb9e17d31201d266f30 /plugins
parentab7c898c87a1f235af6966941823cab502c550f6 (diff)
Define roles for allowed connections to servers.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/pychrysalide/analysis/binary.c5
-rw-r--r--plugins/pychrysalide/analysis/db/Makefile.am2
-rw-r--r--plugins/pychrysalide/analysis/db/admin.c227
-rw-r--r--plugins/pychrysalide/analysis/db/admin.h45
-rw-r--r--plugins/pychrysalide/analysis/db/analyst.c895
-rw-r--r--plugins/pychrysalide/analysis/db/analyst.h45
-rw-r--r--plugins/pychrysalide/analysis/db/client.c713
-rw-r--r--plugins/pychrysalide/analysis/db/module.c4
-rw-r--r--plugins/pychrysalide/analysis/db/server.c3
9 files changed, 1230 insertions, 709 deletions
diff --git a/plugins/pychrysalide/analysis/binary.c b/plugins/pychrysalide/analysis/binary.c
index 2f8af5f..68f2d88 100644
--- a/plugins/pychrysalide/analysis/binary.c
+++ b/plugins/pychrysalide/analysis/binary.c
@@ -127,7 +127,7 @@ static PyObject *py_loaded_binary_get_client(PyObject *self, PyObject *args)
int internal; /* Nature du client visé */
int ret; /* Bilan de lecture des args. */
GLoadedBinary *binary; /* Binaire en cours d'analyse */
- GHubClient *client; /* Eventuel client en place */
+ GAnalystClient *client; /* Eventuel client en place */
#define LOADED_BINARY_GET_CLIENT_METHOD PYTHON_METHOD_DEF \
( \
@@ -135,6 +135,9 @@ static PyObject *py_loaded_binary_get_client(PyObject *self, PyObject *args)
METH_VARARGS, py_loaded_binary, \
"Provide the client connected to an internal or remote server" \
" if defined, or return None otherwise.\n" \
+ "\n" \
+ "The returned object is a pychrysalide.analysis.db.AnalystClient" \
+ " instance or *None*." \
)
internal = 1;
diff --git a/plugins/pychrysalide/analysis/db/Makefile.am b/plugins/pychrysalide/analysis/db/Makefile.am
index fdf491e..721f5b6 100644
--- a/plugins/pychrysalide/analysis/db/Makefile.am
+++ b/plugins/pychrysalide/analysis/db/Makefile.am
@@ -2,6 +2,8 @@
noinst_LTLIBRARIES = libpychrysaanalysisdb.la
libpychrysaanalysisdb_la_SOURCES = \
+ admin.h admin.c \
+ analyst.h analyst.c \
certs.h certs.c \
client.h client.c \
collection.h collection.c \
diff --git a/plugins/pychrysalide/analysis/db/admin.c b/plugins/pychrysalide/analysis/db/admin.c
new file mode 100644
index 0000000..52027ac
--- /dev/null
+++ b/plugins/pychrysalide/analysis/db/admin.c
@@ -0,0 +1,227 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * admin.c - équivalent Python du fichier "analysis/db/admin.c"
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "admin.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/db/admin.h>
+
+
+#include "client.h"
+#include "../../access.h"
+#include "../../helpers.h"
+
+
+
+/* Crée un nouvel objet Python de type 'AdminClient'. */
+static PyObject *py_admin_client_new(PyTypeObject *, PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type de l'objet à instancier. *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Crée un nouvel objet Python de type 'AdminClient'. *
+* *
+* Retour : Instance Python mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_admin_client_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Instance à retourner */
+ GAdminClient *client; /* Serveur mis en place */
+
+#define ADMIN_CLIENT_DOC \
+ "AdminClient provides and receives binary updates to and from a connected" \
+ " to a server.\n" \
+ "\n" \
+ "Such clients must be authenticated and communications are encrypted using TLS.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " AdminClient()" \
+ "\n" \
+ "AdminClient instances emit the following signals:\n" \
+ "* 'snapshots-updated'\n" \
+ " This signal is emitted when the snapshot list has evolved.\n" \
+ "\n" \
+ " Handlers are expected to have only one argument: the client managing the" \
+ " updated snapshots.\n" \
+ "* 'snapshot-changed'\n" \
+ " This signal is emitted when the identifier of the current snapshot changed.\n" \
+ "\n" \
+ " Handlers are expected to have only one argument: the client managing the" \
+ " snapshots."
+
+ client = g_admin_client_new();
+
+ if (client != NULL)
+ {
+ result = pygobject_new(G_OBJECT(client));
+ g_object_unref(client);
+ }
+ else result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_admin_client_type(void)
+{
+ static PyMethodDef py_admin_client_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_admin_client_getseters[] = {
+ { NULL }
+ };
+
+ static PyTypeObject py_admin_client_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.db.AdminClient",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = ADMIN_CLIENT_DOC,
+
+ .tp_methods = py_admin_client_methods,
+ .tp_getset = py_admin_client_getseters,
+ .tp_new = py_admin_client_new,
+
+ };
+
+ return &py_admin_client_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....db.AdminClient'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_admin_client_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'AdminClient' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_admin_client_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ if (!ensure_python_hub_client_is_registered())
+ return false;
+
+ module = get_access_to_python_module("pychrysalide.analysis.db");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ADMIN_CLIENT, type, get_python_hub_client_type()))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en client administrateur. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_admin_client(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_admin_client_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to admin client");
+ break;
+
+ case 1:
+ *((GAdminClient **)dst) = G_ADMIN_CLIENT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/db/admin.h b/plugins/pychrysalide/analysis/db/admin.h
new file mode 100644
index 0000000..8a2dfeb
--- /dev/null
+++ b/plugins/pychrysalide/analysis/db/admin.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * admin.h - prototypes pour l'équivalent Python du fichier "analysis/db/admin.h"
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ADMIN_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ADMIN_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_admin_client_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.db.AdminClient'. */
+bool ensure_python_admin_client_is_registered(void);
+
+/* Tente de convertir en client administrateur. */
+int convert_to_admin_client(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ADMIN_H */
diff --git a/plugins/pychrysalide/analysis/db/analyst.c b/plugins/pychrysalide/analysis/db/analyst.c
new file mode 100644
index 0000000..83e3878
--- /dev/null
+++ b/plugins/pychrysalide/analysis/db/analyst.c
@@ -0,0 +1,895 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * analyst.c - équivalent Python du fichier "analysis/db/analyst.c"
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "analyst.h"
+
+
+#include <assert.h>
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <analysis/db/analyst.h>
+#include <core/collections.h>
+
+
+#include "client.h"
+#include "collection.h"
+#include "../../access.h"
+#include "../../helpers.h"
+#include "../../struct.h"
+
+
+
+/* Crée un nouvel objet Python de type 'AnalystClient'. */
+static PyObject *py_analyst_client_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Effectue une demande de sauvegarde de l'état courant. */
+static PyObject *py_analyst_client_save(PyObject *, PyObject *);
+
+/* Active les éléments en amont d'un horodatage donné. */
+static PyObject *py_analyst_client_set_last_active(PyObject *, PyObject *);
+
+/* Définit la désignation d'un instantané donné. */
+static PyObject *py_analyst_client_set_snapshot_name(PyObject *, PyObject *);
+
+/* Définit la désignation d'un instantané donné. */
+static PyObject *py_analyst_client_set_snapshot_desc(PyObject *, PyObject *);
+
+/* Restaure un ancien instantané. */
+static PyObject *py_analyst_client_restore_snapshot(PyObject *, PyObject *);
+
+/* Crée un nouvel instantané à partir d'un autre. */
+static PyObject *py_analyst_client_create_snapshot(PyObject *, PyObject *);
+
+/* Supprime un ancien instantané. */
+static PyObject *py_analyst_client_remove_snapshot(PyObject *, PyObject *);
+
+/* Fournit la liste des instantanés existants. */
+static PyObject *py_analyst_client_get_snapshots(PyObject *, void *);
+
+/* Fournit l'identifiant de l'instantané courant. */
+static PyObject *py_analyst_client_get_current_snapshot(PyObject *, void *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type de l'objet à instancier. *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Crée un nouvel objet Python de type 'AnalystClient'. *
+* *
+* Retour : Instance Python mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Instance à retourner */
+ const char *hash; /* Empreinte du binaire visé */
+ PyObject *list; /* Liste Python de collections */
+ int ret; /* Bilan de lecture des args. */
+ Py_ssize_t length; /* Nombre d'éléments collectés */
+ GList *collections; /* Liste native de collections */
+ Py_ssize_t i; /* Boucle de parcours */
+ PyObject *item; /* Elément de la liste Python */
+ GDbCollection *collec; /* Version équivalente native */
+ GAnalystClient *client; /* Serveur mis en place */
+
+#define ANALYST_CLIENT_DOC \
+ "AnalystClient provides and receives binary updates to and from a connected" \
+ " to a server.\n" \
+ "\n" \
+ "Such clients must be authenticated and communications are encrypted using TLS.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " AnalystClient(hash, list)" \
+ "\n" \
+ "Where hash is a SHA256 fingerprint of the studied binary and list is a list of" \
+ " pychrysalide.analysis.db.DbCollection instances ; this kind of list can be" \
+ " retrived with the pychrysalide.analysis.LoadedBinary.collections attribute." \
+ "\n" \
+ "AnalystClient instances emit the following signals:\n" \
+ "* 'snapshots-updated'\n" \
+ " This signal is emitted when the snapshot list has evolved.\n" \
+ "\n" \
+ " Handlers are expected to have only one argument: the client managing the" \
+ " updated snapshots.\n" \
+ "* 'snapshot-changed'\n" \
+ " This signal is emitted when the identifier of the current snapshot changed.\n" \
+ "\n" \
+ " Handlers are expected to have only one argument: the client managing the" \
+ " snapshots."
+
+ ret = PyArg_ParseTuple(args, "sO", &hash, &list);
+ if (!ret) return NULL;
+
+ if (!PySequence_Check(list))
+ {
+ PyErr_SetString(PyExc_TypeError, _("The second argument must be a collection list"));
+ return NULL;
+ }
+
+ length = PySequence_Length(list);
+
+ collections = NULL;
+
+ for (i = 0; i < length; i++)
+ {
+ item = PySequence_GetItem(list, i);
+
+ ret = convert_to_db_collection(item, &collec);
+
+ Py_DECREF(item);
+
+ if (ret != 1)
+ {
+ delete_collections_list(&collections);
+ result = NULL;
+ goto exit;
+ }
+
+ g_object_ref(G_OBJECT(collec));
+ collections = g_list_append(collections, collec);
+
+ }
+
+ client = g_analyst_client_new(hash, collections);
+
+ if (client != NULL)
+ {
+ result = pygobject_new(G_OBJECT(client));
+ g_object_unref(client);
+ }
+ else result = NULL;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = client à manipuler. *
+* args = arguments d'appel non utilisés ici. *
+* *
+* Description : Effectue une demande de sauvegarde de l'état courant. *
+* *
+* Retour : True si la commande a bien été envoyée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_save(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GAnalystClient *client; /* Version native du serveur */
+ bool status; /* Bilan de l'opération */
+
+#define ANALYST_CLIENT_SAVE_METHOD PYTHON_METHOD_DEF \
+( \
+ save, "$self, /", \
+ METH_NOARGS, py_analyst_client, \
+ "Ask the server for saving the current state of the analyzed binary" \
+ " and returns the status of the request transmission." \
+)
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_save(client);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = client à manipuler. *
+* args = arguments d'appel à consulter. *
+* *
+* Description : Active les éléments en amont d'un horodatage donné. *
+* *
+* Retour : True si la commande a bien été envoyée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_set_last_active(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ unsigned long long timestamp; /* Horodatage de limite */
+ int ret; /* Bilan de lecture des args. */
+ GAnalystClient *client; /* Version native du serveur */
+ bool status; /* Bilan de l'opération */
+
+#define ANALYST_CLIENT_SET_LAST_ACTIVE_METHOD PYTHON_METHOD_DEF \
+( \
+ set_last_active, "$self, timestamp, /", \
+ METH_VARARGS, py_analyst_client, \
+ "Define the timestamp of the last active item in the collection" \
+ " and returns the status of the request transmission." \
+ "\n" \
+ "This method should not be used directly. Prefer calling" \
+ " pychrysalide.analysis.LoadedBinary.set_last_active() instead," \
+ " as some items may be volatile and thus not handled by clients." \
+)
+
+ ret = PyArg_ParseTuple(args, "K", &timestamp);
+ if (!ret) return NULL;
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_set_last_active(client, timestamp);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = client à manipuler. *
+* args = arguments d'appel à consulter. *
+* *
+* Description : Définit la désignation d'un instantané donné. *
+* *
+* Retour : True si la commande a bien été envoyée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_set_snapshot_name(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ const char *raw_id; /* Identifiant brut */
+ const char *text; /* Texte fourni à transmettre */
+ int ret; /* Bilan de lecture des args. */
+ snapshot_id_t id; /* Identifiant utilisable */
+ bool status; /* Bilan d'opération */
+ GAnalystClient *client; /* Version native du serveur */
+
+#define ANALYST_CLIENT_SET_SNAPSHOT_NAME_METHOD PYTHON_METHOD_DEF \
+( \
+ set_snapshot_name, "$self, id, name, /", \
+ METH_VARARGS, py_analyst_client, \
+ "Ask the server for defining a new name of for a snapshot using its" \
+ " identifier and returns the status of the request transmission." \
+ "\n" \
+ "A 'snapshots-updated' signal is emitted once the request has been" \
+ " processed with success." \
+)
+
+ ret = PyArg_ParseTuple(args, "ss", &raw_id, &text);
+ if (!ret) return NULL;
+
+ status = init_snapshot_id_from_text(&id, raw_id);
+ if (!status)
+ {
+ PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
+ return NULL;
+ }
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_set_snapshot_name(client, &id, text);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = client à manipuler. *
+* args = arguments d'appel à consulter. *
+* *
+* Description : Définit la désignation d'un instantané donné. *
+* *
+* Retour : True si la commande a bien été envoyée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_set_snapshot_desc(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ const char *raw_id; /* Identifiant brut */
+ const char *text; /* Texte fourni à transmettre */
+ int ret; /* Bilan de lecture des args. */
+ snapshot_id_t id; /* Identifiant utilisable */
+ bool status; /* Bilan d'opération */
+ GAnalystClient *client; /* Version native du serveur */
+
+#define ANALYST_CLIENT_SET_SNAPSHOT_DESC_METHOD PYTHON_METHOD_DEF \
+( \
+ set_snapshot_desc, "$self, id, desc, /", \
+ METH_VARARGS, py_analyst_client, \
+ "Ask the server for defining a new description for a snapshot using" \
+ " its identifier and returns the status of the request transmission." \
+ "\n" \
+ "A 'snapshots-updated' signal is emitted once the request has been" \
+ " processed with success." \
+)
+
+ ret = PyArg_ParseTuple(args, "ss", &raw_id, &text);
+ if (!ret) return NULL;
+
+ status = init_snapshot_id_from_text(&id, raw_id);
+ if (!status)
+ {
+ PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
+ return NULL;
+ }
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_set_snapshot_desc(client, &id, text);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = client à manipuler. *
+* args = arguments d'appel à consulter. *
+* *
+* Description : Restaure un ancien instantané. *
+* *
+* Retour : True si la commande a bien été envoyée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_restore_snapshot(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ const char *raw_id; /* Identifiant brut */
+ int ret; /* Bilan de lecture des args. */
+ snapshot_id_t id; /* Identifiant utilisable */
+ bool status; /* Bilan d'opération */
+ GAnalystClient *client; /* Version native du serveur */
+
+#define ANALYST_CLIENT_RESTORE_SNAPSHOT_METHOD PYTHON_METHOD_DEF \
+( \
+ restore_snapshot, "$self, id, /", \
+ METH_VARARGS, py_analyst_client, \
+ "Ask the server for restoring a given snapshot using" \
+ " its identifier and returns the status of the request transmission." \
+ "\n" \
+ "A 'snapshot-changed' signal is emitted once the request has been" \
+ " processed with success." \
+)
+
+ ret = PyArg_ParseTuple(args, "s", &raw_id);
+ if (!ret) return NULL;
+
+ status = init_snapshot_id_from_text(&id, raw_id);
+ if (!status)
+ {
+ PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
+ return NULL;
+ }
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_restore_snapshot(client, &id);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = client à manipuler. *
+* args = arguments d'appel à consulter. *
+* *
+* Description : Crée un nouvel instantané à partir d'un autre. *
+* *
+* Retour : True si la commande a bien été envoyée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_create_snapshot(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GAnalystClient *client; /* Version native du serveur */
+ bool status; /* Bilan d'opération */
+
+#define ANALYST_CLIENT_CREATE_SNAPSHOT_METHOD PYTHON_METHOD_DEF \
+( \
+ create_snapshot, "$self, /", \
+ METH_NOARGS, py_analyst_client, \
+ "Ask the server for creating a new snapshot of the current state" \
+ " and returns the status of the request transmission." \
+ "\n" \
+ "A 'snapshots-updated' signal is emitted once the request has been" \
+ " processed with success." \
+)
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_create_snapshot(client);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = client à manipuler. *
+* args = arguments d'appel à consulter. *
+* *
+* Description : Supprime un ancien instantané. *
+* *
+* Retour : True si la commande a bien été envoyée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_remove_snapshot(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ const char *raw_id; /* Identifiant brut */
+ int rec; /* Indicateur de récursivité */
+ int ret; /* Bilan de lecture des args. */
+ snapshot_id_t id; /* Identifiant utilisable */
+ bool status; /* Bilan d'opération */
+ GAnalystClient *client; /* Version native du serveur */
+
+#define ANALYST_CLIENT_REMOVE_SNAPSHOT_METHOD PYTHON_METHOD_DEF \
+( \
+ remove_snapshot, "$self, id, recursive, /", \
+ METH_VARARGS, py_analyst_client, \
+ "Ask the server for removing a given snapshot using" \
+ " its identifier and returns the status of the request transmission." \
+ "\n" \
+ "If this removal has not to be recursive, all children snapshots get" \
+ " reassigned to the parent snapshot of the target." \
+ "\n" \
+ "A 'snapshots-updated' signal is emitted once the request has been" \
+ " processed with success." \
+)
+
+ ret = PyArg_ParseTuple(args, "sp", &raw_id, &rec);
+ if (!ret) return NULL;
+
+ status = init_snapshot_id_from_text(&id, raw_id);
+ if (!status)
+ {
+ PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
+ return NULL;
+ }
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_remove_snapshot(client, &id, rec);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la liste des instantanés existants. *
+* *
+* Retour : Liste d'instantanés ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_get_snapshots(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GAnalystClient *client; /* Version native du serveur */
+ snapshot_info_t *info; /* Liste d'instantanés présents*/
+ size_t count; /* Taille de cette liste */
+ bool status; /* Validité de cet identifiant */
+ PyTypeObject *base; /* Modèle d'objet à créer */
+ size_t i; /* Boucle de parcours */
+ PyObject *item; /* Nouvelle description */
+ char *text; /* Valeur textuelle à placer */
+ PyObject *attrib; /* Attribut à constituer */
+ int ret; /* Bilan d'une mise en place */
+ bool failed; /* Détection d'une erreur */
+
+#define ANALYST_CLIENT_SNAPSHOTS_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ snapshots, py_analyst_client, \
+ "List of all existing snapshots, provided as a tuple of pychrysalide.StructObject." \
+ "\n" \
+ "Each snapshot is characterised by the following properties :\n" \
+ "* parent_id : identifier of the parent snapshot;\n" \
+ "* id : identifier of the snapshot;\n" \
+ "* created : timestamp of the creation date;\n" \
+ "* name : name of the snapshot, or None;\n" \
+ "* desc : description of the snapshot, or None." \
+)
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_get_snapshots(client, &info, &count);
+
+ if (status)
+ {
+ result = PyTuple_New(count);
+
+ base = get_python_py_struct_type();
+
+ failed = false;
+
+ for (i = 0; i < count; i++)
+ {
+ item = PyObject_CallFunction((PyObject *)base, NULL);
+ assert(item != NULL);
+
+ text = snapshot_id_as_string(get_snapshot_info_parent_id(&info[i]));
+ attrib = PyUnicode_FromString(text);
+ ret = PyDict_SetItemString(item, "parent_id", attrib);
+ if (ret != 0) break;
+
+ text = snapshot_id_as_string(get_snapshot_info_id(&info[i]));
+ attrib = PyUnicode_FromString(text);
+ ret = PyDict_SetItemString(item, "id", attrib);
+ if (ret != 0) break;
+
+ attrib = PyLong_FromUnsignedLongLong(get_snapshot_info_created(&info[i]));
+ ret = PyDict_SetItemString(item, "created", attrib);
+ if (ret != 0) break;
+
+ text = get_snapshot_info_name(&info[i]);
+
+ if (text != NULL)
+ attrib = PyUnicode_FromString(text);
+ else
+ {
+ attrib = Py_None;
+ Py_INCREF(attrib);
+ }
+
+ ret = PyDict_SetItemString(item, "name", attrib);
+ if (ret != 0) break;
+
+ text = get_snapshot_info_desc(&info[i]);
+
+ if (text != NULL)
+ attrib = PyUnicode_FromString(text);
+ else
+ {
+ attrib = Py_None;
+ Py_INCREF(attrib);
+ }
+
+ ret = PyDict_SetItemString(item, "desc", attrib);
+ if (ret != 0) break;
+
+ PyTuple_SetItem(result, i, item);
+
+ }
+
+ failed = (i < count);
+
+ for (i = 0; i < count; i++)
+ exit_snapshot_info(&info[i]);
+
+ free(info);
+
+ if (failed)
+ goto on_failure;
+
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+ on_failure:
+
+ Py_DECREF(result);
+
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit l'identifiant de l'instantané courant. *
+* *
+* Retour : Identifiant d'instantané ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_analyst_client_get_current_snapshot(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GAnalystClient *client; /* Version native du serveur */
+ snapshot_id_t id; /* Identifiant à transmettre */
+ bool status; /* Validité de cet identifiant */
+
+#define ANALYST_CLIENT_CURRENT_SNAPSHOT_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ current_snapshot, py_analyst_client, \
+ "Identifier of the current snapshot, provided as a string." \
+ "\n" \
+ "The returned value is a cached version of the value stored at" \
+ " server side. Thus, defining a new current snapshot is" \
+ " successful as soon as the request to this server is sent." \
+)
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_get_current_snapshot(client, &id);
+
+ if (status)
+ result = PyUnicode_FromString(snapshot_id_as_string(&id));
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Définit l'identifiant de l'instantané courant. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_analyst_client_set_current_snapshot(PyObject *self, PyObject *value, void *closure)
+{
+ int ret; /* Bilan d'analyse */
+ void *raw; /* Valeur brute d'identifiant */
+ snapshot_id_t id; /* Identifiant reconnu */
+ bool status; /* Bilan d'une conversion */
+ GAnalystClient *client; /* Version native du serveur */
+
+ ret = PyUnicode_Check(value);
+ if (!ret) return -1;
+
+ raw = PyUnicode_DATA(value);
+
+ status = init_snapshot_id_from_text(&id, raw);
+ if (!status)
+ {
+ PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
+ return -1;
+ }
+
+ client = G_ANALYST_CLIENT(pygobject_get(self));
+
+ status = g_analyst_client_set_current_snapshot(client, &id);
+ if (!status)
+ {
+ PyErr_SetString(PyExc_TypeError, "unable to send the provided snapshot identifier");
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_analyst_client_type(void)
+{
+ static PyMethodDef py_analyst_client_methods[] = {
+ ANALYST_CLIENT_SAVE_METHOD,
+ ANALYST_CLIENT_SET_LAST_ACTIVE_METHOD,
+ ANALYST_CLIENT_SET_SNAPSHOT_NAME_METHOD,
+ ANALYST_CLIENT_SET_SNAPSHOT_DESC_METHOD,
+ ANALYST_CLIENT_RESTORE_SNAPSHOT_METHOD,
+ ANALYST_CLIENT_CREATE_SNAPSHOT_METHOD,
+ ANALYST_CLIENT_REMOVE_SNAPSHOT_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_analyst_client_getseters[] = {
+ ANALYST_CLIENT_SNAPSHOTS_ATTRIB,
+ ANALYST_CLIENT_CURRENT_SNAPSHOT_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_analyst_client_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.analysis.db.AnalystClient",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = ANALYST_CLIENT_DOC,
+
+ .tp_methods = py_analyst_client_methods,
+ .tp_getset = py_analyst_client_getseters,
+ .tp_new = py_analyst_client_new,
+
+ };
+
+ return &py_analyst_client_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide....db.AnalystClient'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_analyst_client_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'AnalystClient' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_analyst_client_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ if (!ensure_python_hub_client_is_registered())
+ return false;
+
+ module = get_access_to_python_module("pychrysalide.analysis.db");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_ANALYST_CLIENT, type, get_python_hub_client_type()))
+ return false;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en client analyste. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_analyst_client(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_analyst_client_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to analyst client");
+ break;
+
+ case 1:
+ *((GAnalystClient **)dst) = G_ANALYST_CLIENT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/db/analyst.h b/plugins/pychrysalide/analysis/db/analyst.h
new file mode 100644
index 0000000..b250933
--- /dev/null
+++ b/plugins/pychrysalide/analysis/db/analyst.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * analyst.h - prototypes pour l'équivalent Python du fichier "analysis/db/analyst.h"
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ANALYST_H
+#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ANALYST_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_analyst_client_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.analysis.db.AnalystClient'. */
+bool ensure_python_analyst_client_is_registered(void);
+
+/* Tente de convertir en client analyste. */
+int convert_to_analyst_client(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ANALYST_H */
diff --git a/plugins/pychrysalide/analysis/db/client.c b/plugins/pychrysalide/analysis/db/client.c
index d5d8b48..0cd9704 100644
--- a/plugins/pychrysalide/analysis/db/client.c
+++ b/plugins/pychrysalide/analysis/db/client.c
@@ -41,84 +41,13 @@
-/* Crée un nouvel objet Python de type 'HubClient'. */
-static PyObject *py_hub_client_new(PyTypeObject *, PyObject *, PyObject *);
-
-/* Démarre la connexion à la base de données. */
-static PyObject *py_hub_client_start(PyObject *, PyObject *);
-
-/* Arrête la connexion à la base de données. */
-static PyObject *py_hub_client_stop(PyObject *, PyObject *);
-
-/* Effectue une demande de sauvegarde de l'état courant. */
-static PyObject *py_hub_client_save(PyObject *, PyObject *);
-
-/* Active les éléments en amont d'un horodatage donné. */
-static PyObject *py_hub_client_set_last_active(PyObject *, PyObject *);
-
-/* Définit la désignation d'un instantané donné. */
-static PyObject *py_hub_client_set_snapshot_name(PyObject *, PyObject *);
-
-/* Définit la désignation d'un instantané donné. */
-static PyObject *py_hub_client_set_snapshot_desc(PyObject *, PyObject *);
-
-/* Restaure un ancien instantané. */
-static PyObject *py_hub_client_restore_snapshot(PyObject *, PyObject *);
-
-/* Crée un nouvel instantané à partir d'un autre. */
-static PyObject *py_hub_client_create_snapshot(PyObject *, PyObject *);
-
-/* Supprime un ancien instantané. */
-static PyObject *py_hub_client_remove_snapshot(PyObject *, PyObject *);
-
-/* Fournit la liste des instantanés existants. */
-static PyObject *py_hub_client_get_snapshots(PyObject *, void *);
-
-/* Fournit l'identifiant de l'instantané courant. */
-static PyObject *py_hub_client_get_current_snapshot(PyObject *, void *);
-
-
-
-/******************************************************************************
-* *
-* Paramètres : type = type de l'objet à instancier. *
-* args = arguments fournis à l'appel. *
-* kwds = arguments de type key=val fournis. *
-* *
-* Description : Crée un nouvel objet Python de type 'HubClient'. *
-* *
-* Retour : Instance Python mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *result; /* Instance à retourner */
- const char *hash; /* Empreinte du binaire visé */
- PyObject *list; /* Liste Python de collections */
- int ret; /* Bilan de lecture des args. */
- Py_ssize_t length; /* Nombre d'éléments collectés */
- GList *collections; /* Liste native de collections */
- Py_ssize_t i; /* Boucle de parcours */
- PyObject *item; /* Elément de la liste Python */
- GDbCollection *collec; /* Version équivalente native */
- GHubClient *client; /* Serveur mis en place */
-
#define HUB_CLIENT_DOC \
"HubClient provides and receives binary updates to and from a connected" \
" to a server.\n" \
"\n" \
"Such clients must be authenticated and communications are encrypted using TLS.\n" \
"\n" \
- "Instances can be created using the following constructor:\n" \
- "\n" \
- " HubClient(hash, list)" \
- "\n" \
- "Where hash is a SHA256 fingerprint of the studied binary and list is a list of" \
- " pychrysalide.analysis.db.DbCollection instances ; this kind of list can be" \
- " retrived with the pychrysalide.analysis.LoadedBinary.collections attribute." \
+ "Instances can be created directly." \
"\n" \
"HubClient instances emit the following signals:\n" \
"* 'snapshots-updated'\n" \
@@ -132,53 +61,14 @@ static PyObject *py_hub_client_new(PyTypeObject *type, PyObject *args, PyObject
" Handlers are expected to have only one argument: the client managing the" \
" snapshots."
- ret = PyArg_ParseTuple(args, "sO", &hash, &list);
- if (!ret) return NULL;
-
- if (!PySequence_Check(list))
- {
- PyErr_SetString(PyExc_TypeError, _("The second argument must be a collection list"));
- return NULL;
- }
-
- length = PySequence_Length(list);
-
- collections = NULL;
-
- for (i = 0; i < length; i++)
- {
- item = PySequence_GetItem(list, i);
-
- ret = convert_to_db_collection(item, &collec);
-
- Py_DECREF(item);
- if (ret != 1)
- {
- delete_collections_list(&collections);
- result = NULL;
- goto exit;
- }
- g_object_ref(G_OBJECT(collec));
- collections = g_list_append(collections, collec);
-
- }
-
- client = g_hub_client_new(hash, collections);
-
- if (client != NULL)
- {
- result = pygobject_new(G_OBJECT(client));
- g_object_unref(client);
- }
- else result = NULL;
-
- exit:
+/* Démarre la connexion à la base de données. */
+static PyObject *py_hub_client_start(PyObject *, PyObject *);
- return result;
+/* Arrête la connexion à la base de données. */
+static PyObject *py_hub_client_stop(PyObject *, PyObject *);
-}
/******************************************************************************
@@ -275,588 +165,6 @@ static PyObject *py_hub_client_stop(PyObject *self, PyObject *args)
/******************************************************************************
* *
-* Paramètres : self = client à manipuler. *
-* args = arguments d'appel non utilisés ici. *
-* *
-* Description : Effectue une demande de sauvegarde de l'état courant. *
-* *
-* Retour : True si la commande a bien été envoyée, False sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_save(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Bilan à retourner */
- GHubClient *client; /* Version native du serveur */
- bool status; /* Bilan de l'opération */
-
-#define HUB_CLIENT_SAVE_METHOD PYTHON_METHOD_DEF \
-( \
- save, "$self, /", \
- METH_NOARGS, py_hub_client, \
- "Ask the server for saving the current state of the analyzed binary" \
- " and returns the status of the request transmission." \
-)
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_save(client);
-
- result = status ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = client à manipuler. *
-* args = arguments d'appel à consulter. *
-* *
-* Description : Active les éléments en amont d'un horodatage donné. *
-* *
-* Retour : True si la commande a bien été envoyée, False sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_set_last_active(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Bilan à retourner */
- unsigned long long timestamp; /* Horodatage de limite */
- int ret; /* Bilan de lecture des args. */
- GHubClient *client; /* Version native du serveur */
- bool status; /* Bilan de l'opération */
-
-#define HUB_CLIENT_SET_LAST_ACTIVE_METHOD PYTHON_METHOD_DEF \
-( \
- set_last_active, "$self, timestamp, /", \
- METH_VARARGS, py_hub_client, \
- "Define the timestamp of the last active item in the collection" \
- " and returns the status of the request transmission." \
- "\n" \
- "This method should not be used directly. Prefer calling" \
- " pychrysalide.analysis.LoadedBinary.set_last_active() instead," \
- " as some items may be volatile and thus not handled by clients." \
-)
-
- ret = PyArg_ParseTuple(args, "K", &timestamp);
- if (!ret) return NULL;
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_set_last_active(client, timestamp);
-
- result = status ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = client à manipuler. *
-* args = arguments d'appel à consulter. *
-* *
-* Description : Définit la désignation d'un instantané donné. *
-* *
-* Retour : True si la commande a bien été envoyée, False sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_set_snapshot_name(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Bilan à retourner */
- const char *raw_id; /* Identifiant brut */
- const char *text; /* Texte fourni à transmettre */
- int ret; /* Bilan de lecture des args. */
- snapshot_id_t id; /* Identifiant utilisable */
- bool status; /* Bilan d'opération */
- GHubClient *client; /* Version native du serveur */
-
-#define HUB_CLIENT_SET_SNAPSHOT_NAME_METHOD PYTHON_METHOD_DEF \
-( \
- set_snapshot_name, "$self, id, name, /", \
- METH_VARARGS, py_hub_client, \
- "Ask the server for defining a new name of for a snapshot using its" \
- " identifier and returns the status of the request transmission." \
- "\n" \
- "A 'snapshots-updated' signal is emitted once the request has been" \
- " processed with success." \
-)
-
- ret = PyArg_ParseTuple(args, "ss", &raw_id, &text);
- if (!ret) return NULL;
-
- status = init_snapshot_id_from_text(&id, raw_id);
- if (!status)
- {
- PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
- return NULL;
- }
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_set_snapshot_name(client, &id, text);
-
- result = status ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = client à manipuler. *
-* args = arguments d'appel à consulter. *
-* *
-* Description : Définit la désignation d'un instantané donné. *
-* *
-* Retour : True si la commande a bien été envoyée, False sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_set_snapshot_desc(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Bilan à retourner */
- const char *raw_id; /* Identifiant brut */
- const char *text; /* Texte fourni à transmettre */
- int ret; /* Bilan de lecture des args. */
- snapshot_id_t id; /* Identifiant utilisable */
- bool status; /* Bilan d'opération */
- GHubClient *client; /* Version native du serveur */
-
-#define HUB_CLIENT_SET_SNAPSHOT_DESC_METHOD PYTHON_METHOD_DEF \
-( \
- set_snapshot_desc, "$self, id, desc, /", \
- METH_VARARGS, py_hub_client, \
- "Ask the server for defining a new description for a snapshot using" \
- " its identifier and returns the status of the request transmission." \
- "\n" \
- "A 'snapshots-updated' signal is emitted once the request has been" \
- " processed with success." \
-)
-
- ret = PyArg_ParseTuple(args, "ss", &raw_id, &text);
- if (!ret) return NULL;
-
- status = init_snapshot_id_from_text(&id, raw_id);
- if (!status)
- {
- PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
- return NULL;
- }
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_set_snapshot_desc(client, &id, text);
-
- result = status ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = client à manipuler. *
-* args = arguments d'appel à consulter. *
-* *
-* Description : Restaure un ancien instantané. *
-* *
-* Retour : True si la commande a bien été envoyée, False sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_restore_snapshot(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Bilan à retourner */
- const char *raw_id; /* Identifiant brut */
- int ret; /* Bilan de lecture des args. */
- snapshot_id_t id; /* Identifiant utilisable */
- bool status; /* Bilan d'opération */
- GHubClient *client; /* Version native du serveur */
-
-#define HUB_CLIENT_RESTORE_SNAPSHOT_METHOD PYTHON_METHOD_DEF \
-( \
- restore_snapshot, "$self, id, /", \
- METH_VARARGS, py_hub_client, \
- "Ask the server for restoring a given snapshot using" \
- " its identifier and returns the status of the request transmission." \
- "\n" \
- "A 'snapshot-changed' signal is emitted once the request has been" \
- " processed with success." \
-)
-
- ret = PyArg_ParseTuple(args, "s", &raw_id);
- if (!ret) return NULL;
-
- status = init_snapshot_id_from_text(&id, raw_id);
- if (!status)
- {
- PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
- return NULL;
- }
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_restore_snapshot(client, &id);
-
- result = status ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = client à manipuler. *
-* args = arguments d'appel à consulter. *
-* *
-* Description : Crée un nouvel instantané à partir d'un autre. *
-* *
-* Retour : True si la commande a bien été envoyée, False sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_create_snapshot(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Bilan à retourner */
- GHubClient *client; /* Version native du serveur */
- bool status; /* Bilan d'opération */
-
-#define HUB_CLIENT_CREATE_SNAPSHOT_METHOD PYTHON_METHOD_DEF \
-( \
- create_snapshot, "$self, /", \
- METH_NOARGS, py_hub_client, \
- "Ask the server for creating a new snapshot of the current state" \
- " and returns the status of the request transmission." \
- "\n" \
- "A 'snapshots-updated' signal is emitted once the request has been" \
- " processed with success." \
-)
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_create_snapshot(client);
-
- result = status ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = client à manipuler. *
-* args = arguments d'appel à consulter. *
-* *
-* Description : Supprime un ancien instantané. *
-* *
-* Retour : True si la commande a bien été envoyée, False sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_remove_snapshot(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Bilan à retourner */
- const char *raw_id; /* Identifiant brut */
- int rec; /* Indicateur de récursivité */
- int ret; /* Bilan de lecture des args. */
- snapshot_id_t id; /* Identifiant utilisable */
- bool status; /* Bilan d'opération */
- GHubClient *client; /* Version native du serveur */
-
-#define HUB_CLIENT_REMOVE_SNAPSHOT_METHOD PYTHON_METHOD_DEF \
-( \
- remove_snapshot, "$self, id, recursive, /", \
- METH_VARARGS, py_hub_client, \
- "Ask the server for removing a given snapshot using" \
- " its identifier and returns the status of the request transmission." \
- "\n" \
- "If this removal has not to be recursive, all children snapshots get" \
- " reassigned to the parent snapshot of the target." \
- "\n" \
- "A 'snapshots-updated' signal is emitted once the request has been" \
- " processed with success." \
-)
-
- ret = PyArg_ParseTuple(args, "sp", &raw_id, &rec);
- if (!ret) return NULL;
-
- status = init_snapshot_id_from_text(&id, raw_id);
- if (!status)
- {
- PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
- return NULL;
- }
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_remove_snapshot(client, &id, rec);
-
- result = status ? Py_True : Py_False;
- Py_INCREF(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
-* Description : Fournit la liste des instantanés existants. *
-* *
-* Retour : Liste d'instantanés ou None. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_get_snapshots(PyObject *self, void *closure)
-{
- PyObject *result; /* Valeur à retourner */
- GHubClient *client; /* Version native du serveur */
- snapshot_info_t *info; /* Liste d'instantanés présents*/
- size_t count; /* Taille de cette liste */
- bool status; /* Validité de cet identifiant */
- PyTypeObject *base; /* Modèle d'objet à créer */
- size_t i; /* Boucle de parcours */
- PyObject *item; /* Nouvelle description */
- char *text; /* Valeur textuelle à placer */
- PyObject *attrib; /* Attribut à constituer */
- int ret; /* Bilan d'une mise en place */
- bool failed; /* Détection d'une erreur */
-
-#define HUB_CLIENT_SNAPSHOTS_ATTRIB PYTHON_GET_DEF_FULL \
-( \
- snapshots, py_hub_client, \
- "List of all existing snapshots, provided as a tuple of pychrysalide.StructObject." \
- "\n" \
- "Each snapshot is characterised by the following properties :\n" \
- "* parent_id : identifier of the parent snapshot;\n" \
- "* id : identifier of the snapshot;\n" \
- "* created : timestamp of the creation date;\n" \
- "* name : name of the snapshot, or None;\n" \
- "* desc : description of the snapshot, or None." \
-)
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_get_snapshots(client, &info, &count);
-
- if (status)
- {
- result = PyTuple_New(count);
-
- base = get_python_py_struct_type();
-
- failed = false;
-
- for (i = 0; i < count; i++)
- {
- item = PyObject_CallFunction((PyObject *)base, NULL);
- assert(item != NULL);
-
- text = snapshot_id_as_string(get_snapshot_info_parent_id(&info[i]));
- attrib = PyUnicode_FromString(text);
- ret = PyDict_SetItemString(item, "parent_id", attrib);
- if (ret != 0) break;
-
- text = snapshot_id_as_string(get_snapshot_info_id(&info[i]));
- attrib = PyUnicode_FromString(text);
- ret = PyDict_SetItemString(item, "id", attrib);
- if (ret != 0) break;
-
- attrib = PyLong_FromUnsignedLongLong(get_snapshot_info_created(&info[i]));
- ret = PyDict_SetItemString(item, "created", attrib);
- if (ret != 0) break;
-
- text = get_snapshot_info_name(&info[i]);
-
- if (text != NULL)
- attrib = PyUnicode_FromString(text);
- else
- {
- attrib = Py_None;
- Py_INCREF(attrib);
- }
-
- ret = PyDict_SetItemString(item, "name", attrib);
- if (ret != 0) break;
-
- text = get_snapshot_info_desc(&info[i]);
-
- if (text != NULL)
- attrib = PyUnicode_FromString(text);
- else
- {
- attrib = Py_None;
- Py_INCREF(attrib);
- }
-
- ret = PyDict_SetItemString(item, "desc", attrib);
- if (ret != 0) break;
-
- PyTuple_SetItem(result, i, item);
-
- }
-
- failed = (i < count);
-
- for (i = 0; i < count; i++)
- exit_snapshot_info(&info[i]);
-
- free(info);
-
- if (failed)
- goto on_failure;
-
- }
-
- else
- {
- result = Py_None;
- Py_INCREF(result);
- }
-
- return result;
-
- on_failure:
-
- Py_DECREF(result);
-
- return NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* closure = non utilisé ici. *
-* *
-* Description : Fournit l'identifiant de l'instantané courant. *
-* *
-* Retour : Identifiant d'instantané ou None. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_hub_client_get_current_snapshot(PyObject *self, void *closure)
-{
- PyObject *result; /* Valeur à retourner */
- GHubClient *client; /* Version native du serveur */
- snapshot_id_t id; /* Identifiant à transmettre */
- bool status; /* Validité de cet identifiant */
-
-#define HUB_CLIENT_CURRENT_SNAPSHOT_ATTRIB PYTHON_GETSET_DEF_FULL \
-( \
- current_snapshot, py_hub_client, \
- "Identifier of the current snapshot, provided as a string." \
- "\n" \
- "The returned value is a cached version of the value stored at" \
- " server side. Thus, defining a new current snapshot is" \
- " successful as soon as the request to this server is sent." \
-)
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_get_current_snapshot(client, &id);
-
- if (status)
- result = PyUnicode_FromString(snapshot_id_as_string(&id));
-
- else
- {
- result = Py_None;
- Py_INCREF(result);
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = objet Python concerné par l'appel. *
-* value = valeur fournie à intégrer ou prendre en compte. *
-* closure = adresse non utilisée ici. *
-* *
-* Description : Définit l'identifiant de l'instantané courant. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static int py_hub_client_set_current_snapshot(PyObject *self, PyObject *value, void *closure)
-{
- int ret; /* Bilan d'analyse */
- void *raw; /* Valeur brute d'identifiant */
- snapshot_id_t id; /* Identifiant reconnu */
- bool status; /* Bilan d'une conversion */
- GHubClient *client; /* Version native du serveur */
-
- ret = PyUnicode_Check(value);
- if (!ret) return -1;
-
- raw = PyUnicode_DATA(value);
-
- status = init_snapshot_id_from_text(&id, raw);
- if (!status)
- {
- PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier."));
- return -1;
- }
-
- client = G_HUB_CLIENT(pygobject_get(self));
-
- status = g_hub_client_set_current_snapshot(client, &id);
- if (!status)
- {
- PyErr_SetString(PyExc_TypeError, "unable to send the provided snapshot identifier");
- return -1;
- }
-
- return 0;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -872,19 +180,10 @@ PyTypeObject *get_python_hub_client_type(void)
static PyMethodDef py_hub_client_methods[] = {
HUB_CLIENT_START_METHOD,
HUB_CLIENT_STOP_METHOD,
- HUB_CLIENT_SAVE_METHOD,
- HUB_CLIENT_SET_LAST_ACTIVE_METHOD,
- HUB_CLIENT_SET_SNAPSHOT_NAME_METHOD,
- HUB_CLIENT_SET_SNAPSHOT_DESC_METHOD,
- HUB_CLIENT_RESTORE_SNAPSHOT_METHOD,
- HUB_CLIENT_CREATE_SNAPSHOT_METHOD,
- HUB_CLIENT_REMOVE_SNAPSHOT_METHOD,
{ NULL }
};
static PyGetSetDef py_hub_client_getseters[] = {
- HUB_CLIENT_SNAPSHOTS_ATTRIB,
- HUB_CLIENT_CURRENT_SNAPSHOT_ATTRIB,
{ NULL }
};
@@ -901,7 +200,7 @@ PyTypeObject *get_python_hub_client_type(void)
.tp_methods = py_hub_client_methods,
.tp_getset = py_hub_client_getseters,
- .tp_new = py_hub_client_new,
+ .tp_new = no_python_constructor_allowed,
};
diff --git a/plugins/pychrysalide/analysis/db/module.c b/plugins/pychrysalide/analysis/db/module.c
index fa5a139..ddae5a7 100644
--- a/plugins/pychrysalide/analysis/db/module.c
+++ b/plugins/pychrysalide/analysis/db/module.c
@@ -28,6 +28,8 @@
#include <assert.h>
+#include "admin.h"
+#include "analyst.h"
#include "certs.h"
#include "client.h"
#include "collection.h"
@@ -98,6 +100,8 @@ bool populate_analysis_db_module(void)
result = true;
+ if (result) result = ensure_python_admin_client_is_registered();
+ if (result) result = ensure_python_analyst_client_is_registered();
if (result) result = ensure_python_certs_is_registered();
if (result) result = ensure_python_hub_client_is_registered();
if (result) result = ensure_python_db_collection_is_registered();
diff --git a/plugins/pychrysalide/analysis/db/server.c b/plugins/pychrysalide/analysis/db/server.c
index 80ff4e2..9e4ee61 100644
--- a/plugins/pychrysalide/analysis/db/server.c
+++ b/plugins/pychrysalide/analysis/db/server.c
@@ -83,7 +83,8 @@ static PyObject *py_hub_server_new(PyTypeObject *type, PyObject *args, PyObject
"\n" \
"Instances can be created using the following constructor:\n" \
"\n" \
- " HubServer(host=None, port='1337', ipv6=True)" \
+ " HubServer()" \
+ " HubServer(host='localhost', port='1337', ipv6=True)" \
"\n" \
"Where host and port define the listening properties of the server, and ipv6" \
" tries to establish IPv6 connections first." \