From b3000495c05ff40d848f6357974cd4d5294a66c2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 24 May 2021 13:28:47 +0200
Subject: Handle errors with more care when creating certificates.

---
 src/analysis/db/certs.c    | 96 ++++++++++++++++++++++++++++------------------
 tests/analysis/db/certs.py |  4 +-
 2 files changed, 60 insertions(+), 40 deletions(-)

diff --git a/src/analysis/db/certs.c b/src/analysis/db/certs.c
index dabc127..11d12fd 100644
--- a/src/analysis/db/certs.c
+++ b/src/analysis/db/certs.c
@@ -255,6 +255,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 +264,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 +355,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 +376,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 +394,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 +467,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 +477,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 +543,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 +556,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 +577,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 +595,29 @@ 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:
-
-    EVP_PKEY_free(pk);
-
-    return false;
-
  asign_failed:
 
     EVP_PKEY_free(pk);
 
  pk_failed:
-
-    RSA_free(rsa);
-
  rsa_failed:
 
-    return false;
+    return result;
 
 }
 
diff --git a/tests/analysis/db/certs.py b/tests/analysis/db/certs.py
index ead768e..dcf7d71 100644
--- a/tests/analysis/db/certs.py
+++ b/tests/analysis/db/certs.py
@@ -58,7 +58,7 @@ class TestRestrictedContent(ChrysalideTestCase):
 
         }
 
-        ret = certs.make_ca(self._tmppath, 'ca', 3650 * 24 * 60 * 60, identity)
+        ret = certs.build_keys_and_ca(self._tmppath, 'ca', 3650 * 24 * 60 * 60, identity)
         self.assertTrue(ret)
 
         cmd = 'openssl x509 -in %s/ca-cert.pem -subject -noout' % self._tmppath
@@ -85,7 +85,7 @@ class TestRestrictedContent(ChrysalideTestCase):
 
         }
 
-        ret = certs.make_request(self._tmppath, 'server', identity);
+        ret = certs.build_keys_and_request(self._tmppath, 'server', identity);
         self.assertTrue(ret)
 
 
-- 
cgit v0.11.2-87-g4458