diff options
author | Rob Austein <sra@hactrn.net> | 2012-01-26 00:31:13 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2012-01-26 00:31:13 +0000 |
commit | 5bf7d2750c906084fe2b61132f7f4325d101eb9c (patch) | |
tree | 54e2a4ce2282c6bb96f3eea42dcd5d9fd9f2ce95 /rcynic | |
parent | 37a20077f47e0991e445905d731fbd58c53747c1 (diff) |
Conformance tests: tighter checking of AIA and SIA extension values.
svn path=/trunk/; revision=4265
Diffstat (limited to 'rcynic')
-rw-r--r-- | rcynic/rcynic.c | 151 |
1 files changed, 90 insertions, 61 deletions
diff --git a/rcynic/rcynic.c b/rcynic/rcynic.c index 4a37c6a9..0ff3ae40 100644 --- a/rcynic/rcynic.c +++ b/rcynic/rcynic.c @@ -205,6 +205,8 @@ static const struct { #define MIB_COUNTERS \ MIB_COUNTERS_FROM_OPENSSL \ QB(aia_doesnt_match_issuer, "AIA doesn't match issuer") \ + QB(aia_extension_missing, "AIA extension missing") \ + QB(aia_extension_forbidden, "AIA extension forbidden") \ QB(aia_uri_missing, "AIA URI missing") \ QB(aki_extension_issuer_mismatch, "AKI extension issuer mismatch") \ QB(aki_extension_missing, "AKI extension missing") \ @@ -228,7 +230,9 @@ static const struct { QB(crldp_doesnt_match_issuer_sia, "CRLDP doesn't match issuer's SIA") \ QB(crldp_uri_missing, "CRLDP URI missing") \ QB(disallowed_x509v3_extension, "Disallowed X.509v3 extension") \ - QB(inappropriate_eku_extension, "Inappropriate EKU extension") \ + QB(inappropriate_eku_extension, "Inappropriate EKU extension") \ + QB(malformed_aia_extension, "Malformed AIA extension") \ + QB(malformed_sia_extension, "Malformed SIA extension") \ QB(malformed_basic_constraints, "Malformed basicConstraints") \ QB(malformed_certificate_policy, "Malformed certificate policy") \ QB(malformed_trust_anchor, "Malformed trust anchor") \ @@ -245,7 +249,7 @@ static const struct { QB(nonconformant_asn1_time_value, "Nonconformant ASN.1 time value") \ QB(nonconformant_public_key_algorithm,"Nonconformant public key algorithm")\ QB(nonconformant_signature_algorithm, "Nonconformant signature algorithm")\ - QB(nonconformant_digest_algorithm, "Nonconformant digest algorithm") \ + QB(nonconformant_digest_algorithm, "Nonconformant digest algorithm") \ QB(object_rejected, "Object rejected") \ QB(roa_contains_bad_afi_value, "ROA contains bad AFI value") \ QB(roa_resource_not_in_ee, "ROA resource not in EE") \ @@ -253,6 +257,7 @@ static const struct { QB(rsync_transfer_failed, "rsync transfer failed") \ QB(rsync_transfer_timed_out, "rsync transfer timed out") \ QB(sia_cadirectory_uri_missing, "SIA caDirectory URI missing") \ + QB(sia_extension_missing, "SIA extension missing") \ QB(sia_manifest_uri_missing, "SIA manifest URI missing") \ QB(ski_extension_missing, "SKI extension missing") \ QB(trust_anchor_key_mismatch, "Trust anchor key mismatch") \ @@ -275,6 +280,7 @@ static const struct { QW(unknown_object_type_skipped, "Unknown object type skipped") \ QW(uri_too_long, "URI too long") \ QG(current_cert_recheck, "Certificate rechecked") \ + QG(non_rsync_uri_in_extension, "Non-rsync URI in extension") \ QG(object_accepted, "Object accepted") \ QG(rsync_transfer_succeeded, "rsync transfer succeeded") \ QG(validation_ok, "OK") @@ -379,7 +385,7 @@ DECLARE_STACK_OF(validation_status_t) typedef struct certinfo { int ca, ta; object_generation_t generation; - uri_t uri, sia, aia, crldp, manifest; + uri_t uri, sia, aia, crldp, manifest, signedobject; } certinfo_t; typedef struct rcynic_ctx rcynic_ctx_t; @@ -551,6 +557,10 @@ static const unsigned char id_ad_caRepository[] = static const unsigned char id_ad_rpkiManifest[] = {0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x30, 0xa}; +/** 1.3.6.1.5.5.7.48.11 */ +static const unsigned char id_ad_signedObject[] = + {0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x30, 0xb}; + /** 1.2.840.113549.1.9.16.1.24 */ static const unsigned char id_ct_routeOriginAttestation[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x18}; @@ -2752,85 +2762,75 @@ static CMS_ContentInfo *read_cms(const path_t *filename, hashbuf_t *hash) * Extract CRLDP data from a certificate. Stops looking after finding * the first rsync URI. */ -static void extract_crldp_uri(rcynic_ctx_t *rc, - const uri_t *uri, - const object_generation_t generation, - const STACK_OF(DIST_POINT) *crldp, - uri_t *result) +static int extract_crldp_uri(rcynic_ctx_t *rc, + const uri_t *uri, + const object_generation_t generation, + const STACK_OF(DIST_POINT) *crldp, + uri_t *result) { DIST_POINT *d; int i; assert(crldp); - if (sk_DIST_POINT_num(crldp) != 1) { - log_validation_status(rc, uri, malformed_crldp_extension, generation); - return; - } + if (sk_DIST_POINT_num(crldp) != 1) + goto bad; d = sk_DIST_POINT_value(crldp, 0); - if (d->reasons || d->CRLissuer || !d->distpoint || d->distpoint->type != 0) { - log_validation_status(rc, uri, malformed_crldp_extension, generation); - return; - } + if (d->reasons || d->CRLissuer || !d->distpoint || d->distpoint->type != 0) + goto bad; for (i = 0; i < sk_GENERAL_NAME_num(d->distpoint->name.fullname); i++) { GENERAL_NAME *n = sk_GENERAL_NAME_value(d->distpoint->name.fullname, i); - assert(n != NULL); - if (n->type != GEN_URI) { - log_validation_status(rc, uri, malformed_crldp_extension, generation); - return; - } + if (n == NULL || n->type != GEN_URI) + goto bad; if (!is_rsync((char *) n->d.uniformResourceIdentifier->data)) { - logmsg(rc, log_verbose, "Skipping non-rsync URI %s for %s", - (char *) n->d.uniformResourceIdentifier->data, uri->s); - continue; - } - if (sizeof(result->s) <= n->d.uniformResourceIdentifier->length) { + log_validation_status(rc, uri, non_rsync_uri_in_extension, generation); + } else if (sizeof(result->s) <= n->d.uniformResourceIdentifier->length) { log_validation_status(rc, uri, uri_too_long, generation); - continue; + } else { + strcpy(result->s, (char *) n->d.uniformResourceIdentifier->data); + return 1; } - strcpy(result->s, (char *) n->d.uniformResourceIdentifier->data); - return; } + + bad: + log_validation_status(rc, uri, malformed_crldp_extension, generation); + return 0; } /** * Extract SIA or AIA data from a certificate. */ -static void extract_access_uri(rcynic_ctx_t *rc, - const uri_t *uri, - const object_generation_t generation, - const AUTHORITY_INFO_ACCESS *xia, - const unsigned char *oid, - const int oidlen, - uri_t *result) +static int extract_access_uri(rcynic_ctx_t *rc, + const uri_t *uri, + const object_generation_t generation, + const AUTHORITY_INFO_ACCESS *xia, + const unsigned char *oid, + const int oidlen, + uri_t *result) { int i; - if (!xia) - return; + assert(xia); for (i = 0; i < sk_ACCESS_DESCRIPTION_num(xia); i++) { ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(xia, i); - assert(a != NULL); - if (a->location->type != GEN_URI) - return; + if (a == NULL || a->location->type != GEN_URI) + return 0; if (oid_cmp(a->method, oid, oidlen)) continue; if (!is_rsync((char *) a->location->d.uniformResourceIdentifier->data)) { - logmsg(rc, log_verbose, "Skipping non-rsync URI %s for %s", - a->location->d.uniformResourceIdentifier->data, uri->s); - continue; - } - if (sizeof(result->s) <= a->location->d.uniformResourceIdentifier->length) { + log_validation_status(rc, uri, non_rsync_uri_in_extension, generation); + } else if (sizeof(result->s) <= a->location->d.uniformResourceIdentifier->length) { log_validation_status(rc, uri, uri_too_long, generation); - continue; + } else { + strcpy(result->s, (char *) a->location->d.uniformResourceIdentifier->data); + return 1; } - strcpy(result->s, (char *) a->location->d.uniformResourceIdentifier->data); - return; } + return 1; } @@ -3285,21 +3285,54 @@ static int check_x509(rcynic_ctx_t *rc, if ((aia = X509_get_ext_d2i(x, NID_info_access, NULL, NULL)) != NULL) { ex_count--; - extract_access_uri(rc, uri, generation, aia, - id_ad_caIssuers, sizeof(id_ad_caIssuers), &certinfo->aia); + if (!extract_access_uri(rc, uri, generation, aia, + id_ad_caIssuers, sizeof(id_ad_caIssuers), &certinfo->aia) || + !certinfo->aia.s[0]) { + log_validation_status(rc, uri, malformed_aia_extension, generation); + goto done; + } + } + + if (certinfo->ta && aia) { + log_validation_status(rc, uri, aia_extension_forbidden, generation); + goto done; + } + + if (!certinfo->ta && !aia) { + log_validation_status(rc, uri, aia_extension_missing, generation); + goto done; } if ((sia = X509_get_ext_d2i(x, NID_sinfo_access, NULL, NULL)) != NULL) { + int got_caDirectory, got_rpkiManifest, got_signedObject; ex_count--; - extract_access_uri(rc, uri, generation, sia, - id_ad_caRepository, sizeof(id_ad_caRepository), &certinfo->sia); - extract_access_uri(rc, uri, generation, sia, - id_ad_rpkiManifest, sizeof(id_ad_rpkiManifest), &certinfo->manifest); + ok = (extract_access_uri(rc, uri, generation, sia, id_ad_caRepository, + sizeof(id_ad_caRepository), &certinfo->sia) && + extract_access_uri(rc, uri, generation, sia, id_ad_rpkiManifest, + sizeof(id_ad_rpkiManifest), &certinfo->manifest) && + extract_access_uri(rc, uri, generation, sia, id_ad_signedObject, + sizeof(id_ad_signedObject), &certinfo->signedobject)); + got_caDirectory = certinfo->sia.s[0] != '\0'; + got_rpkiManifest = certinfo->manifest.s[0] != '\0'; + got_signedObject = certinfo->signedobject.s[0] != '\0'; + ok &= sk_ACCESS_DESCRIPTION_num(sia) == got_caDirectory + got_rpkiManifest + got_signedObject; + if (certinfo->ca) + ok &= got_caDirectory && got_rpkiManifest && !got_signedObject; + else + ok &= !got_caDirectory && !got_rpkiManifest && got_signedObject; + if (!ok) { + log_validation_status(rc, uri, malformed_sia_extension, generation); + goto done; + } + } else { + log_validation_status(rc, uri, sia_extension_missing, generation); + goto done; } if ((crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL)) != NULL) { ex_count--; - extract_crldp_uri(rc, uri, generation, crldp, &certinfo->crldp); + if (!extract_crldp_uri(rc, uri, generation, crldp, &certinfo->crldp)) + goto done; } rctx.rc = rc; @@ -3324,11 +3357,6 @@ static int check_x509(rcynic_ctx_t *rc, goto done; } - if (!certinfo->ta && !certinfo->aia.s[0]) { - log_validation_status(rc, uri, aia_uri_missing, generation); - goto done; - } - if (!w->certinfo.ta && strcmp(w->certinfo.uri.s, certinfo->aia.s)) { log_validation_status(rc, uri, aia_doesnt_match_issuer, generation); goto done; @@ -4446,6 +4474,7 @@ static int check_ta(rcynic_ctx_t *rc, X509 *x, const uri_t *uri, } if (!check_x509(rc, wsk, uri, x, NULL, generation)) { + log_validation_status(rc, uri, object_rejected, generation); walk_ctx_stack_free(wsk); return 1; } |