summaryrefslogtreecommitdiff
path: root/src/analysis/db/certs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/db/certs.c')
-rw-r--r--src/analysis/db/certs.c317
1 files changed, 252 insertions, 65 deletions
diff --git a/src/analysis/db/certs.c b/src/analysis/db/certs.c
index dabc127..22ff397 100644
--- a/src/analysis/db/certs.c
+++ b/src/analysis/db/certs.c
@@ -39,6 +39,7 @@
#include <i18n.h>
+#include "../../common/extstr.h"
#include "../../core/logs.h"
@@ -52,6 +53,9 @@ static bool add_extension_to_req(STACK_OF(X509_EXTENSION) *, int, /*const */char
/* Crée une paire de clefs RSA. */
static RSA *generate_rsa_key(unsigned int, unsigned long);
+/* Recharge l'identité inscrite dans un élément X509. */
+static bool load_identity_from_x509(/*const */X509_NAME *, x509_entries *);
+
/******************************************************************************
@@ -97,6 +101,70 @@ bool are_x509_entries_empty(const x509_entries *entries)
/******************************************************************************
* *
+* Paramètres : entries = éléments d'identité à convertir. *
+* *
+* Description : Traduit en chaîne de caractères une définition d'identité. *
+* *
+* Retour : Chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *translate_x509_entries(const x509_entries *entries)
+{
+ char *result; /* Description à retourner */
+
+ result = NULL;
+
+ if (entries->country != NULL)
+ {
+ result = stradd(result, "C=");
+ result = stradd(result, entries->country);
+ }
+
+ if (entries->state != NULL)
+ {
+ if (result != NULL) result = stradd(result, "/");
+ result = stradd(result, "ST=");
+ result = stradd(result, entries->state);
+ }
+
+ if (entries->locality != NULL)
+ {
+ if (result != NULL) result = stradd(result, "/");
+ result = stradd(result, "L=");
+ result = stradd(result, entries->locality);
+ }
+
+ if (entries->organisation != NULL)
+ {
+ if (result != NULL) result = stradd(result, "/");
+ result = stradd(result, "O=");
+ result = stradd(result, entries->organisation);
+ }
+
+ if (entries->organisational_unit != NULL)
+ {
+ if (result != NULL) result = stradd(result, "/");
+ result = stradd(result, "OU=");
+ result = stradd(result, entries->organisational_unit);
+ }
+
+ if (entries->common_name != NULL)
+ {
+ if (result != NULL) result = stradd(result, "/");
+ result = stradd(result, "CN=");
+ result = stradd(result, entries->common_name);
+ }
+
+ 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é. *
@@ -255,6 +323,7 @@ static RSA *generate_rsa_key(unsigned int bits, unsigned long e)
bool build_keys_and_ca(const char *dir, const char *label, unsigned long valid, const x509_entries *entries)
{
+ bool result; /* Bilan à retourner */
RSA *rsa; /* Clef RSA pour le certificat */
EVP_PKEY *pk; /* Enveloppe pour clef publique*/
int ret; /* Bilan d'un appel */
@@ -263,20 +332,30 @@ bool build_keys_and_ca(const char *dir, const char *label, unsigned long valid,
char *filename; /* Chemin d'accès à un fichier */
FILE *stream; /* Flux ouvert en écriture */
+ result = false;
+
rsa = generate_rsa_key(4096, 17);
if (rsa == NULL) goto rsa_failed;
pk = EVP_PKEY_new();
- if (pk == NULL) goto pk_failed;
+ if (pk == NULL)
+ {
+ RSA_free(rsa);
+ goto pk_failed;
+ }
ret = EVP_PKEY_assign_RSA(pk, rsa);
- if (ret != 1) goto asign_failed;
+ if (ret != 1)
+ {
+ RSA_free(rsa);
+ goto asign_failed;
+ }
x509 = X509_new();
if (x509 == NULL) goto x509_failed;
ret = X509_set_pubkey(x509, pk);
- if (ret != 1) goto ca_failed;
+ if (ret != 1) goto ca_asign_failed;
ret = X509_set_version(x509, 2);
if (ret != 1) goto ca_failed;
@@ -344,7 +423,11 @@ bool build_keys_and_ca(const char *dir, const char *label, unsigned long valid,
asprintf(&filename, "%s%c%s-key.pem", dir, G_DIR_SEPARATOR, label);
stream = fopen(filename, "wb");
- if (stream == NULL) goto ca_failed;
+ if (stream == NULL)
+ {
+ free(filename);
+ goto ca_failed;
+ }
ret = PEM_write_PrivateKey(stream, pk, NULL, NULL, 0, NULL, NULL);
@@ -361,7 +444,11 @@ bool build_keys_and_ca(const char *dir, const char *label, unsigned long valid,
asprintf(&filename, "%s%c%s-cert.pem", dir, G_DIR_SEPARATOR, label);
stream = fopen(filename, "wb");
- if (stream == NULL) goto ca_failed;
+ if (stream == NULL)
+ {
+ free(filename);
+ goto ca_failed;
+ }
ret = PEM_write_X509(stream, x509);
@@ -375,34 +462,24 @@ bool build_keys_and_ca(const char *dir, const char *label, unsigned long valid,
if (ret != 1)
goto ca_failed;
- /* Libérations finales */
-
- X509_free(x509);
- EVP_PKEY_free(pk);
+ result = true;
- return true;
+ /* Libérations finales */
ca_failed:
+ ca_asign_failed:
X509_free(x509);
x509_failed:
-
- EVP_PKEY_free(pk);
-
- return false;
-
asign_failed:
EVP_PKEY_free(pk);
pk_failed:
-
- RSA_free(rsa);
-
rsa_failed:
- return false;
+ return result;
}
@@ -458,6 +535,7 @@ static bool add_extension_to_req(STACK_OF(X509_EXTENSION) *sk, int nid, /*const
bool build_keys_and_request(const char *dir, const char *label, const x509_entries *entries)
{
+ bool result; /* Bilan à retourner */
RSA *rsa; /* Clef RSA pour le certificat */
EVP_PKEY *pk; /* Enveloppe pour clef publique*/
int ret; /* Bilan d'un appel */
@@ -467,20 +545,30 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri
char *filename; /* Chemin d'accès à un fichier */
FILE *stream; /* Flux ouvert en écriture */
+ result = false;
+
rsa = generate_rsa_key(2048, 17);
if (rsa == NULL) goto rsa_failed;
pk = EVP_PKEY_new();
- if (pk == NULL) goto pk_failed;
+ if (pk == NULL)
+ {
+ RSA_free(rsa);
+ goto pk_failed;
+ }
ret = EVP_PKEY_assign_RSA(pk, rsa);
- if (ret != 1) goto asign_failed;
+ if (ret != 1)
+ {
+ RSA_free(rsa);
+ goto asign_failed;
+ }
x509 = X509_REQ_new();
if (x509 == NULL) goto x509_failed;
ret = X509_REQ_set_pubkey(x509, pk);
- if (ret != 1) goto asign_failed;
+ if (ret != 1) goto req_asign_failed;
/* Etablissement d'une identité */
@@ -523,8 +611,6 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri
ret = X509_REQ_add_extensions(x509, exts);
if (ret != 1) goto exts_failed;
- sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
-
/* Signature */
ret = X509_REQ_sign(x509, pk, EVP_sha256());
@@ -538,7 +624,11 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri
asprintf(&filename, "%s%c%s-key.pem", dir, G_DIR_SEPARATOR, label);
stream = fopen(filename, "wb");
- if (stream == NULL) goto req_failed_2;
+ if (stream == NULL)
+ {
+ free(filename);
+ goto req_failed_2;
+ }
ret = PEM_write_PrivateKey(stream, pk, NULL, NULL, 0, NULL, NULL);
@@ -555,7 +645,11 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri
asprintf(&filename, "%s%c%s-csr.pem", dir, G_DIR_SEPARATOR, label);
stream = fopen(filename, "wb");
- if (stream == NULL) goto req_failed_2;
+ if (stream == NULL)
+ {
+ free(filename);
+ goto req_failed_2;
+ }
ret = PEM_write_X509_REQ(stream, x509);
@@ -569,35 +663,87 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri
if (ret != 1)
goto req_failed_2;
- return true;
+ result = true;
- req_failed_2:
+ /* Libérations finales */
+ req_failed_2:
exts_failed:
- sk_X509_EXTENSION_free(exts);
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
req_failed:
+ req_asign_failed:
X509_REQ_free(x509);
x509_failed:
+ asign_failed:
EVP_PKEY_free(pk);
- return false;
+ pk_failed:
+ rsa_failed:
- asign_failed:
+ return result;
- EVP_PKEY_free(pk);
+}
- pk_failed:
- RSA_free(rsa);
+/******************************************************************************
+* *
+* Paramètres : subject = sujet d'un élément X509. *
+* entries = éléments de l'identité constituée. [OUT] *
+* *
+* Description : Recharge l'identité inscrite dans un élément X509. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool load_identity_from_x509(/*const */X509_NAME *subject, x509_entries *entries)
+{
+ bool result; /* Bilan à retourner */
+ int length; /* Taille du champ visé */
- rsa_failed:
+ result = false;
- return false;
+#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); \
+ if (length == -1) \
+ goto copy_failed; \
+ } \
+ } \
+ 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
+
+ result = true;
+
+ copy_failed:
+
+ return result;
}
@@ -621,7 +767,6 @@ bool load_identity_from_request(const char *csr, x509_entries *entries)
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;
@@ -646,38 +791,65 @@ bool load_identity_from_request(const char *csr, x509_entries *entries)
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)
+ result = load_identity_from_x509(subject, entries);
- GET_NAME_ENTRY(NID_countryName, country);
+ X509_REQ_free(req);
- GET_NAME_ENTRY(NID_stateOrProvinceName, state);
+ csr_read_failed:
- GET_NAME_ENTRY(NID_localityName, locality);
+ return result;
- GET_NAME_ENTRY(NID_organizationName, organisation);
+}
- GET_NAME_ENTRY(NID_organizationalUnitName, organisational_unit);
- GET_NAME_ENTRY(NID_commonName, common_name);
+/******************************************************************************
+* *
+* Paramètres : crt = fichier contenant un certificat signé. *
+* entries = éléments de l'identité constituée. [OUT] *
+* *
+* Description : Recharge l'identité inscrite dans un certificat signé. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
-#undef GET_NAME_ENTRY
+bool load_identity_from_cert(const char *crt, x509_entries *entries)
+{
+ bool result; /* Bilan à retourner */
+ FILE *stream; /* Flux ouvert en lecture */
+ X509 *x; /* Certificat X509 signé */
+ X509_NAME *subject; /* Sujet du certificat */
- X509_REQ_free(req);
+ result = false;
- result = true;
+ memset(entries, 0, sizeof(*entries));
- csr_read_failed:
+ /* Chargement de la requête */
+
+ stream = fopen(crt, "rb");
+ if (stream == NULL) goto crt_read_failed;
+
+ x = PEM_read_X509(stream, NULL, NULL, NULL);
+
+ fclose(stream);
+
+ if (x == NULL)
+ {
+ log_variadic_message(LMT_ERROR, _("Unable to read the signed certificate from '%s'"), crt);
+ goto crt_read_failed;
+ }
+
+ /* Recherche des éléments */
+
+ subject = X509_get_subject_name(x);
+
+ result = load_identity_from_x509(subject, entries);
+
+ X509_free(x);
+
+ crt_read_failed:
return result;
@@ -714,7 +886,12 @@ bool sign_cert(const char *csr, const char *cacert, const char *cakey, const cha
/* Chargement de la requête */
stream = fopen(csr, "rb");
- if (stream == NULL) goto csr_read_failed;
+
+ if (stream == NULL)
+ {
+ log_variadic_message(LMT_ERROR, _("Unable to open the certificate signing request file '%s'"), csr);
+ goto csr_read_failed;
+ }
req = PEM_read_X509_REQ(stream, NULL, NULL, NULL);
@@ -722,7 +899,7 @@ bool sign_cert(const char *csr, const char *cacert, const char *cakey, const cha
if (req == NULL)
{
- log_variadic_message(LMT_ERROR, _("Unable to read the certificate signing request from '%s'"), cert);
+ log_variadic_message(LMT_ERROR, _("Unable to read the certificate signing request from '%s'"), csr);
goto csr_read_failed;
}
@@ -735,7 +912,12 @@ bool sign_cert(const char *csr, const char *cacert, const char *cakey, const cha
/* Chargement des éléments de l'autorité */
stream = fopen(cacert, "rb");
- if (stream == NULL) goto cacert_read_failed;
+
+ if (stream == NULL)
+ {
+ log_variadic_message(LMT_ERROR, _("Unable to open the CA certificate file '%s'"), cacert);
+ goto cacert_read_failed;
+ }
ca_cert = PEM_read_X509(stream, NULL, NULL, NULL);
@@ -743,12 +925,17 @@ bool sign_cert(const char *csr, const char *cacert, const char *cakey, const cha
if (ca_cert == NULL)
{
- log_variadic_message(LMT_ERROR, _("Unable to read the certificate from '%s'"), cert);
+ log_variadic_message(LMT_ERROR, _("Unable to read the CA certificate from '%s'"), cacert);
goto cacert_read_failed;
}
stream = fopen(cakey, "rb");
- if (stream == NULL) goto cakey_read_failed;
+
+ if (stream == NULL)
+ {
+ log_variadic_message(LMT_ERROR, _("Unable to open the CA private key file '%s'"), cakey);
+ goto cakey_read_failed;
+ }
ca_pk = PEM_read_PrivateKey(stream, NULL, NULL, NULL);
@@ -756,7 +943,7 @@ bool sign_cert(const char *csr, const char *cacert, const char *cakey, const cha
if (ca_pk == NULL)
{
- log_variadic_message(LMT_ERROR, _("Unable to read the CA private key from %s"), cakey);
+ log_variadic_message(LMT_ERROR, _("Unable to read the CA private key from '%s'"), cakey);
goto cakey_read_failed;
}