aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rcynic/rcynic.c184
1 files changed, 101 insertions, 83 deletions
diff --git a/rcynic/rcynic.c b/rcynic/rcynic.c
index 64f44096..c7245f47 100644
--- a/rcynic/rcynic.c
+++ b/rcynic/rcynic.c
@@ -502,6 +502,7 @@ struct rcynic_ctx {
int allow_non_self_signed_trust_anchor, allow_object_not_in_manifest;
int max_parallel_fetches, max_retries, retry_wait_min, run_rsync;
int allow_digest_mismatch, allow_crl_digest_mismatch;
+ int allow_nonconformant_name;
unsigned max_select_time, validation_status_creation_order;
log_level_t log_level;
X509_STORE *x509_store;
@@ -2875,6 +2876,87 @@ static int check_aki(rcynic_ctx_t *rc,
/**
+ * Check whether extensions in a certificate are allowed by profile.
+ * Also returns failure in a few null-pointer cases that can't
+ * possibly conform to profile.
+ */
+static int check_allowed_extensions(const X509 *x, const int allow_eku)
+{
+ int i;
+
+ if (x == NULL || x->cert_info == NULL || x->cert_info->extensions == NULL)
+ return 0;
+
+ for (i = 0; i < sk_X509_EXTENSION_num(x->cert_info->extensions); i++) {
+ switch (OBJ_obj2nid(sk_X509_EXTENSION_value(x->cert_info->extensions,
+ i)->object)) {
+ case NID_basic_constraints:
+ case NID_subject_key_identifier:
+ case NID_authority_key_identifier:
+ case NID_key_usage:
+ case NID_crl_distribution_points:
+ case NID_info_access:
+ case NID_sinfo_access:
+ case NID_certificate_policies:
+ case NID_sbgp_ipAddrBlock:
+ case NID_sbgp_autonomousSysNum:
+ continue;
+ case NID_ext_key_usage:
+ if (allow_eku)
+ continue;
+ else
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/**
+ * Check whether a Distinguished Name conforms to the rescert profile.
+ * The profile is very restrictive: it only allows one mandatory
+ * CommonName field and one optional SerialNumber field, both of which
+ * must be of type PrintableString.
+ */
+static int check_allowed_dn(X509_NAME *dn)
+{
+ X509_NAME_ENTRY *ne;
+ ASN1_STRING *s;
+ int loc;
+
+ if (dn == NULL)
+ return 0;
+
+ switch (X509_NAME_entry_count(dn)) {
+
+ case 2:
+ if ((loc = X509_NAME_get_index_by_NID(dn, NID_serialNumber, -1)) < 0 ||
+ (ne = X509_NAME_get_entry(dn, loc)) == NULL ||
+ (s = X509_NAME_ENTRY_get_data(ne)) == NULL ||
+ ASN1_STRING_type(s) != V_ASN1_PRINTABLESTRING)
+ return 0;
+
+ /* Fall through */
+
+ case 1:
+ if ((loc = X509_NAME_get_index_by_NID(dn, NID_commonName, -1)) < 0 ||
+ (ne = X509_NAME_get_entry(dn, loc)) == NULL ||
+ (s = X509_NAME_ENTRY_get_data(ne)) == NULL ||
+ ASN1_STRING_type(s) != V_ASN1_PRINTABLESTRING)
+ return 0;
+
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+
+
+/**
* Attempt to read and check one CRL from disk.
*/
@@ -2925,6 +3007,12 @@ static X509_CRL *check_crl_1(rcynic_ctx_t *rc,
goto punt;
}
+ if (!check_allowed_dn(X509_CRL_get_issuer(crl))) {
+ log_validation_status(rc, uri, nonconformant_issuer_name, generation);
+ if (!rc->allow_nonconformant_name)
+ goto punt;
+ }
+
if ((revoked = X509_CRL_get_REVOKED(crl)) != NULL) {
for (i = sk_X509_REVOKED_num(revoked) - 1; i >= 0; --i) {
if (X509_REVOKED_get_ext_count(sk_X509_REVOKED_value(revoked, i)) > 0) {
@@ -3048,87 +3136,6 @@ static int check_crl_digest(const rcynic_ctx_t *rc,
/**
- * Check whether extensions in a certificate are allowed by profile.
- * Also returns failure in a few null-pointer cases that can't
- * possibly conform to profile.
- */
-static int check_allowed_extensions(const X509 *x, const int allow_eku)
-{
- int i;
-
- if (x == NULL || x->cert_info == NULL || x->cert_info->extensions == NULL)
- return 0;
-
- for (i = 0; i < sk_X509_EXTENSION_num(x->cert_info->extensions); i++) {
- switch (OBJ_obj2nid(sk_X509_EXTENSION_value(x->cert_info->extensions,
- i)->object)) {
- case NID_basic_constraints:
- case NID_subject_key_identifier:
- case NID_authority_key_identifier:
- case NID_key_usage:
- case NID_crl_distribution_points:
- case NID_info_access:
- case NID_sinfo_access:
- case NID_certificate_policies:
- case NID_sbgp_ipAddrBlock:
- case NID_sbgp_autonomousSysNum:
- continue;
- case NID_ext_key_usage:
- if (allow_eku)
- continue;
- else
- return 0;
- default:
- return 0;
- }
- }
-
- return 1;
-}
-
-/**
- * Check whether a Distinguished Name conforms to the rescert profile.
- * The profile is very restrictive: it only allows one mandatory
- * CommonName field and one optional SerialNumber field, both of which
- * must be of type PrintableString.
- */
-static int check_allowed_dn(X509_NAME *dn)
-{
- X509_NAME_ENTRY *ne;
- ASN1_STRING *s;
- int loc;
-
- if (dn == NULL)
- return 0;
-
- switch (X509_NAME_entry_count(dn)) {
-
- case 2:
- if ((loc = X509_NAME_get_index_by_NID(dn, NID_serialNumber, -1)) < 0 ||
- (ne = X509_NAME_get_entry(dn, loc)) == NULL ||
- (s = X509_NAME_ENTRY_get_data(ne)) == NULL ||
- ASN1_STRING_type(s) != V_ASN1_PRINTABLESTRING)
- return 0;
-
- /* Fall through */
-
- case 1:
- if ((loc = X509_NAME_get_index_by_NID(dn, NID_commonName, -1)) < 0 ||
- (ne = X509_NAME_get_entry(dn, loc)) == NULL ||
- (s = X509_NAME_ENTRY_get_data(ne)) == NULL ||
- ASN1_STRING_type(s) != V_ASN1_PRINTABLESTRING)
- return 0;
-
- return 1;
-
- default:
- return 0;
- }
-}
-
-
-
-/**
* Validation callback function for use with x509_verify_cert().
*/
static int check_x509_cb(int ok, X509_STORE_CTX *ctx)
@@ -3278,11 +3285,17 @@ static int check_x509(rcynic_ctx_t *rc,
goto done;
}
- if (!check_allowed_dn(X509_get_subject_name(x)))
+ if (!check_allowed_dn(X509_get_subject_name(x))) {
log_validation_status(rc, &certinfo->uri, nonconformant_subject_name, certinfo->generation);
+ if (!rc->allow_nonconformant_name)
+ goto done;
+ }
- if (!check_allowed_dn(X509_get_issuer_name(x)))
+ if (!check_allowed_dn(X509_get_issuer_name(x))) {
log_validation_status(rc, &certinfo->uri, nonconformant_issuer_name, certinfo->generation);
+ if (!rc->allow_nonconformant_name)
+ goto done;
+ }
if (certinfo->ta) {
@@ -4331,6 +4344,7 @@ int main(int argc, char *argv[])
rc.allow_digest_mismatch = 1;
rc.allow_crl_digest_mismatch = 1;
rc.allow_object_not_in_manifest = 1;
+ rc.allow_nonconformant_name = 1;
rc.max_parallel_fetches = 1;
rc.max_retries = 3;
rc.retry_wait_min = 30;
@@ -4504,6 +4518,10 @@ int main(int argc, char *argv[])
!configure_boolean(&rc, &rc.run_rsync, val->value))
goto done;
+ else if (!name_cmp(val->name, "allow-nonconformant-name") &&
+ !configure_boolean(&rc, &rc.allow_nonconformant_name, val->value))
+ goto done;
+
/*
* Ugly, but the easiest way to handle all these strings.
*/