From: pcarana Date: Wed, 6 Feb 2019 22:54:41 +0000 (-0600) Subject: Implement cert's subject validation X-Git-Tag: v0.0.2~97 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=557fff65d2321710ca6a58f1db0da934b0943fad;p=thirdparty%2FFORT-validator.git Implement cert's subject validation --- diff --git a/src/object/certificate.c b/src/object/certificate.c index c4601920..50d0eafb 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -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; diff --git a/src/state.c b/src/state.c index c8f559e2..ccb7c509 100644 --- a/src/state.c +++ b/src/state.c @@ -1,13 +1,15 @@ #include "state.h" -#include #include +#include +#include #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; +} diff --git a/src/state.h b/src/state.h index 142d3abc..4e3b1506 100644 --- a/src/state.h +++ b/src/state.h @@ -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_ */