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)
{
/*
* 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;
#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.
* 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;
BN_free(*serial);
}
+static void
+subject_cleanup(char **subject)
+{
+ free(*subject);
+}
+
void
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++;
}
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
*/
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;
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;
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;
+}