summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-09-01 21:37:51 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-09-01 21:37:51 (GMT)
commita820f204162f61e3e7a91e66c1aabea22f23d0cb (patch)
treed8cd00ab7dbef97272858c5217ce3ef4b6981996 /src
parent14f1b8ff552dfb8aef6c66b3c65e816aa7820bb0 (diff)
Prepared the update of the user identity from the GUI.
Diffstat (limited to 'src')
-rw-r--r--src/analysis/db/auth.c49
-rw-r--r--src/analysis/db/auth.h3
-rw-r--r--src/analysis/db/certs.c109
-rw-r--r--src/analysis/db/certs.h3
-rw-r--r--src/gui/dialogs/identity.c111
-rw-r--r--src/gui/dialogs/identity.ui119
6 files changed, 301 insertions, 93 deletions
diff --git a/src/analysis/db/auth.c b/src/analysis/db/auth.c
index af51af6..5e62f58 100644
--- a/src/analysis/db/auth.c
+++ b/src/analysis/db/auth.c
@@ -209,6 +209,38 @@ static char *get_cert_storage_directory(const char *outdir, const char *host, co
/******************************************************************************
* *
+* Paramètres : - *
+* *
+* Description : Détermine la désignation par défaut de l'usager. *
+* *
+* Retour : Nom déterminé à libérer de la mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *get_default_username(void)
+{
+ char *result; /* Désignation à retourner */
+ uid_t uid; /* Identifiant d'utilisateur */
+ struct passwd *pw; /* Indications sur l'usager */
+
+ uid = geteuid();
+ pw = getpwuid(uid);
+
+ if (pw != NULL)
+ result = strdup(pw->pw_name);
+
+ else
+ result = strdup("anonymous");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : valid = durée de validité des certificats. *
* entries = éléments d'identité à utiliser pour l'opération. *
* *
@@ -224,8 +256,6 @@ bool setup_client_identity(unsigned long valid, x509_entries *entries)
{
bool result; /* Bilan de l'opération */
char *working; /* Répertoire pour le client */
- uid_t uid; /* Identifiant d'utilisateur */
- struct passwd *pw; /* Indications sur l'usager */
working = get_db_working_directory("clients", NULL, NULL, NULL);
@@ -235,18 +265,11 @@ bool setup_client_identity(unsigned long valid, x509_entries *entries)
{
if (entries->common_name == NULL)
{
- uid = geteuid();
- pw = getpwuid(uid);
-
- if (pw != NULL)
- {
- log_variadic_message(LMT_WARNING,
- _("Replaced the empty identity common name with '%s'"),
- pw->pw_name);
-
- entries->common_name = strdup(pw->pw_name);
+ entries->common_name = get_default_username();
- }
+ log_variadic_message(LMT_WARNING,
+ _("Replaced the empty identity common name with '%s'"),
+ entries->common_name);
}
diff --git a/src/analysis/db/auth.h b/src/analysis/db/auth.h
index 4db7af7..4464244 100644
--- a/src/analysis/db/auth.h
+++ b/src/analysis/db/auth.h
@@ -39,6 +39,9 @@ bool build_internal_server_socket(struct sockaddr_un *);
/* Fournit le répertoire de travail pour les données d'analyse. */
char *get_db_working_directory(const char *, const char *, const char *, const char *);
+/* Détermine la désignation par défaut de l'usager. */
+char *get_default_username(void);
+
/* Etablit une base pour l'identité de l'utilisateur. */
bool setup_client_identity(unsigned long, x509_entries *);
diff --git a/src/analysis/db/certs.c b/src/analysis/db/certs.c
index a333d9a..107b7b9 100644
--- a/src/analysis/db/certs.c
+++ b/src/analysis/db/certs.c
@@ -24,6 +24,7 @@
#include "certs.h"
+#include <assert.h>
#include <glib.h>
#include <malloc.h>
#include <stdio.h>
@@ -258,7 +259,7 @@ bool build_keys_and_ca(const char *dir, const char *label, unsigned long valid,
EVP_PKEY *pk; /* Enveloppe pour clef publique*/
int ret; /* Bilan d'un appel */
X509 *x509; /* Certificat X509 à définir */
- X509_NAME *name; /* Désignation du certificat */
+ X509_NAME *subject; /* SUjet du certificat */
char *filename; /* Chemin d'accès à un fichier */
FILE *stream; /* Flux ouvert en écriture */
@@ -288,14 +289,14 @@ bool build_keys_and_ca(const char *dir, const char *label, unsigned long valid,
/* Etablissement d'une identité */
- name = X509_get_subject_name(x509);
+ subject = X509_get_subject_name(x509);
#define SET_NAME_ENTRY(key, value) \
do \
{ \
if (entries->value != NULL) \
{ \
- ret = X509_NAME_add_entry_by_txt(name, key, MBSTRING_UTF8, \
+ ret = X509_NAME_add_entry_by_txt(subject, key, MBSTRING_UTF8, \
(unsigned char *)entries->value, -1, -1, 0); \
if (ret != 1) goto ca_failed; \
} \
@@ -316,7 +317,7 @@ bool build_keys_and_ca(const char *dir, const char *label, unsigned long valid,
#undef SET_NAME_ENTRY
- ret = X509_set_issuer_name(x509, name);
+ ret = X509_set_issuer_name(x509, subject);
if (ret != 1) goto ca_failed;
/* Extensions */
@@ -461,7 +462,7 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri
EVP_PKEY *pk; /* Enveloppe pour clef publique*/
int ret; /* Bilan d'un appel */
X509_REQ *x509; /* Certificat X509 à définir */
- X509_NAME *name; /* Désignation du certificat */
+ X509_NAME *subject; /* Sujet du certificat */
STACK_OF(X509_EXTENSION) *exts; /* Extensions du certificat */
char *filename; /* Chemin d'accès à un fichier */
FILE *stream; /* Flux ouvert en écriture */
@@ -483,14 +484,14 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri
/* Etablissement d'une identité */
- name = X509_REQ_get_subject_name(x509);
+ subject = X509_REQ_get_subject_name(x509);
#define SET_NAME_ENTRY(key, value) \
do \
{ \
if (entries->value != NULL) \
{ \
- ret = X509_NAME_add_entry_by_txt(name, key, MBSTRING_UTF8, \
+ ret = X509_NAME_add_entry_by_txt(subject, key, MBSTRING_UTF8, \
(unsigned char *)entries->value, -1, -1, 0); \
if (ret != 1) goto req_failed; \
} \
@@ -603,6 +604,88 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri
/******************************************************************************
* *
+* Paramètres : csr = fichier contenant le certificat à signer. *
+* entries = éléments de l'identité constituée. [OUT] *
+* *
+* Description : Recharge l'identité inscrite dans une requête de signature. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_identity_from_request(const char *csr, x509_entries *entries)
+{
+ bool result; /* Bilan à retourner */
+ FILE *stream; /* Flux ouvert en lecture */
+ X509_REQ *req; /* Certificat X509 à signer */
+ X509_NAME *subject; /* Sujet du certificat */
+ int length; /* Taille du champ visé */
+
+ result = false;
+
+ memset(entries, 0, sizeof(*entries));
+
+ /* Chargement de la requête */
+
+ stream = fopen(csr, "rb");
+ if (stream == NULL) goto csr_read_failed;
+
+ req = PEM_read_X509_REQ(stream, NULL, NULL, NULL);
+
+ fclose(stream);
+
+ if (req == NULL)
+ {
+ log_variadic_message(LMT_ERROR, _("Unable to read the certificate signing request from '%s'"), csr);
+ goto csr_read_failed;
+ }
+
+ /* Recherche des éléments */
+
+ subject = X509_REQ_get_subject_name(req);
+
+#define GET_NAME_ENTRY(key, value) \
+ do \
+ { \
+ length = X509_NAME_get_text_by_NID(subject, key, NULL, -1); \
+ if (length != -1) \
+ { \
+ entries->value = malloc((length + 1) * sizeof(char)); \
+ length = X509_NAME_get_text_by_NID(subject, key, entries->value, length + 1); \
+ assert(length != -1); \
+ } \
+ } \
+ while (0)
+
+ GET_NAME_ENTRY(NID_countryName, country);
+
+ GET_NAME_ENTRY(NID_stateOrProvinceName, state);
+
+ GET_NAME_ENTRY(NID_localityName, locality);
+
+ GET_NAME_ENTRY(NID_organizationName, organisation);
+
+ GET_NAME_ENTRY(NID_organizationalUnitName, organisational_unit);
+
+ GET_NAME_ENTRY(NID_commonName, common_name);
+
+#undef GET_NAME_ENTRY
+
+ X509_REQ_free(req);
+
+ result = true;
+
+ csr_read_failed:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : csr = fichier contenant le certificat à signer. *
* cacert = fichier contenant le certificat de l'autorité. *
* cakey = fichier contenant la clef privée du CA. *
@@ -619,14 +702,14 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri
bool sign_cert(const char *csr, const char *cacert, const char *cakey, const char *cert, unsigned long valid)
{
- FILE *stream; /* Flux ouvert en écriture */
+ FILE *stream; /* Flux ouvert en lecture */
X509_REQ *req; /* Certificat X509 à signer */
EVP_PKEY *pk; /* Enveloppe pour clef publique*/
X509 *ca_cert; /* Certificat de l'autorité */
EVP_PKEY *ca_pk; /* Enveloppe pour clef privée */
X509 *x509; /* Certificat X509 à définir */
int ret; /* Bilan d'un appel */
- X509_NAME *name; /* Désignation du certificat */
+ X509_NAME *subject; /* Sujet de certificat */
/* Chargement de la requête */
@@ -696,14 +779,14 @@ bool sign_cert(const char *csr, const char *cacert, const char *cakey, const cha
ret = X509_set_pubkey(x509, pk);
if (ret != 1) goto signing_failed;
- name = X509_REQ_get_subject_name(req);
+ subject = X509_REQ_get_subject_name(req);
- ret = X509_set_subject_name(x509, name);
+ ret = X509_set_subject_name(x509, subject);
if (ret != 1) goto signing_failed;
- name = X509_get_subject_name(ca_cert);
+ subject = X509_get_subject_name(ca_cert);
- ret = X509_set_issuer_name(x509, name);
+ ret = X509_set_issuer_name(x509, subject);
if (ret != 1) goto signing_failed;
/* Extensions */
diff --git a/src/analysis/db/certs.h b/src/analysis/db/certs.h
index 132cd7f..50c96c0 100644
--- a/src/analysis/db/certs.h
+++ b/src/analysis/db/certs.h
@@ -54,6 +54,9 @@ bool build_keys_and_ca(const char *, const char *, unsigned long, const x509_ent
/* Crée un certificat pour application. */
bool build_keys_and_request(const char *, const char *, const x509_entries *);
+/* Recharge l'identité inscrite dans une requête de signature. */
+bool load_identity_from_request(const char *, x509_entries *);
+
/* Signe un certificat pour application. */
bool sign_cert(const char *, const char *, const char *, const char *, unsigned long);
diff --git a/src/gui/dialogs/identity.c b/src/gui/dialogs/identity.c
index 625c556..eae1069 100644
--- a/src/gui/dialogs/identity.c
+++ b/src/gui/dialogs/identity.c
@@ -24,19 +24,22 @@
#include "identity.h"
+#include <malloc.h>
#include <string.h>
#include <i18n.h>
+#include "../../analysis/db/auth.h"
#include "../../analysis/db/certs.h"
+#include "../../common/extstr.h"
#include "../../core/logs.h"
/* Applique la nouvelle définition d'identité. */
-static void update_identity(GtkButton *button, GtkBuilder *);
+static void update_identity(GtkButton *, GtkBuilder *);
@@ -57,8 +60,11 @@ GtkWidget *create_identity_dialog(GtkWindow *parent, GtkBuilder **outb)
{
GtkWidget *result; /* Fenêtre à renvoyer */
GtkBuilder *builder; /* Constructeur utilisé */
- x509_entries entries; /* Eléments identitaires */
+ char *username; /* Nom par défaut */
GtkEntry *entry; /* Zone de saisie à initialiser*/
+ char *filename; /* Fichier devant être présent */
+ x509_entries identity; /* Eléments identitaires */
+ bool status; /* Bilan d'un chargement */
builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/identity.ui");
*outb = builder;
@@ -67,47 +73,64 @@ GtkWidget *create_identity_dialog(GtkWindow *parent, GtkBuilder **outb)
gtk_window_set_transient_for(GTK_WINDOW(result), parent);
- /* Mise à jour de l'interface */
+ username = get_default_username();
- memset(&entries, 0, sizeof(entries));
- //load_identity(true, &entries);
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "cn"));
+ gtk_entry_set_placeholder_text(entry, username);
- if (entries.country != NULL)
- {
- entry = GTK_ENTRY(gtk_builder_get_object(builder, "c"));
- gtk_entry_set_text(entry, entries.country);
- }
+ free(username);
- if (entries.state != NULL)
- {
- entry = GTK_ENTRY(gtk_builder_get_object(builder, "st"));
- gtk_entry_set_text(entry, entries.state);
- }
+ /* Mise à jour de l'interface */
- if (entries.locality != NULL)
- {
- entry = GTK_ENTRY(gtk_builder_get_object(builder, "l"));
- gtk_entry_set_text(entry, entries.locality);
- }
+ filename = get_db_working_directory("clients", NULL, NULL, NULL);
+ filename = stradd(filename, "client-csr.pem");
- if (entries.organisation != NULL)
- {
- entry = GTK_ENTRY(gtk_builder_get_object(builder, "o"));
- gtk_entry_set_text(entry, entries.organisation);
- }
+ status = load_identity_from_request(filename, &identity);
- if (entries.organisational_unit != NULL)
- {
- entry = GTK_ENTRY(gtk_builder_get_object(builder, "ou"));
- gtk_entry_set_text(entry, entries.organisational_unit);
- }
+ free(filename);
- if (entries.country != NULL)
+ if (status)
{
- 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);
+ if (identity.country != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "c"));
+ gtk_entry_set_text(entry, identity.country);
+ }
+
+ if (identity.state != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "st"));
+ gtk_entry_set_text(entry, identity.state);
+ }
+
+ if (identity.locality != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "l"));
+ gtk_entry_set_text(entry, identity.locality);
+ }
+
+ if (identity.organisation != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "o"));
+ gtk_entry_set_text(entry, identity.organisation);
+ }
+
+ if (identity.organisational_unit != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "ou"));
+ gtk_entry_set_text(entry, identity.organisational_unit);
+ }
+
+ if (identity.common_name != NULL)
+ {
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "cn"));
+ gtk_entry_set_text(entry, identity.common_name);
+
+ gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
+
+ }
+
+ free_x509_entries(&identity);
}
@@ -141,7 +164,7 @@ 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 */
+ x509_entries identity; /* Nouvelle identité à pousser */
bool status; /* Bilan de la mise à jour */
/* Récupération des éléments */
@@ -149,42 +172,42 @@ static void update_identity(GtkButton *button, GtkBuilder *builder)
entry = GTK_ENTRY(gtk_builder_get_object(builder, "c"));
data = gtk_entry_get_text(entry);
- entries.country = (strlen(data) > 0 ? strdup(data) : NULL);
+ identity.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);
+ identity.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);
+ identity.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);
+ identity.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);
+ identity.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);
+ identity.common_name = (strlen(data) > 0 ? strdup(data) : NULL);
/* Application de la nouvelle définition */
status = false;//register_standalone_certs(&entries);
- free_x509_entries(&entries);
+ free_x509_entries(&identity);
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..."));
+ log_simple_message(LMT_ERROR, _("Failure while reloading the new identity..."));
}
diff --git a/src/gui/dialogs/identity.ui b/src/gui/dialogs/identity.ui
index 25d398f..413d7f6 100644
--- a/src/gui/dialogs/identity.ui
+++ b/src/gui/dialogs/identity.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.21.0 -->
+<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkDialog" id="window">
@@ -8,8 +8,12 @@
<property name="title" translatable="yes">Identity</property>
<property name="modal">True</property>
<property name="window_position">center-on-parent</property>
- <property name="default_width">515</property>
+ <property name="default_width">520</property>
+ <property name="default_height">550</property>
<property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="can_focus">False</property>
@@ -78,7 +82,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">1</property>
+ <property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
@@ -87,9 +91,7 @@
<property name="width_request">500</property>
<property name="visible">True</property>
<property name="can_focus">False</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="label" translatable="yes">All the following information is used to create your authentication certifcates. These certificates grant you access to database servers and identify each analysis change.</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
<property name="xalign">0</property>
@@ -109,7 +111,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">2</property>
+ <property name="top_attach">3</property>
</packing>
</child>
<child>
@@ -122,7 +124,7 @@
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">2</property>
+ <property name="top_attach">3</property>
</packing>
</child>
<child>
@@ -134,7 +136,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">3</property>
+ <property name="top_attach">4</property>
<property name="width">2</property>
</packing>
</child>
@@ -147,7 +149,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">4</property>
+ <property name="top_attach">5</property>
</packing>
</child>
<child>
@@ -157,7 +159,7 @@
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">4</property>
+ <property name="top_attach">5</property>
</packing>
</child>
<child>
@@ -167,7 +169,7 @@
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">5</property>
+ <property name="top_attach">6</property>
</packing>
</child>
<child>
@@ -179,7 +181,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">5</property>
+ <property name="top_attach">6</property>
</packing>
</child>
<child>
@@ -191,7 +193,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">6</property>
+ <property name="top_attach">7</property>
<property name="width">2</property>
</packing>
</child>
@@ -204,7 +206,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">7</property>
+ <property name="top_attach">8</property>
</packing>
</child>
<child>
@@ -214,7 +216,7 @@
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">7</property>
+ <property name="top_attach">8</property>
</packing>
</child>
<child>
@@ -224,7 +226,7 @@
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">8</property>
+ <property name="top_attach">9</property>
</packing>
</child>
<child>
@@ -236,7 +238,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">8</property>
+ <property name="top_attach">9</property>
</packing>
</child>
<child>
@@ -248,7 +250,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">9</property>
+ <property name="top_attach">10</property>
</packing>
</child>
<child>
@@ -258,7 +260,81 @@
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">9</property>
+ <property name="top_attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Updating this information drives to new signing requests! Please contact the administrators of all the remote servers to update your accesses.
+
+The authorization for the internal server is updated automatically.</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Warning</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator" id="separator2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">11</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Certificate validity period (in seconds):</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">12</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="placeholder_text" translatable="yes">94608000</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">12</property>
</packing>
</child>
</object>
@@ -274,8 +350,5 @@
<action-widget response="-6">button1</action-widget>
<action-widget response="-10">button2</action-widget>
</action-widgets>
- <child>
- <placeholder/>
- </child>
</object>
</interface>