diff --git a/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c b/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c index 7c9430d3c6..28f21a6c2d 100755 --- a/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c +++ b/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c @@ -168,6 +168,9 @@ pkix_NameConstraintsChecker_Check( PKIX_PL_CertNameConstraints *mergedNameConstraints = NULL; PKIX_Boolean selfIssued = PKIX_FALSE; PKIX_Boolean lastCert = PKIX_FALSE; + PKIX_Boolean treatCommonNameAsDNSName = PKIX_FALSE; + PKIX_List *extKeyUsageList = NULL; + PKIX_PL_OID *serverAuthOID = NULL; PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Check"); PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); @@ -185,11 +188,38 @@ pkix_NameConstraintsChecker_Check( PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext), PKIX_ISCERTSELFISSUEDFAILED); + if (lastCert) { + /* For the last cert, treat the CN as a DNS name for name + * constraint check. But only if EKU has id-kp-serverAuth + * or EKU is absent. It does not make sense to treat CN + * as a DNS name for an OCSP signing certificate, for example. + */ + PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage + (cert, &extKeyUsageList, plContext), + PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); + if (extKeyUsageList == NULL) { + treatCommonNameAsDNSName = PKIX_TRUE; + } else { + PKIX_CHECK(PKIX_PL_OID_Create + (PKIX_KEY_USAGE_SERVER_AUTH_OID, + &serverAuthOID, + plContext), + PKIX_OIDCREATEFAILED); + + PKIX_CHECK(pkix_List_Contains + (extKeyUsageList, + (PKIX_PL_Object *) serverAuthOID, + &treatCommonNameAsDNSName, + plContext), + PKIX_LISTCONTAINSFAILED); + } + } + /* Check on non self-issued and if so only for last cert */ if (selfIssued == PKIX_FALSE || (selfIssued == PKIX_TRUE && lastCert)) { PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints - (cert, state->nameConstraints, lastCert, + (cert, state->nameConstraints, treatCommonNameAsDNSName, plContext), PKIX_CERTCHECKNAMECONSTRAINTSFAILED); } @@ -241,6 +271,8 @@ pkix_NameConstraintsChecker_Check( cleanup: PKIX_DECREF(state); + PKIX_DECREF(extKeyUsageList); + PKIX_DECREF(serverAuthOID); PKIX_RETURN(CERTCHAINCHECKER); } diff --git a/tests/chains/scenarios/nameconstraints.cfg b/tests/chains/scenarios/nameconstraints.cfg index 6eda441ce6..4a149032b1 100644 --- a/tests/chains/scenarios/nameconstraints.cfg +++ b/tests/chains/scenarios/nameconstraints.cfg @@ -10,6 +10,7 @@ import NameConstraints.ca:x:CT,C,C # Name Constrained CA: Name constrained to permited DNSName ".example" import NameConstraints.ncca:x:CT,C,C import NameConstraints.dcisscopy:x:CT,C,C +import NameConstraints.ipaca:x:CT,C,C # Intermediate 1: Name constrained to permited DNSName ".example" @@ -158,4 +159,12 @@ verify NameConstraints.dcissblocked:x verify NameConstraints.dcissallowed:x result pass +# Subject: "O = IPA.LOCAL 201901211552, CN = OCSP Subsystem" +# +# This tests that a non server certificate (i.e. id-kp-serverAuth +# not present in EKU) does *NOT* have CN treated as dnsName for +# purposes of Name Constraints validation +verify NameConstraints.ocsp1:x + usage 10 + result pass diff --git a/tests/libpkix/certs/NameConstraints.ipaca.cert b/tests/libpkix/certs/NameConstraints.ipaca.cert new file mode 100644 index 0000000000..6c7d68c770 Binary files /dev/null and b/tests/libpkix/certs/NameConstraints.ipaca.cert differ diff --git a/tests/libpkix/certs/NameConstraints.ocsp1.cert b/tests/libpkix/certs/NameConstraints.ocsp1.cert new file mode 100644 index 0000000000..ce7325fca9 Binary files /dev/null and b/tests/libpkix/certs/NameConstraints.ocsp1.cert differ