summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-02-19 11:55:28 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-02-19 11:55:28 (GMT)
commit588c206289a84bfc939ac27dacba991d9b6d0793 (patch)
tree0de656a445e236de1846e8f40e6635077b9d3f19 /src
parent1898c6ea16d0eee8ecc5ab9ebb26ac91ad7314b4 (diff)
Created client/server certificates on demand for a given identity.
Diffstat (limited to 'src')
-rw-r--r--src/analysis/db/certs.c45
-rw-r--r--src/analysis/db/certs.h3
-rw-r--r--src/analysis/db/keymgn.c429
-rw-r--r--src/analysis/db/keymgn.h26
-rw-r--r--src/core/core.c4
-rw-r--r--src/core/params.c39
-rw-r--r--src/core/params.h13
-rw-r--r--src/glibext/configuration.c40
-rw-r--r--src/glibext/configuration.h1
-rw-r--r--src/gui/dialogs/Makefile.am4
-rw-r--r--src/gui/dialogs/gresource.xml3
-rw-r--r--src/gui/dialogs/identity.c189
-rw-r--r--src/gui/dialogs/identity.h37
-rw-r--r--src/gui/dialogs/identity.ui278
-rw-r--r--src/gui/menus/Makefile.am1
-rw-r--r--src/gui/menus/menubar.c7
-rw-r--r--src/gui/menus/tools.c105
-rw-r--r--src/gui/menus/tools.h41
-rw-r--r--src/gui/panels/regedit.c22
19 files changed, 1284 insertions, 3 deletions
diff --git a/src/analysis/db/certs.c b/src/analysis/db/certs.c
index ac2ff39..8367c39 100644
--- a/src/analysis/db/certs.c
+++ b/src/analysis/db/certs.c
@@ -51,6 +51,47 @@ static bool add_extension_to_req(STACK_OF(X509_EXTENSION) *, int, /*const */char
/******************************************************************************
* *
+* Paramètres : entries = éléments d'identité à consulter. *
+* *
+* Description : Indique si une définition existe dans l'identité. *
+* *
+* Retour : Etat de la définition des entrées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool are_x509_entries_empty(const x509_entries *entries)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (entries->country != NULL)
+ result = false;
+
+ if (!result && entries->state != NULL)
+ result = false;
+
+ if (!result && entries->locality != NULL)
+ result = false;
+
+ if (!result && entries->organisation != NULL)
+ result = false;
+
+ if (!result && entries->organisational_unit != NULL)
+ result = false;
+
+ if (!result && entries->common_name != NULL)
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : entries = éléments d'identité à supprimer de la mémoire. *
* *
* Description : Libère la mémoire occupée par une définition d'identité. *
@@ -425,7 +466,7 @@ bool make_request(const char *dir, const char *label, const x509_entries *entrie
/* Signature */
- ret = X509_REQ_sign(x509, pk, EVP_sha1());
+ ret = X509_REQ_sign(x509, pk, EVP_sha256());
if (ret == 0) goto req_failed_2;
ret = X509_REQ_verify(x509, pk);
@@ -491,7 +532,7 @@ bool make_request(const char *dir, const char *label, const x509_entries *entrie
pk_failed:
- RSA_free(rsa);
+ RSA_free(rsa);
rsa_failed:
diff --git a/src/analysis/db/certs.h b/src/analysis/db/certs.h
index 0f7c51d..5d9142f 100644
--- a/src/analysis/db/certs.h
+++ b/src/analysis/db/certs.h
@@ -42,6 +42,9 @@ typedef struct _x509_entries
} x509_entries;
+/* Indique si une définition existe dans l'identité. */
+bool are_x509_entries_empty(const x509_entries *);
+
/* Libère la mémoire occupée par une définition d'identité. */
void free_x509_entries(x509_entries *);
diff --git a/src/analysis/db/keymgn.c b/src/analysis/db/keymgn.c
index 9c35289..e1afdcf 100644
--- a/src/analysis/db/keymgn.c
+++ b/src/analysis/db/keymgn.c
@@ -24,6 +24,435 @@
#include "keymgn.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "../../common/extstr.h"
+#include "../../common/pathname.h"
+#include "../../common/xdg.h"
+#include "../../core/params.h"
+
+
+
+/* Mémorise en mémoire la définition d'une identité courante. */
+static void store_identity(const x509_entries *, bool);
+
+/* Fournit le répertoire de travail pour les certifications. */
+static char *get_cert_working_directory(const char *, const char *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : client = précise la nature de l'identité à représenter. *
+* entries = éléments d'identité à définir en mémoire. [OUT] *
+* *
+* Description : Charge en mémoire la définition de l'identité courante. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void load_identity(bool client, x509_entries *entries)
+{
+ GGenConfig *config; /* Configuration à manipuler */
+ const char *path; /* Accès à la configuration */
+ char *saved; /* Valeur sauvegardée */
+ char *username; /* Dénomination affichée */
+ char *lang; /* Langage de l'utilisateur */
+ size_t length; /* Taille de valeur récupérée */
+ size_t first; /* Indice de première majuscule*/
+ size_t i; /* Boucle de parcours */
+
+ memset(entries, 0, sizeof(x509_entries));
+
+ /* Chargement à partir des sauvegardes */
+
+ config = get_main_configuration();
+
+ path = (client ? MPK_IDENTITY_CLIENT_C : MPK_IDENTITY_SERVER_C);
+
+ if (g_generic_config_get_value(get_main_configuration(), path, &saved))
+ entries->country = (saved != NULL ? strdup(saved) : NULL);
+
+ path = (client ? MPK_IDENTITY_CLIENT_ST : MPK_IDENTITY_SERVER_ST);
+
+ if (g_generic_config_get_value(get_main_configuration(), path, &saved))
+ entries->state = (saved != NULL ? strdup(saved) : NULL);
+
+ path = (client ? MPK_IDENTITY_CLIENT_L : MPK_IDENTITY_SERVER_L);
+
+ if (g_generic_config_get_value(get_main_configuration(), path, &saved))
+ entries->locality = (saved != NULL ? strdup(saved) : NULL);
+
+ path = (client ? MPK_IDENTITY_CLIENT_O : MPK_IDENTITY_SERVER_O);
+
+ if (g_generic_config_get_value(get_main_configuration(), path, &saved))
+ entries->organisation = (saved != NULL ? strdup(saved) : NULL);
+
+ path = (client ? MPK_IDENTITY_CLIENT_OU : MPK_IDENTITY_SERVER_OU);
+
+ if (g_generic_config_get_value(get_main_configuration(), path, &saved))
+ entries->organisational_unit = (saved != NULL ? strdup(saved) : NULL);
+
+ path = (client ? MPK_IDENTITY_CLIENT_CN : MPK_IDENTITY_SERVER_CN);
+
+ if (g_generic_config_get_value(get_main_configuration(), path, &saved))
+ entries->common_name = (saved != NULL ? strdup(saved) : NULL);
+
+ /* Si les valeurs n'étaient pas définies... */
+
+ if (are_x509_entries_empty(entries))
+ {
+ /* Identification de l'utilisateur */
+
+ username = getenv("USERNAME");
+
+ if (username == NULL)
+ username = getenv("USER");
+
+ if (username == NULL)
+ username = getenv("LOGNAME");
+
+ if (username != NULL)
+ entries->common_name = strdup(username);
+ else
+ entries->common_name = strdup("???");
+
+ /* Identification du pays */
+
+ lang = getenv("LANG");
+
+ if (lang != NULL)
+ {
+ length = strlen(lang);
+
+ first = length;
+
+ for (i = 0; i < length; i++)
+ {
+ if (isupper(lang[i]))
+ {
+ if (first == length)
+ first = i;
+ }
+
+ else if (first != length)
+ {
+ entries->country = strndup(&lang[first], i - first);
+ break;
+ }
+
+ }
+
+ }
+
+ if (entries->country == NULL)
+ entries->country = strdup("??");
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entries = éléments d'identité à conserver en mémoire. *
+* client = précise la nature de l'identité représentée. *
+* *
+* Description : Mémorise en mémoire la définition d'une identité courante. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void store_identity(const x509_entries *entries, bool client)
+{
+ GGenConfig *config; /* Configuration à manipuler */
+ const char *path; /* Accès à la configuration */
+
+ config = get_main_configuration();
+
+ path = (client ? MPK_IDENTITY_CLIENT_C : MPK_IDENTITY_SERVER_C);
+
+ g_generic_config_set_value(config, path, entries->country);
+
+ path = (client ? MPK_IDENTITY_CLIENT_ST : MPK_IDENTITY_SERVER_ST);
+
+ g_generic_config_set_value(config, path, entries->state);
+
+ path = (client ? MPK_IDENTITY_CLIENT_L : MPK_IDENTITY_SERVER_L);
+
+ g_generic_config_set_value(config, path, entries->locality);
+
+ path = (client ? MPK_IDENTITY_CLIENT_O : MPK_IDENTITY_SERVER_O);
+
+ g_generic_config_set_value(config, path, entries->organisation);
+
+ path = (client ? MPK_IDENTITY_CLIENT_OU : MPK_IDENTITY_SERVER_OU);
+
+ g_generic_config_set_value(config, path, entries->organisational_unit);
+
+ path = (client ? MPK_IDENTITY_CLIENT_CN : MPK_IDENTITY_SERVER_CN);
+
+ g_generic_config_set_value(config, path, entries->common_name);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type de certificat à gérer. *
+* name = dénomination du serveur visé. *
+* *
+* Description : Fournit le répertoire de travail pour les certifications. *
+* *
+* Retour : Définition d'emplacement à libérer de la mémoire après usage.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *get_cert_working_directory(const char *type, const char *name)
+{
+ char *result; /* Chemin à retourner */
+ char *suffix; /* Fin de la destination */
+
+ suffix = strdup("chrysalide");
+ suffix = stradd(suffix, G_DIR_SEPARATOR_S);
+ suffix = stradd(suffix, type);
+ suffix = stradd(suffix, G_DIR_SEPARATOR_S);
+ suffix = stradd(suffix, name);
+ suffix = stradd(suffix, G_DIR_SEPARATOR_S);
+
+ result = get_xdg_config_dir(suffix);
+
+ free(suffix);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entries = éléments d'identité à utiliser pour l'opération. *
+* *
+* Description : Définit les certificats utilisés pour les échanges internes. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_standalone_certs(const x509_entries *entries)
+{
+ bool result; /* Bilan de l'opération */
+ char *working; /* Répertoire par le client */
+ char *csr; /* Requête de signature */
+ char *cert; /* Certificat signé en sortie */
+
+ /* Certificats côtés serveur */
+
+ result = register_server_cert("standalone", entries);
+
+ if (result)
+ {
+ /* Demande de signature */
+
+ result = make_client_sign_request("standalone", entries);
+
+ /* Signature */
+
+ if (result)
+ {
+ working = get_cert_working_directory("clients", "standalone");
+
+ csr = build_absolute_filename(working, "client-csr.pem");
+ cert = build_absolute_filename(working, "client-cert.pem");
+
+ result = sign_client_request("standalone", csr, cert);
+
+ free(csr);
+ free(cert);
+
+ free(working);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : name = dénomination du serveur visé. *
+* entries = éléments d'identité à utiliser pour l'opération. *
+* *
+* Description : Définit les certificats utilisés pour par un serveur. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_server_cert(const char *name, const x509_entries *entries)
+{
+ bool result; /* Bilan de l'opération */
+ char *suffix; /* Fin de la destination */
+ char *working; /* Répertoire de travail */
+ unsigned long valid; /* Durée de validité */
+ char *csr; /* Requête de signature */
+ char *cacert; /* Certificat d'autorité */
+ char *cakey; /* Clef de cette autorité */
+ char *cert; /* Certificat signé en sortie */
+
+ result = false;
+
+ working = get_cert_working_directory("servers", name);
+
+ if (working != NULL)
+ {
+ result = mkpath(working);
+ if (!result) goto rsc_quick_exit;
+
+ result = g_generic_config_get_value(get_main_configuration(), MPK_IDENTITY_VALIDITY, &valid);
+
+ if (!result)
+ goto rsc_quick_exit;
+
+ result = make_ca(working, "ca", valid, entries);
+ if (!result) goto rsc_quick_exit;
+
+ result = make_request(working, "server", entries);
+ if (!result) goto rsc_quick_exit;
+
+ csr = build_absolute_filename(working, "server-csr.pem");
+ cacert = build_absolute_filename(working, "ca-cert.pem");
+ cakey = build_absolute_filename(working, "ca-key.pem");
+ cert = build_absolute_filename(working, "server-cert.pem");
+
+ result = sign_cert(csr, cacert, cakey, cert, valid);
+
+ if (result)
+ store_identity(entries, false);
+
+ free(csr);
+ free(cacert);
+ free(cakey);
+ free(cert);
+
+ rsc_quick_exit:
+
+ free(working);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : name = dénomination du serveur visé. *
+* entries = éléments d'identité à utiliser pour l'opération. *
+* *
+* Description : Elabore une demande de signature de certificat. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool make_client_sign_request(const char *name, const x509_entries *entries)
+{
+ bool result; /* Bilan de l'opération */
+ char *working; /* Répertoire par le client */
+
+ working = get_cert_working_directory("clients", name);
+
+ result = mkpath(working);
+
+ if (result)
+ result = make_request(working, "client", entries);
+
+ if (result)
+ store_identity(entries, true);
+
+ free(working);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : name = dénomination du serveur visé. *
+* csr = fichier contenant le certificat à signer. *
+* cert = fichier contenant le certificat signé. *
+* *
+* Description : Signe un certificat client pour un accès un serveur donné. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool sign_client_request(const char *name, const char *csr, const char *cert)
+{
+ bool result; /* Bilan de l'opération */
+ char *working; /* Répertoire par le serveur */
+ unsigned long valid; /* Durée de validité */
+ char *cacert; /* Certificat d'autorité */
+ char *cakey; /* Clef de cette autorité */
+
+ working = get_cert_working_directory("servers", name);
+
+ result = g_generic_config_get_value(get_main_configuration(), MPK_IDENTITY_VALIDITY, &valid);
+
+ if (!result)
+ goto scr_exit;
+
+ cacert = build_absolute_filename(working, "ca-cert.pem");
+ cakey = build_absolute_filename(working, "ca-key.pem");
+
+ result = sign_cert(csr, cacert, cakey, cert, valid);
+
+ free(cacert);
+ free(cakey);
+
+ scr_exit:
+
+ free(working);
+
+ return result;
+
+}
+
+
+
+
+
+
+
+
+
+
#include <assert.h>
#include <glib.h>
#include <malloc.h>
diff --git a/src/analysis/db/keymgn.h b/src/analysis/db/keymgn.h
index 6d4703c..f2b2b74 100644
--- a/src/analysis/db/keymgn.h
+++ b/src/analysis/db/keymgn.h
@@ -26,6 +26,32 @@
#include <stdbool.h>
+
+
+#include "certs.h"
+
+
+
+/* Charge en mémoire la définition de l'identité courante. */
+void load_identity(bool, x509_entries *);
+
+/* Définit les certificats utilisés pour les échanges internes. */
+bool register_standalone_certs(const x509_entries *);
+
+/* Définit les certificats utilisés pour par un serveur. */
+bool register_server_cert(const char *, const x509_entries *);
+
+/* Elabore une demande de signature de certificat. */
+bool make_client_sign_request(const char *, const x509_entries *);
+
+/* Signe un certificat client pour un accès un serveur donné. */
+bool sign_client_request(const char *, const char *, const char *);
+
+
+
+
+
+#include <stdbool.h>
#include <openssl/rsa.h>
diff --git a/src/core/core.c b/src/core/core.c
index e265250..9750fc6 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
+#include <openssl/ssl.h>
#include <config.h>
@@ -79,6 +80,9 @@ bool load_all_basic_components(void)
result &= load_main_config_parameters();
+ SSL_load_error_strings();
+ SSL_library_init();
+
result &= ensure_user_has_rsa_keys();
result &= g_generic_config_read(get_main_configuration());
diff --git a/src/core/params.c b/src/core/params.c
index 1611e98..a82f186 100644
--- a/src/core/params.c
+++ b/src/core/params.c
@@ -120,6 +120,45 @@ bool load_main_config_parameters(void)
free(string);
if (param == NULL) return false;
+ param = g_generic_config_create_param(config, MPK_IDENTITY_CLIENT_C, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_CLIENT_ST, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_CLIENT_L, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_CLIENT_O, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_CLIENT_OU, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_CLIENT_CN, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_SERVER_C, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_SERVER_ST, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_SERVER_L, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_SERVER_O, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_SERVER_OU, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_SERVER_CN, CPT_STRING, NULL);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_IDENTITY_VALIDITY, CPT_ULONG, 10 * 365 * 24 * 60 * 60);
+ if (param == NULL) return false;
+
param = g_generic_config_create_param(config, MPK_REMOTE_HOST, CPT_STRING, "localhost");
if (param == NULL) return false;
diff --git a/src/core/params.h b/src/core/params.h
index ec55710..9bbffc6 100644
--- a/src/core/params.h
+++ b/src/core/params.h
@@ -34,6 +34,19 @@
*/
#define MPK_AUTHOR_NAME "cdb.default.author"
+#define MPK_IDENTITY_CLIENT_C "cdb.identity.client.country"
+#define MPK_IDENTITY_CLIENT_ST "cdb.identity.client.state"
+#define MPK_IDENTITY_CLIENT_L "cdb.identity.client.locality"
+#define MPK_IDENTITY_CLIENT_O "cdb.identity.client.organisation"
+#define MPK_IDENTITY_CLIENT_OU "cdb.identity.client.organisational_unit"
+#define MPK_IDENTITY_CLIENT_CN "cdb.identity.client.common_name"
+#define MPK_IDENTITY_SERVER_C "cdb.identity.server.country"
+#define MPK_IDENTITY_SERVER_ST "cdb.identity.server.state"
+#define MPK_IDENTITY_SERVER_L "cdb.identity.server.locality"
+#define MPK_IDENTITY_SERVER_O "cdb.identity.server.organisation"
+#define MPK_IDENTITY_SERVER_OU "cdb.identity.server.organisational_unit"
+#define MPK_IDENTITY_SERVER_CN "cdb.identity.server.common_name"
+#define MPK_IDENTITY_VALIDITY "cdb.identity.validity"
#define MPK_REMOTE_HOST "cdb.default.network.remote.server"
#define MPK_REMOTE_PORT "cdb.default.network.remote.port"
#define MPK_LOCAL_HOST "cdb.network.local.server"
diff --git a/src/glibext/configuration.c b/src/glibext/configuration.c
index b1a16f0..718f7c0 100644
--- a/src/glibext/configuration.c
+++ b/src/glibext/configuration.c
@@ -50,6 +50,7 @@ typedef union _param_value
{
bool boolean; /* Valeur booléenne */
int integer; /* Valeur entière */
+ unsigned long ulong; /* Valeur entière positive */
char *string; /* Chaîne de caractères */
} param_value;
@@ -332,6 +333,10 @@ GCfgParam *g_config_param_new(const char *path, ConfigParamType type, ...)
result->def.integer = va_arg(ap, int);
break;
+ case CPT_ULONG:
+ result->def.ulong = va_arg(ap, unsigned long);
+ break;
+
case CPT_STRING:
result->def.string = va_arg(ap, char *);
if (result->def.string != NULL)
@@ -406,6 +411,7 @@ static bool g_config_param_read(GCfgParam *param, xmlXPathContextPtr context)
{
char *access; /* Chemin d'accès XML */
char *value; /* Valeur en chaîne de carac. */
+ unsigned long ulval; /* Valeur transformée */
access = strdup(param->path);
access = strrpl(access, ".", "/");
@@ -428,6 +434,11 @@ static bool g_config_param_read(GCfgParam *param, xmlXPathContextPtr context)
g_config_param_set_value(param, atoi(value));
break;
+ case CPT_ULONG:
+ ulval = strtoul(value, NULL, 10);
+ g_config_param_set_value(param, ulval);
+ break;
+
case CPT_STRING:
g_config_param_set_value(param, value);
break;
@@ -469,6 +480,7 @@ static bool g_config_param_write(GCfgParam *param, xmlDocPtr xdoc, xmlXPathConte
ConfigParamState state; /* Etat du paramètre */
char *access; /* Chemin d'accès XML */
char int_val[sizeof(XSTR(INT_MIN)) + 1];/* Valeur en chaîne de carac. */
+ char ul_val[sizeof(XSTR(ULONG_MAX)) + 1];/* Valeur en chaîne de carac. */
state = g_config_param_get_state(param);
@@ -497,6 +509,11 @@ static bool g_config_param_write(GCfgParam *param, xmlDocPtr xdoc, xmlXPathConte
result = add_content_to_node(xdoc, context, access, int_val);
break;
+ case CPT_ULONG:
+ snprintf(ul_val, sizeof(ul_val), "%lu", param->cur.ulong);
+ result = add_content_to_node(xdoc, context, access, ul_val);
+ break;
+
case CPT_STRING:
if (param->def.string != NULL && param->def.string != NULL
@@ -620,6 +637,10 @@ ConfigParamState g_config_param_get_state(GCfgParam *param)
param->cached_state = (param->def.integer == param->cur.integer ? CPS_DEFAULT : CPS_CHANGED);
break;
+ case CPT_ULONG:
+ param->cached_state = (param->def.ulong == param->cur.ulong ? CPS_DEFAULT : CPS_CHANGED);
+ break;
+
case CPT_STRING:
if (param->def.string == NULL && param->cur.string == NULL)
param->cached_state = CPS_DEFAULT;
@@ -667,6 +688,10 @@ void g_config_param_make_empty(GCfgParam *param)
param->cur.integer = INT_MIN;
break;
+ case CPT_ULONG:
+ param->cur.ulong = 0;
+ break;
+
case CPT_STRING:
if (param->cur.string != NULL)
{
@@ -722,6 +747,10 @@ void g_config_param_reset(GCfgParam *param)
param->cur.integer = param->def.integer;
break;
+ case CPT_ULONG:
+ param->cur.ulong = param->def.ulong;
+ break;
+
case CPT_STRING:
if (param->def.string != NULL)
param->cur.string = strdup(param->def.string);
@@ -767,6 +796,7 @@ void g_config_param_set_value(GCfgParam *param, ...)
va_list ap; /* Liste d'arguments */
bool old_boolean; /* Valeur booléenne */
int old_integer; /* Valeur entière */
+ unsigned long old_ulong; /* Valeur entière positive */
char *old_string; /* Chaîne de caractères */
bool modified; /* Détermine une modification */
@@ -786,6 +816,12 @@ void g_config_param_set_value(GCfgParam *param, ...)
modified = (old_integer != param->cur.integer);
break;
+ case CPT_ULONG:
+ old_ulong = param->cur.ulong;
+ param->cur.ulong = va_arg(ap, unsigned long);
+ modified = (old_ulong != param->cur.ulong);
+ break;
+
case CPT_STRING:
old_string = param->cur.string;
param->cur.string = va_arg(ap, char *);
@@ -856,6 +892,10 @@ void g_config_param_get_value(GCfgParam *param, ...)
*(va_arg(ap, int *)) = param->cur.integer;
break;
+ case CPT_ULONG:
+ *(va_arg(ap, unsigned long *)) = param->cur.ulong;
+ break;
+
case CPT_STRING:
*(va_arg(ap, char **)) = param->cur.string;
break;
diff --git a/src/glibext/configuration.h b/src/glibext/configuration.h
index bed0462..c78d3ca 100644
--- a/src/glibext/configuration.h
+++ b/src/glibext/configuration.h
@@ -38,6 +38,7 @@ typedef enum _ConfigParamType
{
CPT_BOOLEAN, /* Valeur booléenne */
CPT_INTEGER, /* Valeur entière */
+ CPT_ULONG, /* Valeur entière positive */
CPT_STRING, /* Chaîne de caractère */
CPT_COUNT
diff --git a/src/gui/dialogs/Makefile.am b/src/gui/dialogs/Makefile.am
index e1774d7..bb2087b 100644
--- a/src/gui/dialogs/Makefile.am
+++ b/src/gui/dialogs/Makefile.am
@@ -4,7 +4,8 @@ BUILT_SOURCES = resources.h resources.c
noinst_LTLIBRARIES = libguidialogs.la
UI_FILES = \
- binadmin.ui
+ binadmin.ui \
+ identity.ui
libguidialogs_la_SOURCES = \
about.h about.c \
@@ -12,6 +13,7 @@ libguidialogs_la_SOURCES = \
export.h export.c \
goto.h goto.c \
gotox.h gotox.c \
+ identity.h identity.c \
plugins.h plugins.c \
resources.h resources.c \
shellcode.h shellcode.c \
diff --git a/src/gui/dialogs/gresource.xml b/src/gui/dialogs/gresource.xml
index 913b830..d1ba8b6 100644
--- a/src/gui/dialogs/gresource.xml
+++ b/src/gui/dialogs/gresource.xml
@@ -3,4 +3,7 @@
<gresource prefix="/org/chrysalide/gui/dialogs">
<file compressed="true">binadmin.ui</file>
</gresource>
+ <gresource prefix="/org/chrysalide/gui/dialogs">
+ <file compressed="true">identity.ui</file>
+ </gresource>
</gresources>
diff --git a/src/gui/dialogs/identity.c b/src/gui/dialogs/identity.c
new file mode 100644
index 0000000..0f6a111
--- /dev/null
+++ b/src/gui/dialogs/identity.c
@@ -0,0 +1,189 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * identity.c - (re)définition de l'identité de l'utilisateur
+ *
+ * Copyright (C) 2017 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "identity.h"
+
+
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "../panels/log.h"
+#include "../../analysis/db/keymgn.h"
+
+
+
+/* Applique la nouvelle définition d'identité. */
+static void update_identity(GtkButton *button, GtkBuilder *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : parent = fenêtre principale de l'éditeur. *
+* outb = constructeur à détruire après usage. [OUT] *
+* *
+* Description : Propose une édition des informations conernant l'utilisateur.*
+* *
+* Retour : Adresse de la fenêtre mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *create_identity_dialog(GtkWindow *parent, GtkBuilder **outb)
+{
+ GtkWidget *result; /* Fenêtre à renvoyer */
+ GtkBuilder *builder; /* Constructeur utilisé */
+ x509_entries entries; /* Eléments identitaires */
+ GtkEntry *entry; /* Zone de saisie à initialiser*/
+
+ builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/identity.ui");
+ *outb = builder;
+
+ result = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+
+ gtk_window_set_transient_for(GTK_WINDOW(result), parent);
+
+ /* Mise à jour de l'interface */
+
+ load_identity(true, &entries);
+
+ if (entries.country != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "c"));
+ gtk_entry_set_text(entry, entries.country);
+ }
+
+ if (entries.state != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "st"));
+ gtk_entry_set_text(entry, entries.state);
+ }
+
+ if (entries.locality != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "l"));
+ gtk_entry_set_text(entry, entries.locality);
+ }
+
+ if (entries.organisation != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "o"));
+ gtk_entry_set_text(entry, entries.organisation);
+ }
+
+ if (entries.organisational_unit != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "ou"));
+ gtk_entry_set_text(entry, entries.organisational_unit);
+ }
+
+ if (entries.country != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "cn"));
+ gtk_entry_set_text(entry, entries.common_name);
+
+ gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
+
+ }
+
+ /* Connexion des signaux */
+
+ gtk_builder_add_callback_symbols(builder,
+ "update_identity", G_CALLBACK(update_identity),
+ NULL);
+
+ gtk_builder_connect_signals(builder, builder);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* builder = espace de référencement global. *
+* *
+* Description : Applique la nouvelle définition d'identité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void update_identity(GtkButton *button, GtkBuilder *builder)
+{
+ GtkEntry *entry; /* Zone de saisie à consulter */
+ const gchar *data; /* Données internes à GTK */
+ x509_entries entries; /* Nouvelle identité à pousser */
+ bool status; /* Bilan de la mise à jour */
+
+ /* Récupération des éléments */
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "c"));
+ data = gtk_entry_get_text(entry);
+
+ entries.country = (strlen(data) > 0 ? strdup(data) : NULL);
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "st"));
+ data = gtk_entry_get_text(entry);
+
+ entries.state = (strlen(data) > 0 ? strdup(data) : NULL);
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "l"));
+ data = gtk_entry_get_text(entry);
+
+ entries.locality = (strlen(data) > 0 ? strdup(data) : NULL);
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "o"));
+ data = gtk_entry_get_text(entry);
+
+ entries.organisation = (strlen(data) > 0 ? strdup(data) : NULL);
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "ou"));
+ data = gtk_entry_get_text(entry);
+
+ entries.organisational_unit = (strlen(data) > 0 ? strdup(data) : NULL);
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "cn"));
+ data = gtk_entry_get_text(entry);
+
+ entries.common_name = (strlen(data) > 0 ? strdup(data) : NULL);
+
+ /* Application de la nouvelle définition */
+
+ status = register_standalone_certs(&entries);
+
+ free_x509_entries(&entries);
+
+ if (status)
+ log_simple_message(LMT_INFO, _("New identity has been loaded with success!"));
+ else
+ log_simple_message(LMT_ERROR, _("Failure while loading the new identity..."));
+
+}
diff --git a/src/gui/dialogs/identity.h b/src/gui/dialogs/identity.h
new file mode 100644
index 0000000..2019eba
--- /dev/null
+++ b/src/gui/dialogs/identity.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * identity.h - prototypes pour la (re)définition de l'identité de l'utilisateur
+ *
+ * Copyright (C) 2017 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_IDENTITY_H
+#define _GUI_DIALOGS_IDENTITY_H
+
+
+#include <gtk/gtk.h>
+
+
+
+/* Propose une édition des informations conernant l'utilisateur. */
+GtkWidget *create_identity_dialog(GtkWindow *, GtkBuilder **);
+
+
+
+#endif /* _GUI_DIALOGS_IDENTITY_H */
diff --git a/src/gui/dialogs/identity.ui b/src/gui/dialogs/identity.ui
new file mode 100644
index 0000000..f622a91
--- /dev/null
+++ b/src/gui/dialogs/identity.ui
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <object class="GtkDialog" id="window">
+ <property name="width_request">515</property>
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Identity</property>
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="default_width">515</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="margin_left">8</property>
+ <property name="margin_right">8</property>
+ <property name="margin_top">8</property>
+ <property name="margin_bottom">8</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <property name="always_show_image">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button2">
+ <property name="label">gtk-apply</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="clicked" handler="update_identity" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">8</property>
+ <child>
+ <object class="GtkSeparator" id="separator1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">8</property>
+ <property name="margin_right">8</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="width_request">500</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">All the following information is used to create your authentication certifcate. This certificate grants you access to database servers and identifies each analysis change.
+
+&lt;b&gt;Warning: &lt;/b&gt; updating this information drives to new signing requests for remote servers!</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Common name (required):</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="cn">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator" id="separator3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">8</property>
+ <property name="margin_right">8</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Organisational unit:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ou">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="o">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Organisation:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator" id="separator4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">8</property>
+ <property name="margin_right">8</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Locality:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="l">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="st">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">State:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Country (two letters):</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="c">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">button1</action-widget>
+ <action-widget response="-10">button2</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/src/gui/menus/Makefile.am b/src/gui/menus/Makefile.am
index 014f098..7e5a1c3 100644
--- a/src/gui/menus/Makefile.am
+++ b/src/gui/menus/Makefile.am
@@ -10,6 +10,7 @@ libguimenus_la_SOURCES = \
menubar.h menubar.c \
plugins.h plugins.c \
project.h project.c \
+ tools.h tools.c \
view.h view.c
libguimenus_la_LDFLAGS =
diff --git a/src/gui/menus/menubar.c b/src/gui/menus/menubar.c
index 1ccbb00..56540e9 100644
--- a/src/gui/menus/menubar.c
+++ b/src/gui/menus/menubar.c
@@ -32,6 +32,7 @@
#include "help.h"
#include "plugins.h"
#include "project.h"
+#include "tools.h"
#include "view.h"
#include "../editem-int.h"
@@ -48,6 +49,7 @@ struct _GMenuBar
GtkWidget *project; /* Menu "Projet" */
GtkWidget *binary; /* Menu "Binaire" */
GtkWidget *debug; /* Menu "Débogage" */
+ GtkWidget *tools; /* Menu "Outils" */
GtkWidget *plugins; /* Menu "Greffons" */
GtkWidget *help; /* Menu "Aide" */
@@ -247,6 +249,11 @@ GEditorItem *g_menu_bar_new(GObject *ref, GtkAccelGroup *accgroup)
result->debug = build_menu_debug(ref, accgroup);
gtk_container_add(GTK_CONTAINER(item->widget), result->debug);
+ /* Outils */
+
+ result->tools = build_menu_tools(ref, accgroup, result);
+ gtk_container_add(GTK_CONTAINER(item->widget), result->tools);
+
/* Greffons */
result->plugins = build_menu_plugins(ref, accgroup);
diff --git a/src/gui/menus/tools.c b/src/gui/menus/tools.c
new file mode 100644
index 0000000..2ec9551
--- /dev/null
+++ b/src/gui/menus/tools.c
@@ -0,0 +1,105 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tools.c - gestion du menu 'Outils'
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ * This binary 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 "tools.h"
+
+
+#include <i18n.h>
+
+
+#include "../editem-int.h"
+#include "../dialogs/identity.h"
+#include "../../gtkext/easygtk.h"
+
+
+
+/* Réagit au menu "Outils -> Identité". */
+static void mcb_tools_identity(GtkMenuItem *, GMenuBar *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : ref = espace de référencement global. *
+* accgroup = groupe d'accélérateurs pour les menus. *
+* bar = barre de menu parente. *
+* *
+* Description : Construit le menu "Outils". *
+* *
+* Retour : Panneau de menus mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *build_menu_tools(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar)
+{
+ GtkWidget *result; /* Support à retourner */
+ GtkWidget *menubar; /* Support pour éléments */
+ GtkWidget *submenuitem; /* Sous-élément de menu */
+
+ result = gtk_menu_item_new_with_mnemonic(_("_Tools"));
+ gtk_widget_show(result);
+
+ menubar = qck_create_menu(GTK_MENU_ITEM(result));
+
+ submenuitem = qck_create_menu_item(ref, "mnu_tools_identity", _("Identity"),
+ G_CALLBACK(mcb_tools_identity), bar);
+ gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : menuitem = élément de menu sélectionné. *
+* bar = barre de menu parente. *
+* *
+* Description : Réagit au menu "Outils -> Identité". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void mcb_tools_identity(GtkMenuItem *menuitem, GMenuBar *bar)
+{
+ GObject *ref; /* Espace de référencements */
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkWidget *dialog; /* Boîte de dialogue à montrer */
+
+ ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(bar));
+
+ dialog = create_identity_dialog(GTK_WINDOW(ref), &builder);
+
+ gtk_dialog_run(GTK_DIALOG(dialog));
+
+ gtk_widget_destroy(dialog);
+
+ g_object_unref(G_OBJECT(builder));
+
+}
diff --git a/src/gui/menus/tools.h b/src/gui/menus/tools.h
new file mode 100644
index 0000000..0c76137
--- /dev/null
+++ b/src/gui/menus/tools.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tools.h - prototypes pour la gestion du menu 'Outils'
+ *
+ * Copyright (C) 2017 Cyrille Bagard
+ *
+ * This binary 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 _GUI_MENUS_TOOLS_H
+#define _GUI_MENUS_TOOLS_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "menubar.h"
+
+
+
+/* Construit le menu "Outils". */
+GtkWidget *build_menu_tools(GObject *, GtkAccelGroup *, GMenuBar *);
+
+
+
+#endif /* _GUI_MENUS_TOOLS_H */
diff --git a/src/gui/panels/regedit.c b/src/gui/panels/regedit.c
index 579c60b..501bd2f 100644
--- a/src/gui/panels/regedit.c
+++ b/src/gui/panels/regedit.c
@@ -458,6 +458,10 @@ static void reload_config_into_treeview(GRegeditPanel *panel, GGenConfig *config
type_desc = _("Integer");
break;
+ case CPT_ULONG:
+ type_desc = _("Unsigned long");
+ break;
+
case CPT_STRING:
type_desc = _("String");
break;
@@ -547,6 +551,8 @@ static void update_config_param_value(GtkTreeStore *store, GtkTreeIter *iter)
bool boolean; /* Valeur booléenne */
int integer; /* Valeur entière */
char int_val[sizeof(XSTR(INT_MIN)) + 1];/* Valeur en chaîne de carac. */
+ unsigned long ulong; /* Valeur entière positive */
+ char ul_val[sizeof(XSTR(ULONG_MAX)) + 1];/* Valeur en chaîne de carac. */
char *string; /* Chaîne de caractères */
char *desc; /* Description à afficher */
@@ -579,6 +585,12 @@ static void update_config_param_value(GtkTreeStore *store, GtkTreeIter *iter)
desc = int_val;
break;
+ case CPT_ULONG:
+ g_config_param_get_value(param, &ulong);
+ snprintf(ul_val, sizeof(ul_val), "%lu", ulong);
+ desc = ul_val;
+ break;
+
case CPT_STRING:
g_config_param_get_value(param, &string);
desc = (string != NULL ? string : "");
@@ -720,6 +732,7 @@ static void on_param_value_edited(GtkCellRendererText *renderer, gchar *path, gc
GCfgParam *param; /* Paramètre à actualiser */
bool boolean; /* Valeur booléenne */
int integer; /* Valeur entière */
+ int ulong; /* Valeur entière positive */
char *end; /* Pointeur vers '\0' final ? */
tree_path = gtk_tree_path_new_from_string(path);
@@ -751,6 +764,15 @@ static void on_param_value_edited(GtkCellRendererText *renderer, gchar *path, gc
break;
+ case CPT_ULONG:
+
+ ulong = strtoul(new, &end, 10);
+ if (*end != '\0') goto opve_bad_value;
+
+ g_config_param_set_value(param, ulong);
+
+ break;
+
case CPT_STRING:
g_config_param_set_value(param, new);
break;