From 912378bc36eb35465d89555bc25734e35b1f0843 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 21 Jul 2021 00:49:52 +0200 Subject: Extract identities from signed certificates. --- src/analysis/db/certs.c | 198 ++++++++++++++++++++++++++++++++++++++++++------ src/analysis/db/certs.h | 6 ++ 2 files changed, 181 insertions(+), 23 deletions(-) diff --git a/src/analysis/db/certs.c b/src/analysis/db/certs.c index 148abf2..22ff397 100644 --- a/src/analysis/db/certs.c +++ b/src/analysis/db/certs.c @@ -39,6 +39,7 @@ #include +#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é. * @@ -624,6 +692,64 @@ bool build_keys_and_request(const char *dir, const char *label, const x509_entri /****************************************************************************** * * +* 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é */ + + result = 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; + +} + + +/****************************************************************************** +* * * Paramètres : csr = fichier contenant le certificat à signer. * * entries = éléments de l'identité constituée. [OUT] * * * @@ -641,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; @@ -666,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; diff --git a/src/analysis/db/certs.h b/src/analysis/db/certs.h index 51a2e34..359b3d3 100644 --- a/src/analysis/db/certs.h +++ b/src/analysis/db/certs.h @@ -45,6 +45,9 @@ typedef struct _x509_entries /* Indique si une définition existe dans l'identité. */ bool are_x509_entries_empty(const x509_entries *); +/* Traduit en chaîne de caractères une définition d'identité. */ +char *translate_x509_entries(const x509_entries *); + /* Libère la mémoire occupée par une définition d'identité. */ void free_x509_entries(x509_entries *); @@ -57,6 +60,9 @@ 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 *); +/* Recharge l'identité inscrite dans un certificat signé. */ +bool load_identity_from_cert(const char *, x509_entries *); + /* Signe un certificat pour application. */ bool sign_cert(const char *, const char *, const char *, const char *, unsigned long); -- cgit v0.11.2-87-g4458