diff options
Diffstat (limited to 'src/analysis/db/certs.c')
-rw-r--r-- | src/analysis/db/certs.c | 317 |
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; } |