summaryrefslogtreecommitdiffstats
path: root/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
diff options
context:
space:
mode:
Diffstat (limited to 'nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c')
-rw-r--r--nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c b/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
new file mode 100644
index 0000000..28f21a6
--- /dev/null
+++ b/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
@@ -0,0 +1,340 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_nameconstraintschecker.c
+ *
+ * Functions for Name Constraints Checkers
+ *
+ */
+
+#include "pkix_nameconstraintschecker.h"
+
+/* --Private-NameConstraintsCheckerState-Functions---------------------- */
+
+/*
+ * FUNCTION: pkix_NameConstraintsCheckerstate_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_NameConstraintsCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
+ "pkix_NameConstraintsCheckerState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that object type */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTNAMECONSTRAINTSCHECKERSTATE);
+
+ state = (pkix_NameConstraintsCheckerState *)object;
+
+ PKIX_DECREF(state->nameConstraints);
+ PKIX_DECREF(state->nameConstraintsOID);
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_NameConstraintsCheckerState_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_NameConstraintsCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
+ "pkix_NameConstraintsCheckerState_RegisterSelf");
+
+ entry.description = "NameConstraintsCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(pkix_NameConstraintsCheckerState);
+ entry.destructor = pkix_NameConstraintsCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_NameConstraintsCheckerState_Create
+ *
+ * DESCRIPTION:
+ * Allocate and initialize NameConstraintsChecker state data.
+ *
+ * PARAMETERS
+ * "nameConstraints"
+ * Address of NameConstraints to be stored in state. May be NULL.
+ * "numCerts"
+ * Number of certificates in the validation chain. This data is used
+ * to identify end-entity.
+ * "pCheckerState"
+ * Address of NameConstraintsCheckerState that is returned. Must be
+ * non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CERTNAMECONSTRAINTSCHECKERSTATE Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error
+ */
+static PKIX_Error *
+pkix_NameConstraintsCheckerState_Create(
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_UInt32 numCerts,
+ pkix_NameConstraintsCheckerState **pCheckerState,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
+ "pkix_NameConstraintsCheckerState_Create");
+ PKIX_NULLCHECK_ONE(pCheckerState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE,
+ sizeof (pkix_NameConstraintsCheckerState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATENAMECONSTRAINTSCHECKERSTATEOBJECT);
+
+ /* Initialize fields */
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_NAMECONSTRAINTS_OID,
+ &state->nameConstraintsOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_INCREF(nameConstraints);
+
+ state->nameConstraints = nameConstraints;
+ state->certsRemaining = numCerts;
+
+ *pCheckerState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
+}
+
+/* --Private-NameConstraintsChecker-Functions------------------------- */
+
+/*
+ * FUNCTION: pkix_NameConstraintsChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+static PKIX_Error *
+pkix_NameConstraintsChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ 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);
+
+ *pNBIOContext = NULL; /* we never block on pending I/O */
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ state->certsRemaining--;
+ lastCert = state->certsRemaining == 0;
+
+ /* Get status of self issued */
+ 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, treatCommonNameAsDNSName,
+ plContext),
+ PKIX_CERTCHECKNAMECONSTRAINTSFAILED);
+ }
+
+ if (!lastCert) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (cert, &nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+ /* Merge with previous name constraints kept in state */
+
+ if (nameConstraints != NULL) {
+
+ if (state->nameConstraints == NULL) {
+
+ state->nameConstraints = nameConstraints;
+
+ } else {
+
+ PKIX_CHECK(PKIX_PL_Cert_MergeNameConstraints
+ (nameConstraints,
+ state->nameConstraints,
+ &mergedNameConstraints,
+ plContext),
+ PKIX_CERTMERGENAMECONSTRAINTSFAILED);
+
+ PKIX_DECREF(nameConstraints);
+ PKIX_DECREF(state->nameConstraints);
+
+ state->nameConstraints = mergedNameConstraints;
+ }
+
+ /* Remove Name Constraints Extension OID from list */
+ if (unresolvedCriticalExtensions != NULL) {
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticalExtensions,
+ (PKIX_PL_Object *)state->nameConstraintsOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+ }
+ }
+
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)state, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+ PKIX_DECREF(extKeyUsageList);
+ PKIX_DECREF(serverAuthOID);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_NameConstraintsChecker_Initialize
+ *
+ * DESCRIPTION:
+ * Create a CertChainChecker with a NameConstraintsCheckerState. The
+ * NameConstraintsCheckerState is created with "trustedNC" and "numCerts"
+ * as its initial state. The CertChainChecker for the NameConstraints is
+ * returned at address of "pChecker".
+ *
+ * PARAMETERS
+ * "trustedNC"
+ * The NameConstraints from trusted anchor Cert is stored at "trustedNC"
+ * for initialization. May be NULL.
+ * "numCerts"
+ * Number of certificates in the validation chain. This data is used
+ * to identify end-entity.
+ * "pChecker"
+ * Address of CertChainChecker to bo created and returned.
+ * Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CERTCHAINCHECKER Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+pkix_NameConstraintsChecker_Initialize(
+ PKIX_PL_CertNameConstraints *trustedNC,
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(pkix_NameConstraintsCheckerState_Create
+ (trustedNC, numCerts, &state, plContext),
+ PKIX_NAMECONSTRAINTSCHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_NameConstraintsChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *) state,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}