]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Implement cert's subject validation
authorpcarana <pc.moreno2099@gmail.com>
Wed, 6 Feb 2019 22:54:41 +0000 (16:54 -0600)
committerpcarana <pc.moreno2099@gmail.com>
Wed, 6 Feb 2019 22:54:41 +0000 (16:54 -0600)
src/object/certificate.c
src/state.c
src/state.h

index c46019206a32cbef5368485a50fbcb9700c998d7..50d0eafb36e42812d751ce096e38e3a0b925035f 100644 (file)
@@ -171,6 +171,37 @@ validate_name(X509_NAME *name, char *what)
        return 0;
 }
 
+static int
+validate_subject(X509_NAME *name, char *what)
+{
+       struct validation *state;
+       char *subject;
+       int error, sub_len;
+
+       error = validate_name(name, what);
+       if (error)
+               return error;
+
+       state = state_retrieve();
+       if (state == NULL)
+               return -EINVAL;
+
+       sub_len = X509_NAME_get_text_by_NID(name, NID_commonName, NULL, 0);
+       subject = calloc(sub_len + 1, 1);
+       if (subject == NULL) {
+               pr_err("Out of memory.");
+               return -ENOMEM;
+       }
+
+       X509_NAME_get_text_by_NID(name, NID_commonName, subject, sub_len + 1);
+
+       error = validation_store_subject(state, subject);
+       if (error)
+               free(subject);
+
+       return error;
+}
+
 static int
 validate_spki(const unsigned char *cert_spk, int cert_spk_len)
 {
@@ -342,12 +373,10 @@ certificate_validate_rfc6487(X509 *cert, bool is_root)
        /*
         * rfc6487#section-4.5
         *
-        * TODO (field) "Each distinct subordinate CA and
-        * EE certified by the issuer MUST be identified using a subject name
-        * that is unique per issuer.  In this context, "distinct" is defined as
-        * an entity and a given public key."
+        * "An issuer SHOULD use a different subject name if the subject's
+        * key pair has changed" (it's a SHOULD, so [for now] avoid validation)
         */
-       error = validate_name(X509_get_subject_name(cert), "subject");
+       error = validate_subject(X509_get_subject_name(cert), "subject");
        if (error)
                return error;
 
index c8f559e26ae21422867016f3d8348cc6df3ad043..ccb7c5094499c81d69078d1cb7c1bdabb969ec6a 100644 (file)
@@ -1,13 +1,15 @@
 #include "state.h"
 
-#include <errno.h>
 #include <sys/queue.h>
+#include <errno.h>
+#include <string.h>
 #include "array_list.h"
 #include "log.h"
 #include "thread_var.h"
 #include "object/certificate.h"
 
 ARRAY_LIST(serial_numbers, BIGNUM *)
+ARRAY_LIST(subjects, char *)
 
 /**
  * Cached certificate data.
@@ -21,6 +23,7 @@ struct certificate {
         * don't have many children, and I'm running out of time.
         */
        struct serial_numbers serials;
+       struct subjects subjects;
 
        /** Used by certstack. Points to the next stacked certificate. */
        SLIST_ENTRY(certificate) next;
@@ -146,6 +149,12 @@ serial_cleanup(BIGNUM **serial)
        BN_free(*serial);
 }
 
+static void
+subject_cleanup(char **subject)
+{
+       free(*subject);
+}
+
 void
 validation_destroy(struct validation *state)
 {
@@ -165,6 +174,7 @@ validation_destroy(struct validation *state)
                SLIST_REMOVE_HEAD(&state->certs, next);
                resources_destroy(cert->resources);
                serial_numbers_cleanup(&cert->serials, serial_cleanup);
+               subjects_cleanup(&cert->subjects, subject_cleanup);
                free(cert);
                c++;
        }
@@ -230,15 +240,18 @@ validation_push_cert(struct validation *state, struct rpki_uri const *cert_uri,
        error = serial_numbers_init(&cert->serials);
        if (error)
                goto end2;
+       error = subjects_init(&cert->subjects);
+       if (error)
+               goto end3;
        cert->resources = resources_create();
        if (cert->resources == NULL) {
                error = pr_enomem();
-               goto end3;
+               goto end4;
        }
 
        error = certificate_get_resources(x509, cert->resources);
        if (error)
-               goto end4;
+               goto end5;
 
        /*
         * rfc7730#section-2.2
@@ -249,21 +262,22 @@ validation_push_cert(struct validation *state, struct rpki_uri const *cert_uri,
         */
        if (is_ta && resources_empty(cert->resources)) {
                error = pr_err("Trust Anchor certificate does not define any number resources.");
-               goto end4;
+               goto end5;
        }
 
        ok = sk_X509_push(state->trusted, x509);
        if (ok <= 0) {
                error = crypto_err(
                    "Couldn't add certificate to trusted stack: %d", ok);
-               goto end4;
+               goto end5;
        }
 
        SLIST_INSERT_HEAD(&state->certs, cert, next);
 
        return 0;
 
-end4:  resources_destroy(cert->resources);
+end5:  resources_destroy(cert->resources);
+end4:  subjects_cleanup(&cert->subjects, subject_cleanup);
 end3:  serial_numbers_cleanup(&cert->serials, serial_cleanup);
 end2:  free(cert);
 end1:  return error;
@@ -283,6 +297,7 @@ validation_pop_cert(struct validation *state)
        SLIST_REMOVE_HEAD(&state->certs, next);
        resources_destroy(cert->resources);
        serial_numbers_cleanup(&cert->serials, serial_cleanup);
+       subjects_cleanup(&cert->subjects, subject_cleanup);
        free(cert);
 
        return 0;
@@ -334,3 +349,30 @@ validation_store_serial_number(struct validation *state, BIGNUM *number)
 
        return error;
 }
+
+int
+validation_store_subject(struct validation *state, char *subject)
+{
+       struct certificate *cert;
+       char **cursor;
+       char *duplicate;
+       int error;
+
+       cert = SLIST_FIRST(&state->certs);
+       if (cert == NULL)
+               return 0; /* The TA lacks siblings, so subject is unique. */
+
+       ARRAYLIST_FOREACH(&cert->subjects, cursor)
+               if (strcmp(*cursor, subject) == 0)
+                       return pr_err("Subject name is not unique.");
+
+       duplicate = strdup(subject);
+       if (duplicate == NULL)
+               return pr_err("Could not duplicate a String");
+
+       error = subjects_add(&cert->subjects, &duplicate);
+       if (error)
+               free(duplicate);
+
+       return error;
+}
index 142d3abc1a65584504f09d20902b623d637a1425..4e3b150612876840ee81b354ea5f77a6398c50a1 100644 (file)
@@ -33,5 +33,6 @@ struct rpki_uri const *validation_peek_cert_uri(struct validation *);
 struct resources *validation_peek_resource(struct validation *);
 
 int validation_store_serial_number(struct validation *, BIGNUM *);
+int validation_store_subject(struct validation *, char *);
 
 #endif /* SRC_STATE_H_ */