| Index: nss/mozilla/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c
|
| ===================================================================
|
| --- nss/mozilla/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c (revision 0)
|
| +++ nss/mozilla/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c (revision 0)
|
| @@ -0,0 +1,502 @@
|
| +/* ***** BEGIN LICENSE BLOCK *****
|
| + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
| + *
|
| + * The contents of this file are subject to the Mozilla Public License Version
|
| + * 1.1 (the "License"); you may not use this file except in compliance with
|
| + * the License. You may obtain a copy of the License at
|
| + * http://www.mozilla.org/MPL/
|
| + *
|
| + * Software distributed under the License is distributed on an "AS IS" basis,
|
| + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
| + * for the specific language governing rights and limitations under the
|
| + * License.
|
| + *
|
| + * The Original Code is the PKIX-C library.
|
| + *
|
| + * The Initial Developer of the Original Code is
|
| + * Sun Microsystems, Inc.
|
| + * Portions created by the Initial Developer are
|
| + * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
|
| + *
|
| + * Contributor(s):
|
| + * Sun Microsystems, Inc.
|
| + *
|
| + * Alternatively, the contents of this file may be used under the terms of
|
| + * either the GNU General Public License Version 2 or later (the "GPL"), or
|
| + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
| + * in which case the provisions of the GPL or the LGPL are applicable instead
|
| + * of those above. If you wish to allow use of your version of this file only
|
| + * under the terms of either the GPL or the LGPL, and not to allow others to
|
| + * use your version of this file under the terms of the MPL, indicate your
|
| + * decision by deleting the provisions above and replace them with the notice
|
| + * and other provisions required by the GPL or the LGPL. If you do not delete
|
| + * the provisions above, a recipient may use your version of this file under
|
| + * the terms of any one of the MPL, the GPL or the LGPL.
|
| + *
|
| + * ***** END LICENSE BLOCK ***** */
|
| +/*
|
| + * pkix_revocationchecker.c
|
| + *
|
| + * RevocationChecker Object Functions
|
| + *
|
| + */
|
| +
|
| +#include "pkix_revocationchecker.h"
|
| +#include "pkix_tools.h"
|
| +
|
| +/* --Private-Functions-------------------------------------------- */
|
| +
|
| +/*
|
| + * 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_RevocationChecker_Duplicate
|
| + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
|
| + */
|
| +static PKIX_Error *
|
| +pkix_RevocationChecker_Duplicate(
|
| + PKIX_PL_Object *object,
|
| + PKIX_PL_Object **pNewObject,
|
| + void *plContext)
|
| +{
|
| + PKIX_RevocationChecker *checker = NULL;
|
| + PKIX_RevocationChecker *checkerDuplicate = NULL;
|
| + PKIX_List *dupLeafList = NULL;
|
| + PKIX_List *dupChainList = NULL;
|
| +
|
| + PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_Duplicate");
|
| + PKIX_NULLCHECK_TWO(object, pNewObject);
|
| +
|
| + PKIX_CHECK(pkix_CheckType
|
| + (object, PKIX_REVOCATIONCHECKER_TYPE, plContext),
|
| + PKIX_OBJECTNOTCERTCHAINCHECKER);
|
| +
|
| + checker = (PKIX_RevocationChecker *)object;
|
| +
|
| + if (checker->leafMethodList){
|
| + PKIX_CHECK(PKIX_PL_Object_Duplicate
|
| + ((PKIX_PL_Object *)checker->leafMethodList,
|
| + (PKIX_PL_Object **)&dupLeafList,
|
| + plContext),
|
| + PKIX_OBJECTDUPLICATEFAILED);
|
| + }
|
| + if (checker->chainMethodList){
|
| + PKIX_CHECK(PKIX_PL_Object_Duplicate
|
| + ((PKIX_PL_Object *)checker->chainMethodList,
|
| + (PKIX_PL_Object **)&dupChainList,
|
| + plContext),
|
| + PKIX_OBJECTDUPLICATEFAILED);
|
| + }
|
| +
|
| + PKIX_CHECK(
|
| + PKIX_RevocationChecker_Create(checker->leafMethodListFlags,
|
| + checker->chainMethodListFlags,
|
| + &checkerDuplicate,
|
| + plContext),
|
| + PKIX_REVOCATIONCHECKERCREATEFAILED);
|
| +
|
| + checkerDuplicate->leafMethodList = dupLeafList;
|
| + checkerDuplicate->chainMethodList = dupChainList;
|
| + dupLeafList = NULL;
|
| + dupChainList = NULL;
|
| +
|
| + *pNewObject = (PKIX_PL_Object *)checkerDuplicate;
|
| +
|
| +cleanup:
|
| + PKIX_DECREF(dupLeafList);
|
| + PKIX_DECREF(dupChainList);
|
| +
|
| + PKIX_RETURN(REVOCATIONCHECKER);
|
| +}
|
| +
|
| +/*
|
| + * FUNCTION: pkix_RevocationChecker_RegisterSelf
|
| + * DESCRIPTION:
|
| + * Registers PKIX_REVOCATIONCHECKER_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_RevocationChecker_RegisterSelf(void *plContext)
|
| +{
|
| + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
|
| + pkix_ClassTable_Entry entry;
|
| +
|
| + PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_RegisterSelf");
|
| +
|
| + entry.description = "RevocationChecker";
|
| + entry.objCounter = 0;
|
| + entry.typeObjectSize = sizeof(PKIX_RevocationChecker);
|
| + entry.destructor = pkix_RevocationChecker_Destroy;
|
| + entry.equalsFunction = NULL;
|
| + entry.hashcodeFunction = NULL;
|
| + entry.toStringFunction = NULL;
|
| + entry.comparator = NULL;
|
| + entry.duplicateFunction = pkix_RevocationChecker_Duplicate;
|
| +
|
| + systemClasses[PKIX_REVOCATIONCHECKER_TYPE] = entry;
|
| +
|
| + PKIX_RETURN(REVOCATIONCHECKER);
|
| +}
|
| +
|
| +/* Sort methods by theirs priorities */
|
| +static PKIX_Error *
|
| +pkix_RevocationChecker_SortComparator(
|
| + PKIX_PL_Object *obj1,
|
| + PKIX_PL_Object *obj2,
|
| + PKIX_Int32 *pResult,
|
| + void *plContext)
|
| +{
|
| + pkix_RevocationMethod *method1 = NULL, *method2 = NULL;
|
| +
|
| + PKIX_ENTER(BUILD, "pkix_RevocationChecker_SortComparator");
|
| +
|
| + method1 = (pkix_RevocationMethod *)obj1;
|
| + method2 = (pkix_RevocationMethod *)obj2;
|
| +
|
| + *pResult = (method1->priority > method2->priority);
|
| +
|
| + PKIX_RETURN(BUILD);
|
| +}
|
| +
|
| +
|
| +/* --Public-Functions--------------------------------------------- */
|
| +
|
| +
|
| +/*
|
| + * FUNCTION: PKIX_RevocationChecker_Create (see comments in pkix_revchecker.h)
|
| + */
|
| +PKIX_Error *
|
| +PKIX_RevocationChecker_Create(
|
| + PKIX_UInt32 leafMethodListFlags,
|
| + PKIX_UInt32 chainMethodListFlags,
|
| + PKIX_RevocationChecker **pChecker,
|
| + void *plContext)
|
| +{
|
| + PKIX_RevocationChecker *checker = NULL;
|
| +
|
| + PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_Create");
|
| + PKIX_NULLCHECK_ONE(pChecker);
|
| +
|
| + PKIX_CHECK(
|
| + PKIX_PL_Object_Alloc(PKIX_REVOCATIONCHECKER_TYPE,
|
| + sizeof (PKIX_RevocationChecker),
|
| + (PKIX_PL_Object **)&checker,
|
| + plContext),
|
| + PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
|
| +
|
| + checker->leafMethodListFlags = leafMethodListFlags;
|
| + checker->chainMethodListFlags = chainMethodListFlags;
|
| + checker->leafMethodList = NULL;
|
| + checker->chainMethodList = NULL;
|
| +
|
| + *pChecker = checker;
|
| + checker = NULL;
|
| +
|
| +cleanup:
|
| + PKIX_DECREF(checker);
|
| +
|
| + PKIX_RETURN(REVOCATIONCHECKER);
|
| +}
|
| +
|
| +/*
|
| + * 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_RevocationChecker_Check
|
| + */
|
| +PKIX_Error *
|
| +PKIX_RevocationChecker_Check(
|
| + PKIX_PL_Cert *cert,
|
| + PKIX_PL_Cert *issuer,
|
| + PKIX_RevocationChecker *revChecker,
|
| + PKIX_ProcessingParams *procParams,
|
| + PKIX_Boolean chainVerificationState,
|
| + PKIX_Boolean testingLeafCert,
|
| + PKIX_RevocationStatus *pRevStatus,
|
| + PKIX_UInt32 *pReasonCode,
|
| + void **pNbioContext,
|
| + void *plContext)
|
| +{
|
| + PKIX_RevocationStatus overallStatus = PKIX_RevStatus_NoInfo;
|
| + PKIX_RevocationStatus methodStatus[PKIX_RevocationMethod_MAX];
|
| + PKIX_Boolean onlyUseRemoteMethods = PKIX_FALSE;
|
| + PKIX_UInt32 revFlags = 0;
|
| + PKIX_List *revList = NULL;
|
| + PKIX_PL_Date *date = NULL;
|
| + pkix_RevocationMethod *method = NULL;
|
| + void *nbioContext;
|
| + int tries;
|
| +
|
| + PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_Check");
|
| + PKIX_NULLCHECK_TWO(revChecker, procParams);
|
| +
|
| + nbioContext = *pNbioContext;
|
| + *pNbioContext = NULL;
|
| +
|
| + if (testingLeafCert) {
|
| + revList = revChecker->leafMethodList;
|
| + revFlags = revChecker->leafMethodListFlags;
|
| + } else {
|
| + revList = revChecker->chainMethodList;
|
| + revFlags = revChecker->chainMethodListFlags;
|
| + }
|
| + if (!revList) {
|
| + /* Return NoInfo status */
|
| + goto cleanup;
|
| + }
|
| +
|
| + PORT_Memset(methodStatus, PKIX_RevStatus_NoInfo,
|
| + sizeof(PKIX_RevocationStatus) * PKIX_RevocationMethod_MAX);
|
| +
|
| + date = procParams->date;
|
| +
|
| + /* Need to have two loops if we testing all local info first:
|
| + * first we are going to test all local(cached) info
|
| + * second, all remote info(fetching) */
|
| + for (tries = 0;tries < 2;tries++) {
|
| + int methodNum = 0;
|
| + for (;methodNum < revList->length;methodNum++) {
|
| + PKIX_UInt32 methodFlags = 0;
|
| +
|
| + PKIX_DECREF(method);
|
| + pkixErrorResult = PKIX_List_GetItem(revList, methodNum,
|
| + (PKIX_PL_Object**)&method,
|
| + plContext);
|
| + if (pkixErrorResult) {
|
| + /* Return error. Should not shappen in normal conditions. */
|
| + goto cleanup;
|
| + }
|
| + methodFlags = method->flags;
|
| + if (!(methodFlags & PKIX_REV_M_TEST_USING_THIS_METHOD)) {
|
| + /* Will not check with this method. Skipping... */
|
| + continue;
|
| + }
|
| + if (!onlyUseRemoteMethods &&
|
| + methodStatus[methodNum] == PKIX_RevStatus_NoInfo) {
|
| + PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
|
| +
|
| + pkixErrorResult =
|
| + (*method->localRevChecker)(cert, issuer, date,
|
| + method, procParams,
|
| + methodFlags,
|
| + chainVerificationState,
|
| + &revStatus,
|
| + pReasonCode, plContext);
|
| + methodStatus[methodNum] = revStatus;
|
| + if (revStatus == PKIX_RevStatus_Revoked) {
|
| + /* if error was generated use it as final error. */
|
| + overallStatus = PKIX_RevStatus_Revoked;
|
| + goto cleanup;
|
| + }
|
| + if (pkixErrorResult) {
|
| + /* Disregard errors. Only returned revStatus matters. */
|
| + PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
|
| + plContext);
|
| + pkixErrorResult = NULL;
|
| + }
|
| + }
|
| + if ((!(revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST) ||
|
| + onlyUseRemoteMethods) &&
|
| + chainVerificationState &&
|
| + methodStatus[methodNum] == PKIX_RevStatus_NoInfo) {
|
| + if (!(methodFlags & PKIX_REV_M_FORBID_NETWORK_FETCHING)) {
|
| + PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
|
| + pkixErrorResult =
|
| + (*method->externalRevChecker)(cert, issuer, date,
|
| + method,
|
| + procParams, methodFlags,
|
| + &revStatus, pReasonCode,
|
| + &nbioContext, plContext);
|
| + methodStatus[methodNum] = revStatus;
|
| + if (revStatus == PKIX_RevStatus_Revoked) {
|
| + /* if error was generated use it as final error. */
|
| + overallStatus = PKIX_RevStatus_Revoked;
|
| + goto cleanup;
|
| + }
|
| + if (pkixErrorResult) {
|
| + /* Disregard errors. Only returned revStatus matters. */
|
| + PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
|
| + plContext);
|
| + pkixErrorResult = NULL;
|
| + }
|
| + } else if (methodFlags &
|
| + PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
|
| + /* Info is not in the local cache. Network fetching is not
|
| + * allowed. If need to fail on missing fresh info for the
|
| + * the method, then we should fail right here.*/
|
| + overallStatus = PKIX_RevStatus_Revoked;
|
| + goto cleanup;
|
| + }
|
| + }
|
| + /* If success and we should not check the next method, then
|
| + * return a success. */
|
| + if (methodStatus[methodNum] == PKIX_RevStatus_Success &&
|
| + !(methodFlags & PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO)) {
|
| + overallStatus = PKIX_RevStatus_Success;
|
| + goto cleanup;
|
| + }
|
| + } /* inner loop */
|
| + if (!onlyUseRemoteMethods &&
|
| + revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST &&
|
| + chainVerificationState) {
|
| + onlyUseRemoteMethods = PKIX_TRUE;
|
| + continue;
|
| + }
|
| + break;
|
| + } /* outer loop */
|
| +
|
| + if (overallStatus == PKIX_RevStatus_NoInfo &&
|
| + chainVerificationState) {
|
| + /* The following check makes sence only for chain
|
| + * validation step, sinse we do not fetch info while
|
| + * in the process of finding trusted anchor.
|
| + * For chain building step it is enough to know, that
|
| + * the cert was not directly revoked by any of the
|
| + * methods. */
|
| +
|
| + /* Still have no info. But one of the method could
|
| + * have returned success status(possible if CONTINUE
|
| + * TESTING ON FRESH INFO flag was used).
|
| + * If any of the methods have returned Success status,
|
| + * the overallStatus should be success. */
|
| + int methodNum = 0;
|
| + for (;methodNum < PKIX_RevocationMethod_MAX;methodNum++) {
|
| + if (methodStatus[methodNum] == PKIX_RevStatus_Success) {
|
| + overallStatus = PKIX_RevStatus_Success;
|
| + goto cleanup;
|
| + }
|
| + }
|
| + if (revFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE) {
|
| + overallStatus = PKIX_RevStatus_Revoked;
|
| + }
|
| + }
|
| +
|
| +cleanup:
|
| + *pRevStatus = overallStatus;
|
| + PKIX_DECREF(method);
|
| +
|
| + PKIX_RETURN(REVOCATIONCHECKER);
|
| +}
|
| +
|
|
|
| Property changes on: nss/mozilla/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c
|
| ___________________________________________________________________
|
| Added: svn:executable
|
| + *
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|