/* * FUNCTION: pkix_pl_Date_CreateFromPRTime * DESCRIPTION: * * Creates a new Date from the PRTime whose value is "prtime", and stores the * result at "pDate". * * PARAMETERS * "prtime" * The PRTime value to be embodied in the new Date object. * "pDate" * Address where object pointer will be stored. 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 Date Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_Date_CreateFromPRTime( PRTime prtime, PKIX_PL_Date **pDate, void *plContext) { PKIX_PL_Date *date = NULL; PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime"); PKIX_NULLCHECK_ONE(pDate); /* create a PKIX_PL_Date object */ PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_DATE_TYPE, sizeof (PKIX_PL_Date), (PKIX_PL_Object **)&date, plContext), PKIX_COULDNOTCREATEOBJECT); /* populate the nssTime field */ date->nssTime = prtime; *pDate = date; cleanup: PKIX_RETURN(DATE); }
/* * FUNCTION: pkix_pl_HashTable_Destroy * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_HashTable_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_PL_HashTable *ht = NULL; pkix_pl_HT_Elem *item = NULL; PKIX_UInt32 i; PKIX_ENTER(HASHTABLE, "pkix_pl_HashTable_Destroy"); PKIX_NULLCHECK_ONE(object); PKIX_CHECK(pkix_CheckType(object, PKIX_HASHTABLE_TYPE, plContext), PKIX_OBJECTNOTHASHTABLE); ht = (PKIX_PL_HashTable*) object; /* DecRef every object in the primitive hash table */ for (i = 0; i < ht->primHash->size; i++) { for (item = ht->primHash->buckets[i]; item != NULL; item = item->next) { PKIX_DECREF(item->key); PKIX_DECREF(item->value); } } PKIX_CHECK(pkix_pl_PrimHashTable_Destroy(ht->primHash, plContext), PKIX_PRIMHASHTABLEDESTROYFAILED); PKIX_DECREF(ht->tableLock); cleanup: PKIX_RETURN(HASHTABLE); }
/* * FUNCTION: pkix_pl_OcspCertID_Destroy * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_OcspCertID_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_PL_OcspCertID *certID = NULL; PKIX_ENTER(OCSPCERTID, "pkix_pl_OcspCertID_Destroy"); PKIX_NULLCHECK_ONE(object); PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPCERTID_TYPE, plContext), PKIX_OBJECTNOTOCSPCERTID); certID = (PKIX_PL_OcspCertID *)object; if (certID->certID) { CERT_DestroyOCSPCertID(certID->certID); } cleanup: PKIX_RETURN(OCSPCERTID); }
/* * FUNCTION: pkix_pl_CertPolicyQualifier_Destroy * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_CertPolicyQualifier_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_PL_CertPolicyQualifier *certPQ = NULL; PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Destroy"); PKIX_NULLCHECK_ONE(object); PKIX_CHECK(pkix_CheckType (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext), PKIX_OBJECTNOTCERTPOLICYQUALIFIER); certPQ = (PKIX_PL_CertPolicyQualifier*)object; PKIX_DECREF(certPQ->policyQualifierId); PKIX_DECREF(certPQ->qualifier); cleanup: PKIX_RETURN(CERTPOLICYQUALIFIER); }
/* * FUNCTION: pkix_ValidateResult_Destroy * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_ValidateResult_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_ValidateResult *result = NULL; PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Destroy"); PKIX_NULLCHECK_ONE(object); /* Check that this object is a validate result object */ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext), PKIX_OBJECTNOTVALIDATERESULT); result = (PKIX_ValidateResult *)object; PKIX_DECREF(result->anchor); PKIX_DECREF(result->pubKey); PKIX_DECREF(result->policyTree); cleanup: PKIX_RETURN(VALIDATERESULT); }
/* * FUNCTION: pkix_pl_CertBasicConstraints_Destroy * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_CertBasicConstraints_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_PL_CertBasicConstraints *certB = NULL; PKIX_ENTER(CERTBASICCONSTRAINTS, "pkix_pl_CertBasicConstraints_Destroy"); PKIX_NULLCHECK_ONE(object); PKIX_CHECK(pkix_CheckType (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext), PKIX_OBJECTNOTCERTBASICCONSTRAINTS); certB = (PKIX_PL_CertBasicConstraints*)object; certB->isCA = PKIX_FALSE; certB->pathLen = 0; cleanup: PKIX_RETURN(CERTBASICCONSTRAINTS); }
/* * FUNCTION: pkix_pl_CollectionCertStoreContext_Destroy * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_CollectionCertStoreContext_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL; PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, "pkix_pl_CollectionCertStoreContext_Destroy"); PKIX_NULLCHECK_ONE(object); PKIX_CHECK(pkix_CheckType (object, PKIX_COLLECTIONCERTSTORECONTEXT_TYPE, plContext), PKIX_OBJECTNOTCOLLECTIONCERTSTORECONTEXT); colCertStoreContext = (PKIX_PL_CollectionCertStoreContext *)object; PKIX_DECREF(colCertStoreContext->storeDir); PKIX_DECREF(colCertStoreContext->crlList); PKIX_DECREF(colCertStoreContext->certList); cleanup: PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); }
/* * FUNCTION: pkix_RevocationChecker_Destroy * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_RevocationChecker_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_RevocationChecker *checker = NULL; PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_Destroy"); PKIX_NULLCHECK_ONE(object); /* Check that this object is a revocation checker */ PKIX_CHECK(pkix_CheckType (object, PKIX_REVOCATIONCHECKER_TYPE, plContext), PKIX_OBJECTNOTREVOCATIONCHECKER); checker = (PKIX_RevocationChecker *)object; PKIX_DECREF(checker->leafMethodList); PKIX_DECREF(checker->chainMethodList); cleanup: PKIX_RETURN(REVOCATIONCHECKER); }
/* * FUNCTION: pkix_DefaultCRLChecker_Check * * DESCRIPTION: * Check if the Cert has been revoked based the CRLs data. This function * maintains the checker state to be current. * * PARAMETERS * "checker" * Address of CertChainChecker which has the state data. * Must be non-NULL. * "cert" * Address of Certificate that is to be validated. Must be non-NULL. * "unresolvedCriticalExtensions" * A List OIDs. Not **yet** used in this checker function. * "plContext" * Platform-specific context pointer. * * THREAD SAFETY: * Not 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 */ static PKIX_Error * pkix_DefaultCRLChecker_Check( PKIX_CertChainChecker *checker, PKIX_PL_Cert *cert, PKIX_List *unresolvedCriticalExtensions, void **pNBIOContext, void *plContext) { pkix_DefaultCRLCheckerState *state = NULL; PKIX_PL_PublicKey *publicKey = NULL; PKIX_PL_PublicKey *newPublicKey = NULL; PKIX_Error *checkKeyUsageFail = NULL; PKIX_Boolean selfIssued = PKIX_FALSE; void *nbioContext = NULL; PKIX_ENTER(CERTCHAINCHECKER, "pkix_DefaultCRLChecker_Check"); PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); nbioContext = *pNBIOContext; *pNBIOContext = NULL; /* prepare for Error exit */ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState (checker, (PKIX_PL_Object **)&state, plContext), PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey (cert, &publicKey, plContext), PKIX_CERTGETSUBJECTPUBLICKEYFAILED); /* * If we already have a selector, we were in the middle of checking * when a certStore returned with non-blocking I/O pendning. */ if ((state->crlSelector) == NULL) { state->certsRemaining--; PKIX_NULLCHECK_ONE(state->prevPublicKey); if (state->prevCertCrlSign == PKIX_FALSE) { PKIX_ERROR (PKIX_KEYUSAGEKEYCRLSIGNBITNOTON); } /* Set up CRLSelector */ PKIX_CHECK(pkix_DefaultCRLChecker_Check_SetSelector (cert, state, plContext), PKIX_DEFAULTCRLCHECKERCHECKSETSELECTORFAILED); } PKIX_CHECK(pkix_DefaultCRLChecker_Check_Helper (checker, cert, state->prevPublicKey, state, unresolvedCriticalExtensions, PKIX_FALSE, &nbioContext, plContext), PKIX_DEFAULTCRLCHECKERCHECKHELPERFAILED); if (nbioContext != NULL) { *pNBIOContext = nbioContext; goto cleanup; } PKIX_DECREF(state->crlSelector); /* * Some NIST test case in 4.5.* use different publicKeys for * Cert and its CRL on the chain. Self-issued Certs are used * to speciy multiple keys for those cases. That is why we apply * the following algorithm: * * Check if Cert is self-issued. If so, the public key of the Cert * that issues this Cert (old key) can be used together with this * current key (new key) for key verification. If there are multiple * self-issued certs, keys of those Certs (old keys) can also be used * for key verification. Old key(s) is saved in a list (PrevPublickKey- * List) and cleared when a Cert is no longer self-issued. * PrevPublicKey keep key of the previous Cert. * PrevPublicKeyList keep key(s) of Cert before the previous one. */ PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext), PKIX_ISCERTSELFISSUEFAILED); if (selfIssued == PKIX_TRUE) { if (state->prevPublicKeyList == NULL) { PKIX_CHECK(PKIX_List_Create (&state->prevPublicKeyList, plContext), PKIX_LISTCREATEFAILED); } PKIX_CHECK(PKIX_List_AppendItem (state->prevPublicKeyList, (PKIX_PL_Object *) state->prevPublicKey, plContext), PKIX_LISTAPPENDITEMFAILED); } else { /* Not self-issued Cert any more, clear old key(s) saved */ PKIX_DECREF(state->prevPublicKeyList); } /* Make inheritance and save current Public Key */ PKIX_CHECK(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey (publicKey, state->prevPublicKey, &newPublicKey, plContext), PKIX_PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED); if (newPublicKey == NULL){ PKIX_INCREF(publicKey); newPublicKey = publicKey; } PKIX_DECREF(state->prevPublicKey); PKIX_INCREF(newPublicKey); state->prevPublicKey = newPublicKey; /* Save current Cert's crlSign bit for CRL checking later */ if (state->certsRemaining != 0) { checkKeyUsageFail = PKIX_PL_Cert_VerifyKeyUsage (cert, PKIX_CRL_SIGN, plContext); state->prevCertCrlSign = (checkKeyUsageFail == NULL)? PKIX_TRUE : PKIX_FALSE; PKIX_DECREF(checkKeyUsageFail); } /* PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState (checker, (PKIX_PL_Object *)state, plContext), PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); */ cleanup: PKIX_DECREF(state); PKIX_DECREF(publicKey); PKIX_DECREF(newPublicKey); PKIX_DECREF(checkKeyUsageFail); PKIX_RETURN(CERTCHAINCHECKER); }
/* * FUNCTION: pkix_pl_OcspResponse_Create * DESCRIPTION: * * This function transmits the OcspRequest pointed to by "request" and obtains * an OcspResponse, which it stores at "pOcspResponse". If the HTTPClient * supports non-blocking I/O this function may store a non-NULL value at * "pNBIOContext" (the WOULDBLOCK condition). In that case the caller should * make a subsequent call with the same value in "pNBIOContext" and * "pOcspResponse" to resume the operation. Additional WOULDBLOCK returns may * occur; the caller should persist until a return occurs with NULL stored at * "pNBIOContext". * * If a SEC_HttpClientFcn "responder" is supplied, it is used as the client * to which the OCSP query is sent. If none is supplied, the default responder * is used. * * If an OcspResponse_VerifyCallback "verifyFcn" is supplied, it is used to * verify the Cert received from the responder as the signer. If none is * supplied, the default verification function is used. * * The contents of "request" are ignored on calls subsequent to a WOULDBLOCK * return, and the caller is permitted to supply NULL. * * PARAMETERS * "request" * Address of the OcspRequest for which a response is desired. * "responder" * Address, if non-NULL, of the SEC_HttpClientFcn to be sent the OCSP * query. * "verifyFcn" * Address, if non-NULL, of the OcspResponse_VerifyCallback function to be * used to verify the Cert of the OCSP responder. * "pNBIOContext" * Address at which platform-dependent information is stored for handling * of non-blocking I/O. Must be non-NULL. * "pOcspResponse" * The address where the created OcspResponse is stored. 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 an OcspResponse Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_OcspResponse_Create( PKIX_PL_OcspRequest *request, void *responder, PKIX_PL_VerifyCallback verifyFcn, void **pNBIOContext, PKIX_PL_OcspResponse **pResponse, void *plContext) { void *nbioContext = NULL; PKIX_PL_OcspResponse *ocspResponse = NULL; const SEC_HttpClientFcn *httpClient = NULL; const SEC_HttpClientFcnV1 *hcv1 = NULL; SECStatus rv = SECFailure; char *location = NULL; char *hostname = NULL; char *path = NULL; char *responseContentType = NULL; PRUint16 port = 0; SEC_HTTP_SERVER_SESSION serverSession = NULL; SEC_HTTP_REQUEST_SESSION sessionRequest = NULL; SECItem *encodedRequest = NULL; PRUint16 responseCode = 0; char *responseData = NULL; PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Create"); PKIX_NULLCHECK_TWO(pNBIOContext, pResponse); nbioContext = *pNBIOContext; *pNBIOContext = NULL; if (nbioContext != NULL) { ocspResponse = *pResponse; PKIX_NULLCHECK_ONE(ocspResponse); httpClient = ocspResponse->httpClient; serverSession = ocspResponse->serverSession; sessionRequest = ocspResponse->sessionRequest; PKIX_NULLCHECK_THREE(httpClient, serverSession, sessionRequest); } else { PKIX_UInt32 timeout = ((PKIX_PL_NssContext*)plContext)->timeoutSeconds; PKIX_NULLCHECK_ONE(request); PKIX_CHECK(pkix_pl_OcspRequest_GetEncoded (request, &encodedRequest, plContext), PKIX_OCSPREQUESTGETENCODEDFAILED); /* prepare initial message to HTTPClient */ /* Is there a default responder and is it enabled? */ if (responder) { httpClient = (const SEC_HttpClientFcn *)responder; } else { httpClient = SEC_GetRegisteredHttpClient(); } if (httpClient && (httpClient->version == 1)) { hcv1 = &(httpClient->fcnTable.ftable1); PKIX_CHECK(pkix_pl_OcspRequest_GetLocation (request, &location, plContext), PKIX_OCSPREQUESTGETLOCATIONFAILED); /* parse location -> hostname, port, path */ rv = CERT_ParseURL(location, &hostname, &port, &path); if (rv == SECFailure || hostname == NULL || path == NULL) { PKIX_ERROR(PKIX_URLPARSINGFAILED); } rv = (*hcv1->createSessionFcn)(hostname, port, &serverSession); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } rv = (*hcv1->createFcn)(serverSession, "http", path, "POST", PR_SecondsToInterval(timeout), &sessionRequest); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } rv = (*hcv1->setPostDataFcn)(sessionRequest, (char *)encodedRequest->data, encodedRequest->len, "application/ocsp-request"); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } /* create a PKIX_PL_OcspResponse object */ PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_OCSPRESPONSE_TYPE, sizeof (PKIX_PL_OcspResponse), (PKIX_PL_Object **)&ocspResponse, plContext), PKIX_COULDNOTCREATEOBJECT); PKIX_INCREF(request); ocspResponse->request = request; ocspResponse->httpClient = httpClient; ocspResponse->serverSession = serverSession; ocspResponse->sessionRequest = sessionRequest; ocspResponse->verifyFcn = verifyFcn; ocspResponse->handle = CERT_GetDefaultCertDB(); ocspResponse->encodedResponse = NULL; ocspResponse->arena = NULL; ocspResponse->producedAt = 0; ocspResponse->producedAtDate = NULL; ocspResponse->pkixSignerCert = NULL; ocspResponse->nssOCSPResponse = NULL; ocspResponse->signerCert = NULL; } } /* begin or resume IO to HTTPClient */ if (httpClient && (httpClient->version == 1)) { PRUint32 responseDataLen = ((PKIX_PL_NssContext*)plContext)->maxResponseLength; hcv1 = &(httpClient->fcnTable.ftable1); rv = (*hcv1->trySendAndReceiveFcn)(sessionRequest, (PRPollDesc **)&nbioContext, &responseCode, &responseContentType, NULL, /* responseHeaders */ (const char **)&responseData, &responseDataLen); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } /* responseContentType is a pointer to the null-terminated * string returned by httpclient. Memory allocated for context * type will be freed with freeing of the HttpClient struct. */ if (PORT_Strcasecmp(responseContentType, "application/ocsp-response")) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } if (nbioContext != NULL) { *pNBIOContext = nbioContext; goto cleanup; } if (responseCode != 200) { PKIX_ERROR(PKIX_OCSPBADHTTPRESPONSE); } ocspResponse->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (ocspResponse->arena == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } ocspResponse->encodedResponse = SECITEM_AllocItem (ocspResponse->arena, NULL, responseDataLen); if (ocspResponse->encodedResponse == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } PORT_Memcpy(ocspResponse->encodedResponse->data, responseData, responseDataLen); } *pResponse = ocspResponse; cleanup: if (path != NULL) { PORT_Free(path); } if (hostname != NULL) { PORT_Free(hostname); } if (PKIX_ERROR_RECEIVED){ if (ocspResponse) { PKIX_DECREF(ocspResponse); } else { if (serverSession) hcv1->freeSessionFcn(serverSession); if (sessionRequest) hcv1->freeFcn(sessionRequest); } } PKIX_RETURN(OCSPRESPONSE); }
/* * FUNCTION: pkix_TargetCertCheckerState_Create * DESCRIPTION: * * Creates a new TargetCertCheckerState using the CertSelector pointed to * by "certSelector" and the number of certs represented by "certsRemaining" * and stores it at "pState". * * PARAMETERS: * "certSelector" * Address of CertSelector representing the criteria against which the * final certificate in a chain is to be matched. Must be non-NULL. * "certsRemaining" * Number of certificates remaining in the chain. * "pState" * Address where object pointer will be stored. 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 TargetCertCheckerState Error if the function fails in a * non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_TargetCertCheckerState_Create( PKIX_CertSelector *certSelector, PKIX_UInt32 certsRemaining, pkix_TargetCertCheckerState **pState, void *plContext) { pkix_TargetCertCheckerState *state = NULL; PKIX_ComCertSelParams *certSelectorParams = NULL; PKIX_List *pathToNameList = NULL; PKIX_List *extKeyUsageList = NULL; PKIX_List *subjAltNameList = NULL; PKIX_PL_OID *extKeyUsageOID = NULL; PKIX_PL_OID *subjAltNameOID = NULL; PKIX_Boolean subjAltNameMatchAll = PKIX_TRUE; PKIX_ENTER(TARGETCERTCHECKERSTATE, "pkix_TargetCertCheckerState_Create"); PKIX_NULLCHECK_ONE(pState); PKIX_CHECK(PKIX_PL_OID_Create (PKIX_EXTENDEDKEYUSAGE_OID, &extKeyUsageOID, plContext), PKIX_OIDCREATEFAILED); PKIX_CHECK(PKIX_PL_OID_Create (PKIX_CERTSUBJALTNAME_OID, &subjAltNameOID, plContext), PKIX_OIDCREATEFAILED); PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_TARGETCERTCHECKERSTATE_TYPE, sizeof (pkix_TargetCertCheckerState), (PKIX_PL_Object **)&state, plContext), PKIX_COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT); /* initialize fields */ if (certSelector != NULL) { PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams (certSelector, &certSelectorParams, plContext), PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED); if (certSelectorParams != NULL) { PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames (certSelectorParams, &pathToNameList, plContext), PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED); PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage (certSelectorParams, &extKeyUsageList, plContext), PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames (certSelectorParams, &subjAltNameList, plContext), PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED); PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames (certSelectorParams, &subjAltNameMatchAll, plContext), PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED); } } state->certsRemaining = certsRemaining; state->subjAltNameMatchAll = subjAltNameMatchAll; PKIX_INCREF(certSelector); state->certSelector = certSelector; state->pathToNameList = pathToNameList; pathToNameList = NULL; state->extKeyUsageList = extKeyUsageList; extKeyUsageList = NULL; state->subjAltNameList = subjAltNameList; subjAltNameList = NULL; state->extKeyUsageOID = extKeyUsageOID; extKeyUsageOID = NULL; state->subjAltNameOID = subjAltNameOID; subjAltNameOID = NULL; *pState = state; state = NULL; cleanup: PKIX_DECREF(extKeyUsageOID); PKIX_DECREF(subjAltNameOID); PKIX_DECREF(pathToNameList); PKIX_DECREF(extKeyUsageList); PKIX_DECREF(subjAltNameList); PKIX_DECREF(state); PKIX_DECREF(certSelectorParams); PKIX_RETURN(TARGETCERTCHECKERSTATE); }
/* * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h) */ PKIX_Error * PKIX_AddLogger( PKIX_Logger *logger, void *plContext) { PKIX_Logger *dupLogger = NULL; PKIX_Logger *addLogger = NULL; PKIX_List *savedPkixLoggersErrors = NULL; PKIX_List *savedPkixLoggersDebugTrace = NULL; PKIX_Boolean locked = PKIX_FALSE; PKIX_UInt32 i, length; PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger"); PKIX_NULLCHECK_ONE(logger); PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), PKIX_MONITORLOCKENTERFAILED); locked = PKIX_TRUE; savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; pkixLoggersDebugTrace = NULL; savedPkixLoggersErrors = pkixLoggersErrors; pkixLoggersErrors = NULL; PKIX_DECREF(savedPkixLoggersErrors); PKIX_DECREF(savedPkixLoggersDebugTrace); if (pkixLoggers == NULL) { PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext), PKIX_LISTCREATEFAILED); } PKIX_CHECK(pkix_Logger_Duplicate ((PKIX_PL_Object *)logger, (PKIX_PL_Object **)&dupLogger, plContext), PKIX_LOGGERDUPLICATEFAILED); PKIX_CHECK(PKIX_List_AppendItem (pkixLoggers, (PKIX_PL_Object *) dupLogger, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext), PKIX_LISTGETLENGTHFAILED); /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */ for (i = 0; i < length; i++) { PKIX_CHECK(PKIX_List_GetItem (pkixLoggers, i, (PKIX_PL_Object **) &addLogger, plContext), PKIX_LISTGETITEMFAILED); /* Put in pkixLoggersErrors */ if (savedPkixLoggersErrors == NULL) { PKIX_CHECK(PKIX_List_Create (&savedPkixLoggersErrors, plContext), PKIX_LISTCREATEFAILED); } PKIX_CHECK(PKIX_List_AppendItem (savedPkixLoggersErrors, (PKIX_PL_Object *) addLogger, plContext), PKIX_LISTAPPENDITEMFAILED); if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { /* Put in pkixLoggersDebugTrace */ if (savedPkixLoggersDebugTrace == NULL) { PKIX_CHECK(PKIX_List_Create (&savedPkixLoggersDebugTrace, plContext), PKIX_LISTCREATEFAILED); } PKIX_CHECK(PKIX_List_AppendItem (savedPkixLoggersDebugTrace, (PKIX_PL_Object *) addLogger, plContext), PKIX_LISTAPPENDITEMFAILED); } PKIX_DECREF(addLogger); } cleanup: PKIX_DECREF(dupLogger); PKIX_DECREF(addLogger); /* Restore logging capability */ pkixLoggersErrors = savedPkixLoggersErrors; pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; if (locked) { PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), PKIX_MONITORLOCKEXITFAILED); } PKIX_RETURN(LOGGER); }
/* * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h) */ PKIX_Error * PKIX_GetLoggers( PKIX_List **pLoggers, /* list of PKIX_Logger */ void *plContext) { PKIX_List *list = NULL; PKIX_List *savedPkixLoggersDebugTrace = NULL; PKIX_List *savedPkixLoggersErrors = NULL; PKIX_Logger *logger = NULL; PKIX_Logger *dupLogger = NULL; PKIX_UInt32 i, length; PKIX_Boolean locked = PKIX_FALSE; PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers"); PKIX_NULLCHECK_ONE(pLoggers); PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), PKIX_MONITORLOCKENTERFAILED); locked = PKIX_TRUE; /* * Temporarily disable DEBUG/TRACE Logging to avoid possible * deadlock: * When the Logger List is being accessed, e.g. by PKIX_ENTER or * PKIX_DECREF, pkix_Logger_Check may check whether logging * is requested, creating a deadlock situation. */ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; pkixLoggersDebugTrace = NULL; savedPkixLoggersErrors = pkixLoggersErrors; pkixLoggersErrors = NULL; if (pkixLoggers == NULL) { length = 0; } else { PKIX_CHECK(PKIX_List_GetLength (pkixLoggers, &length, plContext), PKIX_LISTGETLENGTHFAILED); } /* Create a list and copy the pkixLoggers item to the list */ PKIX_CHECK(PKIX_List_Create(&list, plContext), PKIX_LISTCREATEFAILED); for (i = 0; i < length; i++) { PKIX_CHECK(PKIX_List_GetItem (pkixLoggers, i, (PKIX_PL_Object **) &logger, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_Logger_Duplicate ((PKIX_PL_Object *)logger, (PKIX_PL_Object **)&dupLogger, plContext), PKIX_LOGGERDUPLICATEFAILED); PKIX_CHECK(PKIX_List_AppendItem (list, (PKIX_PL_Object *) dupLogger, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(logger); PKIX_DECREF(dupLogger); } /* Set the list to be immutable */ PKIX_CHECK(PKIX_List_SetImmutable(list, plContext), PKIX_LISTSETIMMUTABLEFAILED); *pLoggers = list; cleanup: PKIX_DECREF(logger); /* Restore logging capability */ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; pkixLoggersErrors = savedPkixLoggersErrors; if (locked) { PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), PKIX_MONITORLOCKEXITFAILED); } PKIX_RETURN(LOGGER); }
/* * FUNCTION: pkix_pl_HttpCertStore_GetCertContinue * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) */ PKIX_Error * pkix_pl_HttpCertStore_GetCertContinue( PKIX_CertStore *store, PKIX_CertSelector *selector, void **pNBIOContext, PKIX_List **pCertList, void *plContext) { const SEC_HttpClientFcnV1 *hcv1 = NULL; PKIX_PL_HttpCertStoreContext *context = NULL; void *nbioContext = NULL; SECStatus rv = SECFailure; PRUint16 responseCode = 0; const char *responseContentType = NULL; const char *responseData = NULL; PRUint32 responseDataLen = 0; PKIX_List *certList = NULL; PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCertContinue"); PKIX_NULLCHECK_THREE(store, selector, pCertList); nbioContext = *pNBIOContext; *pNBIOContext = NULL; PKIX_CHECK(PKIX_CertStore_GetCertStoreContext (store, (PKIX_PL_Object **)&context, plContext), PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); if (context->client->version != 1) { PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); } hcv1 = &(context->client->fcnTable.ftable1); PKIX_NULLCHECK_ONE(context->requestSession); responseDataLen = ((PKIX_PL_NssContext*)plContext)->maxResponseLength; rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession, (PRPollDesc **)&nbioContext, &responseCode, (const char **)&responseContentType, NULL, /* &responseHeaders */ (const char **)&responseData, &responseDataLen); if (rv != SECSuccess) { PKIX_ERROR(PKIX_HTTPSERVERERROR); } if (nbioContext != 0) { *pNBIOContext = nbioContext; goto cleanup; } PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse (responseCode, responseContentType, responseData, responseDataLen, &certList, plContext), PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED); *pCertList = certList; cleanup: PKIX_DECREF(context); PKIX_RETURN(CERTSTORE); }
/* * FUNCTION: pkix_pl_CollectionCertStoreContext_PopulateCRL * DESCRIPTION: * * Create list of CRLs from *.crl files at directory specified in dirName, * Not recursive to sub-dirctory. Also assume the directory contents are * not changed dynamically. * * PARAMETERS * "colCertStoreContext" - Address of CollectionCertStoreContext * where the dirName is specified and where the return * CRLs are stored as a list. Must be non-NULL. * "plContext" - Platform-specific context pointer. * * THREAD SAFETY: * Not Thread Safe - A lock at top level is required. * * RETURNS: * Returns NULL if the function succeeds. * Returns a CollectionCertStoreContext Error if the function fails in * a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ static PKIX_Error * pkix_pl_CollectionCertStoreContext_PopulateCRL( PKIX_PL_CollectionCertStoreContext *colCertStoreContext, void *plContext) { PKIX_List *crlList = NULL; PKIX_PL_CRL *crlItem = NULL; char *dirName = NULL; char *pathName = NULL; PKIX_UInt32 dirNameLen = 0; PRErrorCode prError = 0; PRDir *dir = NULL; PRDirEntry *dirEntry = NULL; PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, "pkix_pl_CollectionCertStoreContext_PopulateCRL"); PKIX_NULLCHECK_ONE(colCertStoreContext); /* convert directory to ascii */ PKIX_CHECK(PKIX_PL_String_GetEncoded (colCertStoreContext->storeDir, PKIX_ESCASCII, (void **)&dirName, &dirNameLen, plContext), PKIX_STRINGGETENCODEDFAILED); /* create CRL list, if no CRL file, should return an empty list */ PKIX_CHECK(PKIX_List_Create(&crlList, plContext), PKIX_LISTCREATEFAILED); /* open directory and read in .crl files */ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_OpenDir.\n"); dir = PR_OpenDir(dirName); if (!dir) { PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG ("\t\t Directory Name:%s\n", dirName); PKIX_ERROR(PKIX_CANNOTOPENCOLLECTIONCERTSTORECONTEXTDIRECTORY); } PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_ReadDir.\n"); dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH); if (!dirEntry) { PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Empty directory.\n"); PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling PR_GetError.\n"); prError = PR_GetError(); } PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_SetError.\n"); PR_SetError(0, 0); while (dirEntry != NULL && prError == 0) { if (PL_strrstr(dirEntry->name, ".crl") == dirEntry->name + PL_strlen(dirEntry->name) - 4) { PKIX_CHECK_ONLY_FATAL (PKIX_PL_Malloc (dirNameLen + PL_strlen(dirEntry->name) + 2, (void **)&pathName, plContext), PKIX_MALLOCFAILED); if ((!PKIX_ERROR_RECEIVED) && (pathName != NULL)){ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling PL_strcpy for dirName.\n"); PL_strcpy(pathName, dirName); PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling PL_strcat for dirName.\n"); PL_strcat(pathName, "/"); PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling PL_strcat for /.\n"); PL_strcat(pathName, dirEntry->name); PKIX_CHECK_ONLY_FATAL (pkix_pl_CollectionCertStoreContext_CreateCRL (pathName, &crlItem, plContext), PKIX_COLLECTIONCERTSTORECONTEXTCREATECRLFAILED); if (!PKIX_ERROR_RECEIVED){ PKIX_CHECK_ONLY_FATAL (PKIX_List_AppendItem (crlList, (PKIX_PL_Object *)crlItem, plContext), PKIX_LISTAPPENDITEMFAILED); } } PKIX_DECREF(crlItem); PKIX_FREE(pathName); } PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling PR_SetError.\n"); PR_SetError(0, 0); PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling PR_ReadDir.\n"); dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH); if (!dirEntry) { PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling PR_GetError.\n"); prError = PR_GetError(); } } if ((prError != 0) && (prError != PR_NO_MORE_FILES_ERROR)) { PKIX_ERROR(PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED); } PKIX_CHECK(PKIX_List_SetImmutable(crlList, plContext), PKIX_LISTSETIMMUTABLEFAILED); PKIX_INCREF(crlList); colCertStoreContext->crlList = crlList; cleanup: if (dir) { PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling PR_CloseDir.\n"); PR_CloseDir(dir); } PKIX_FREE(pathName); PKIX_FREE(dirName); if (PKIX_ERROR_RECEIVED){ PKIX_DECREF(crlList); } PKIX_DECREF(crlItem); PKIX_DECREF(crlList); PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); }
/* * FUNCTION: PKIX_List_DeleteItem (see comments in pkix_util.h) */ PKIX_Error * PKIX_List_DeleteItem( PKIX_List *list, PKIX_UInt32 index, void *plContext) { PKIX_List *element = NULL; PKIX_List *prevElement = NULL; PKIX_List *nextElement = NULL; PKIX_ENTER(LIST, "PKIX_List_DeleteItem"); PKIX_NULLCHECK_ONE(list); if (list->immutable){ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); } if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), PKIX_LISTGETELEMENTFAILED); /* DecRef old contents */ PKIX_DECREF(element->item); nextElement = element->next; if (nextElement != NULL) { /* If the next element exists, splice it out. */ /* Don't need to change ref counts for targets of next */ element->item = nextElement->item; nextElement->item = NULL; /* Don't need to change ref counts for targets of next */ element->next = nextElement->next; nextElement->next = NULL; PKIX_DECREF(nextElement); } else { /* The element is at the tail of the list */ if (index != 0) { PKIX_CHECK(pkix_List_GetElement (list, index-1, &prevElement, plContext), PKIX_LISTGETELEMENTFAILED); } else if (index == 0){ /* prevElement must be header */ prevElement = list; } prevElement->next = NULL; /* Delete the element */ PKIX_DECREF(element); } PKIX_CHECK(PKIX_PL_Object_InvalidateCache ((PKIX_PL_Object *)list, plContext), PKIX_OBJECTINVALIDATECACHEFAILED); list->length = list->length - 1; cleanup: PKIX_RETURN(LIST); }
/* * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_DecRef( PKIX_PL_Object *object, void *plContext) { PKIX_Int32 refCount = 0; PKIX_PL_Object *objectHeader = NULL; PKIX_PL_NssContext *context = NULL; PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef"); PKIX_NULLCHECK_ONE(object); if (plContext){ /* * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't * have a header therefore we cannot verify its type before * casting. */ context = (PKIX_PL_NssContext *) plContext; if (context->arena != NULL) { goto cleanup; } } if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { goto cleanup; } /* Shift pointer from user data to object header */ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); refCount = PR_ATOMIC_DECREMENT(&objectHeader->references); if (refCount == 0) { PKIX_PL_DestructorCallback destructor = NULL; pkix_ClassTable_Entry *ctEntry = NULL; PKIX_UInt32 objType = objectHeader->type; /* first, special handling for system types */ if (objType >= PKIX_NUMTYPES){ #ifdef PKIX_USER_OBJECT_TYPE PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG ("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL (PKIX_ERRORINGETTINGDESTRUCTOR); } if (ctEntry != NULL){ destructor = ctEntry->destructor; } #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { ctEntry = &systemClasses[objType]; destructor = ctEntry->destructor; } if (destructor != NULL){ /* Call destructor on user data if necessary */ pkixErrorResult = destructor(object, plContext); if (pkixErrorResult) { pkixErrorClass = PKIX_FATAL_ERROR; PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext); pkixErrorResult = NULL; } } /* Atomically decrement object counter */ PR_ATOMIC_DECREMENT(&ctEntry->objCounter); /* pkix_pl_Object_Destroy assumes the lock is held */ /* It will call unlock and destroy the object */ pkixErrorResult = pkix_pl_Object_Destroy(object, plContext); goto cleanup; } if (refCount < 0) { PKIX_ERROR_ALLOC_ERROR(); } cleanup: PKIX_RETURN(OBJECT); }
/* * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_Alloc( PKIX_TYPENUM objType, PKIX_UInt32 size, PKIX_PL_Object **pObject, void *plContext) { PKIX_PL_Object *object = NULL; pkix_ClassTable_Entry *ctEntry = NULL; PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc"); PKIX_NULLCHECK_ONE(pObject); /* * We need to ensure that user-defined types have been registered. * All system types have already been registered by PKIX_PL_Initialize. */ if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type */ #ifdef PKIX_USER_OBJECT_TYPE PKIX_Boolean typeRegistered; PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); } typeRegistered = (ctEntry != NULL); if (!typeRegistered) { PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT); } #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { ctEntry = &systemClasses[objType]; } PORT_Assert(size == ctEntry->typeObjectSize); /* Allocate space for the object header and the requested size */ #ifdef PKIX_OBJECT_LEAK_TEST PKIX_CHECK(PKIX_PL_Calloc (1, ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, (void **)&object, plContext), PKIX_MALLOCFAILED); #else PKIX_CHECK(PKIX_PL_Malloc (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, (void **)&object, plContext), PKIX_MALLOCFAILED); #endif /* PKIX_OBJECT_LEAK_TEST */ /* Initialize all object fields */ object->magicHeader = PKIX_MAGIC_HEADER; object->type = objType; object->references = 1; /* Default to a single reference */ object->stringRep = NULL; object->hashcode = 0; object->hashcodeCached = 0; /* Cannot use PKIX_PL_Mutex because it depends on Object */ /* Using NSPR Locks instead */ PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n"); object->lock = PR_NewLock(); if (object->lock == NULL) { PKIX_ERROR_ALLOC_ERROR(); } PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); /* Return a pointer to the user data. Need to offset by object size */ *pObject = object + 1; object = NULL; /* Atomically increment object counter */ PR_ATOMIC_INCREMENT(&ctEntry->objCounter); cleanup: PKIX_FREE(object); PKIX_RETURN(OBJECT); }
/* * FUNCTION: PKIX_PL_Date_Create_UTCTime (see comments in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_Date_Create_UTCTime( PKIX_PL_String *stringRep, PKIX_PL_Date **pDate, void *plContext) { PKIX_PL_Date *date = NULL; char *asciiString = NULL; PKIX_UInt32 escAsciiLength; SECItem nssTime; SECStatus rv; PRTime time; PKIX_ENTER(DATE, "PKIX_PL_Date_Create_UTCTime"); PKIX_NULLCHECK_ONE(pDate); if (stringRep == NULL){ PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n"); time = PR_Now(); } else { /* convert the input PKIX_PL_String to PKIX_ESCASCII */ PKIX_CHECK(PKIX_PL_String_GetEncoded (stringRep, PKIX_ESCASCII, (void **)&asciiString, &escAsciiLength, plContext), PKIX_STRINGGETENCODEDFAILED); PKIX_DATE_DEBUG("\t\tCalling DER_AsciiToTime).\n"); /* DER_AsciiToTime only supports UTCTime (2-digit years) */ rv = DER_AsciiToTime(&time, asciiString); if (rv != SECSuccess){ PKIX_ERROR(PKIX_DERASCIITOTIMEFAILED); } } PKIX_DATE_DEBUG("\t\tCalling DER_TimeToUTCTime).\n"); rv = DER_TimeToUTCTime(&nssTime, time); if (rv != SECSuccess){ PKIX_ERROR(PKIX_DERTIMETOUTCTIMEFAILED); } /* create a PKIX_PL_Date object */ PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_DATE_TYPE, sizeof (PKIX_PL_Date), (PKIX_PL_Object **)&date, plContext), PKIX_COULDNOTCREATEOBJECT); /* populate the nssTime field */ date->nssTime = nssTime; *pDate = date; cleanup: PKIX_FREE(asciiString); if (PKIX_ERROR_RECEIVED){ PR_Free(nssTime.data); } PKIX_RETURN(DATE); }
/* * FUNCTION: pkix_pl_GeneralName_Hashcode * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_GeneralName_Hashcode( PKIX_PL_Object *object, PKIX_UInt32 *pHashcode, void *plContext) { PKIX_PL_GeneralName *name = NULL; PKIX_UInt32 firstHash, secondHash, nameHash; PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Hashcode"); PKIX_NULLCHECK_TWO(object, pHashcode); PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext), PKIX_OBJECTNOTGENERALNAME); name = (PKIX_PL_GeneralName *)object; switch (name->type) { case certRFC822Name: case certDNSName: case certX400Address: case certEDIPartyName: case certURI: case certIPAddress: PKIX_NULLCHECK_ONE(name->other); PKIX_CHECK(pkix_hash ((const unsigned char *) name->other->data, name->other->len, &nameHash, plContext), PKIX_HASHFAILED); break; case certRegisterID: PKIX_CHECK(PKIX_PL_Object_Hashcode ((PKIX_PL_Object *)name->oid, &nameHash, plContext), PKIX_OIDHASHCODEFAILED); break; case certOtherName: PKIX_NULLCHECK_ONE(name->OthName); PKIX_CHECK(pkix_hash ((const unsigned char *) name->OthName->oid.data, name->OthName->oid.len, &firstHash, plContext), PKIX_HASHFAILED); PKIX_CHECK(pkix_hash ((const unsigned char *) name->OthName->name.data, name->OthName->name.len, &secondHash, plContext), PKIX_HASHFAILED); nameHash = firstHash + secondHash; break; case certDirectoryName: PKIX_CHECK(PKIX_PL_Object_Hashcode ((PKIX_PL_Object *) name->directoryName, &nameHash, plContext), PKIX_X500NAMEHASHCODEFAILED); break; } *pHashcode = nameHash; cleanup: PKIX_RETURN(GENERALNAME); }
/* * FUNCTION: pkix_pl_GeneralName_ToString_Helper * DESCRIPTION: * * Helper function that creates a string representation of the GeneralName * pointed to by "name" and stores it at "pString" Different mechanisms are * used to create the string, depending on the type of the GeneralName. * * PARAMETERS * "name" * Address of GeneralName whose string representation is desired. * Must be non-NULL. * "pString" * Address where object pointer will be stored. 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 GeneralName Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ static PKIX_Error * pkix_pl_GeneralName_ToString_Helper( PKIX_PL_GeneralName *name, PKIX_PL_String **pString, void *plContext) { PKIX_PL_X500Name *pkixDN = NULL; PKIX_PL_OID *pkixOID = NULL; char *x400AsciiName = NULL; char *ediPartyName = NULL; char *asciiName = NULL; PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_ToString_Helper"); PKIX_NULLCHECK_TWO(name, pString); switch (name->type) { case certRFC822Name: case certDNSName: case certURI: /* * Note that we can't use PKIX_ESCASCII here because * name->other->data is not guaranteed to be null-terminated. */ PKIX_NULLCHECK_ONE(name->other); PKIX_CHECK(PKIX_PL_String_Create(PKIX_UTF8, (name->other)->data, (name->other)->len, pString, plContext), PKIX_STRINGCREATEFAILED); break; case certEDIPartyName: /* XXX print out the actual bytes */ ediPartyName = "EDIPartyName: <DER-encoded value>"; PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII, ediPartyName, 0, pString, plContext), PKIX_STRINGCREATEFAILED); break; case certX400Address: /* XXX print out the actual bytes */ x400AsciiName = "X400Address: <DER-encoded value>"; PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII, x400AsciiName, 0, pString, plContext), PKIX_STRINGCREATEFAILED); break; case certIPAddress: PKIX_CHECK(pkix_pl_ipAddrBytes2Ascii (name->other, &asciiName, plContext), PKIX_IPADDRBYTES2ASCIIFAILED); PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII, asciiName, 0, pString, plContext), PKIX_STRINGCREATEFAILED); break; case certOtherName: PKIX_NULLCHECK_ONE(name->OthName); /* we only print type-id - don't know how to print value */ /* XXX print out the bytes of the value */ PKIX_CHECK(pkix_pl_oidBytes2Ascii (&name->OthName->oid, &asciiName, plContext), PKIX_OIDBYTES2ASCIIFAILED); PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, asciiName, 0, pString, plContext), PKIX_STRINGCREATEFAILED); break; case certRegisterID: pkixOID = name->oid; PKIX_CHECK(PKIX_PL_Object_ToString ((PKIX_PL_Object *)pkixOID, pString, plContext), PKIX_OIDTOSTRINGFAILED); break; case certDirectoryName: pkixDN = name->directoryName; PKIX_CHECK(PKIX_PL_Object_ToString ((PKIX_PL_Object *)pkixDN, pString, plContext), PKIX_X500NAMETOSTRINGFAILED); break; default: PKIX_ERROR (PKIX_TOSTRINGFORTHISGENERALNAMETYPENOTSUPPORTED); } cleanup: PKIX_FREE(asciiName); PKIX_RETURN(GENERALNAME); }
/* * FUNCTION: pkix_List_MergeLists * DESCRIPTION: * * Creates a new list consisting of the items from "firstList", followed by * the items on "secondList", returns the new list at "pMergedList". If * both input lists are NULL or empty, the result is an empty list. If an error * occurs, the result is NULL. * * PARAMETERS: * "firstList" * Address of list to be merged from. May be NULL or empty. * "secondList" * Address of list to be merged from. May be NULL or empty. * "pMergedList" * Address where returned object is stored. * "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 List Error if the functions fails in a non-fatal way * Returns a Fatal Error if the function fails in an unrecoverable way */ PKIX_Error * pkix_List_MergeLists( PKIX_List *firstList, PKIX_List *secondList, PKIX_List **pMergedList, void *plContext) { PKIX_List *list = NULL; PKIX_PL_Object *item = NULL; PKIX_UInt32 numItems = 0; PKIX_UInt32 i; PKIX_ENTER(LIST, "pkix_List_MergeLists"); PKIX_NULLCHECK_ONE(pMergedList); *pMergedList = NULL; PKIX_CHECK(PKIX_List_Create(&list, plContext), PKIX_LISTCREATEFAILED); if (firstList != NULL) { PKIX_CHECK(PKIX_List_GetLength(firstList, &numItems, plContext), PKIX_LISTGETLENGTHFAILED); } for (i = 0; i < numItems; i++) { PKIX_CHECK(PKIX_List_GetItem(firstList, i, &item, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(PKIX_List_AppendItem(list, item, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(item); } numItems = 0; if (secondList != NULL) { PKIX_CHECK(PKIX_List_GetLength (secondList, &numItems, plContext), PKIX_LISTGETLENGTHFAILED); } for (i = 0; i < numItems; i++) { PKIX_CHECK(PKIX_List_GetItem (secondList, i, &item, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(PKIX_List_AppendItem (list, item, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(item); } *pMergedList = list; list = NULL; cleanup: PKIX_DECREF(list); PKIX_DECREF(item); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_pl_OcspResponse_Create * DESCRIPTION: * * This function transmits the OcspRequest pointed to by "request" and obtains * an OcspResponse, which it stores at "pOcspResponse". If the HTTPClient * supports non-blocking I/O this function may store a non-NULL value at * "pNBIOContext" (the WOULDBLOCK condition). In that case the caller should * make a subsequent call with the same value in "pNBIOContext" and * "pOcspResponse" to resume the operation. Additional WOULDBLOCK returns may * occur; the caller should persist until a return occurs with NULL stored at * "pNBIOContext". * * If a SEC_HttpClientFcn "responder" is supplied, it is used as the client * to which the OCSP query is sent. If none is supplied, the default responder * is used. * * If an OcspResponse_VerifyCallback "verifyFcn" is supplied, it is used to * verify the Cert received from the responder as the signer. If none is * supplied, the default verification function is used. * * The contents of "request" are ignored on calls subsequent to a WOULDBLOCK * return, and the caller is permitted to supply NULL. * * PARAMETERS * "request" * Address of the OcspRequest for which a response is desired. * "responder" * Address, if non-NULL, of the SEC_HttpClientFcn to be sent the OCSP * query. * "verifyFcn" * Address, if non-NULL, of the OcspResponse_VerifyCallback function to be * used to verify the Cert of the OCSP responder. * "pNBIOContext" * Address at which platform-dependent information is stored for handling * of non-blocking I/O. Must be non-NULL. * "pOcspResponse" * The address where the created OcspResponse is stored. 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 an OcspResponse Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_OcspResponse_Create( PKIX_PL_OcspRequest *request, void *responder, PKIX_PL_OcspResponse_VerifyCallback verifyFcn, void **pNBIOContext, PKIX_PL_OcspResponse **pResponse, void *plContext) { void *nbioContext = NULL; PKIX_PL_OcspResponse *ocspResponse = NULL; const SEC_HttpClientFcn *httpClient = NULL; const SEC_HttpClientFcnV1 *hcv1 = NULL; SECStatus rv = SECFailure; char *location = NULL; char *hostname = NULL; char *path = NULL; PRUint16 port = 0; SEC_HTTP_SERVER_SESSION serverSession = NULL; SEC_HTTP_REQUEST_SESSION requestSession = NULL; SECItem *encodedRequest = NULL; PRUint16 responseCode = 0; char *responseData = NULL; PRUint32 responseDataLen = 0; PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Create"); PKIX_NULLCHECK_TWO(pNBIOContext, pResponse); nbioContext = *pNBIOContext; *pNBIOContext = NULL; if (nbioContext != NULL) { ocspResponse = *pResponse; PKIX_NULLCHECK_ONE(ocspResponse); httpClient = ocspResponse->httpClient; serverSession = ocspResponse->serverSession; requestSession = ocspResponse->requestSession; PKIX_NULLCHECK_THREE(httpClient, serverSession, requestSession); } else { PKIX_NULLCHECK_ONE(request); PKIX_CHECK(pkix_pl_OcspRequest_GetEncoded (request, &encodedRequest, plContext), PKIX_OCSPREQUESTGETENCODEDFAILED); /* prepare initial message to HTTPClient */ /* Is there a default responder and is it enabled? */ if (!responder) { PKIX_PL_NSSCALLRV (OCSPRESPONSE, responder, (void *)SEC_GetRegisteredHttpClient, ()); } httpClient = (const SEC_HttpClientFcn *)responder; if (httpClient && (httpClient->version == 1)) { hcv1 = &(httpClient->fcnTable.ftable1); PKIX_CHECK(pkix_pl_OcspRequest_GetLocation (request, &location, plContext), PKIX_OCSPREQUESTGETLOCATIONFAILED); /* parse location -> hostname, port, path */ PKIX_PL_NSSCALLRV(OCSPRESPONSE, rv, CERT_ParseURL, (location, &hostname, &port, &path)); if ((hostname == NULL) || (path == NULL)) { PKIX_ERROR(PKIX_URLPARSINGFAILED); } PKIX_PL_NSSCALLRV (OCSPRESPONSE, rv, hcv1->createSessionFcn, (hostname, port, &serverSession)); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } PKIX_PL_NSSCALLRV (OCSPRESPONSE, rv, hcv1->createFcn, (serverSession, "http", path, "POST", PR_TicksPerSecond() * 60, &requestSession)); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } PKIX_PL_NSSCALLRV (OCSPRESPONSE, rv, hcv1->setPostDataFcn, (requestSession, (char *)encodedRequest->data, encodedRequest->len, "application/ocsp-request")); if (rv != SECSuccess) { PKIX_ERROR(PKIX_OCSPSERVERERROR); } /* create a PKIX_PL_OcspResponse object */ PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_OCSPRESPONSE_TYPE, sizeof (PKIX_PL_OcspResponse), (PKIX_PL_Object **)&ocspResponse, plContext), PKIX_COULDNOTCREATEOBJECT); PKIX_INCREF(request); ocspResponse->request = request; ocspResponse->httpClient = httpClient; ocspResponse->serverSession = serverSession; ocspResponse->requestSession = requestSession; ocspResponse->verifyFcn = verifyFcn; ocspResponse->handle = CERT_GetDefaultCertDB(); ocspResponse->encodedResponse = NULL; ocspResponse->arena = NULL; ocspResponse->producedAt = 0; ocspResponse->producedAtDate = NULL; ocspResponse->pkixSignerCert = NULL; ocspResponse->nssOCSPResponse = NULL; ocspResponse->signerCert = NULL; } }
/* * FUNCTION: PKIX_RevocationChecker_CreateAndAddMethod */ PKIX_Error * PKIX_RevocationChecker_CreateAndAddMethod( PKIX_RevocationChecker *revChecker, PKIX_ProcessingParams *params, PKIX_RevocationMethodType methodType, PKIX_UInt32 flags, PKIX_UInt32 priority, PKIX_PL_VerifyCallback verificationFn, PKIX_Boolean isLeafMethod, void *plContext) { PKIX_List **methodList = NULL; PKIX_List *unsortedList = NULL; PKIX_List *certStores = NULL; pkix_RevocationMethod *method = NULL; pkix_LocalRevocationCheckFn *localRevChecker = NULL; pkix_ExternalRevocationCheckFn *externRevChecker = NULL; PKIX_UInt32 miFlags; PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_CreateAndAddMethod"); PKIX_NULLCHECK_ONE(revChecker); /* If the caller has said "Either one is sufficient, then don't let the * absence of any one method's info lead to an overall failure. */ miFlags = isLeafMethod ? revChecker->leafMethodListFlags : revChecker->chainMethodListFlags; if (miFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE) flags &= ~PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO; switch (methodType) { case PKIX_RevocationMethod_CRL: localRevChecker = pkix_CrlChecker_CheckLocal; externRevChecker = pkix_CrlChecker_CheckExternal; PKIX_CHECK( PKIX_ProcessingParams_GetCertStores(params, &certStores, plContext), PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); PKIX_CHECK( pkix_CrlChecker_Create(methodType, flags, priority, localRevChecker, externRevChecker, certStores, verificationFn, &method, plContext), PKIX_COULDNOTCREATECRLCHECKEROBJECT); break; case PKIX_RevocationMethod_OCSP: localRevChecker = pkix_OcspChecker_CheckLocal; externRevChecker = pkix_OcspChecker_CheckExternal; PKIX_CHECK( pkix_OcspChecker_Create(methodType, flags, priority, localRevChecker, externRevChecker, verificationFn, &method, plContext), PKIX_COULDNOTCREATEOCSPCHECKEROBJECT); break; default: PKIX_ERROR(PKIX_INVALIDREVOCATIONMETHOD); } if (isLeafMethod) { methodList = &revChecker->leafMethodList; } else { methodList = &revChecker->chainMethodList; } if (*methodList == NULL) { PKIX_CHECK( PKIX_List_Create(methodList, plContext), PKIX_LISTCREATEFAILED); } unsortedList = *methodList; PKIX_CHECK( PKIX_List_AppendItem(unsortedList, (PKIX_PL_Object*)method, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_CHECK( pkix_List_BubbleSort(unsortedList, pkix_RevocationChecker_SortComparator, methodList, plContext), PKIX_LISTBUBBLESORTFAILED); cleanup: PKIX_DECREF(method); PKIX_DECREF(unsortedList); PKIX_DECREF(certStores); PKIX_RETURN(REVOCATIONCHECKER); }
/* * FUNCTION: pkix_pl_HttpCertStore_ProcessCrlResponse * DESCRIPTION: * * This function verifies that the response code pointed to by "responseCode" * and the content type pointed to by "responseContentType" are as expected, * and then decodes the data pointed to by "responseData", of length * "responseDataLen", into a List of Crls, possibly empty, which is returned * at "pCrlList". * * PARAMETERS: * "responseCode" * The value of the HTTP response code. * "responseContentType" * The address of the Content-type string. Must be non-NULL. * "responseData" * The address of the message data. Must be non-NULL. * "responseDataLen" * The length of the message data. * "pCrlList" * The address of the List that is created. 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 HttpCertStore Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_HttpCertStore_ProcessCrlResponse( PRUint16 responseCode, const char *responseContentType, const char *responseData, PRUint32 responseDataLen, PKIX_List **pCrlList, void *plContext) { PRArenaPool *arena = NULL; SECItem *encodedResponse = NULL; PRInt16 compareVal = 0; PKIX_List *crls = NULL; PKIX_ENTER (HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStore_ProcessCrlResponse"); PKIX_NULLCHECK_ONE(pCrlList); if (responseCode != 200) { PKIX_ERROR(PKIX_BADHTTPRESPONSE); } /* check that response type is application/pkix-crl */ if (responseContentType == NULL) { PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE); } compareVal = PORT_Strcasecmp(responseContentType, "application/pkix-crl"); if (compareVal != 0) { PKIX_ERROR(PKIX_CONTENTTYPENOTPKIXCRL); } /* Make a SECItem of the response data */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } if (responseData == NULL) { PKIX_ERROR(PKIX_NORESPONSEDATAINHTTPRESPONSE); } encodedResponse = SECITEM_AllocItem(arena, NULL, responseDataLen); if (encodedResponse == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } PORT_Memcpy(encodedResponse->data, responseData, responseDataLen); PKIX_CHECK(PKIX_List_Create(&crls, plContext), PKIX_LISTCREATEFAILED); PKIX_CHECK(pkix_pl_CRL_CreateToList (encodedResponse, crls, plContext), PKIX_CRLCREATETOLISTFAILED); *pCrlList = crls; cleanup: if (PKIX_ERROR_RECEIVED) { PKIX_DECREF(crls); } if (arena != NULL) { PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena, (arena, PR_FALSE)); } PKIX_RETURN(HTTPCERTSTORECONTEXT); }