コード例 #1
0
/*
 * FUNCTION: pkix_UnlockObject
 * DESCRIPTION:
 *
 *  Unlocks the object pointed to by "object".
 *
 * PARAMETERS:
 *  "object"
 *      Address of Object. 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 Fatal Error if the function fails in an unrecoverable way.
 */
PKIX_Error *
pkix_UnlockObject(
        PKIX_PL_Object *object,
        void *plContext)
{
        PKIX_PL_Object *objectHeader;
        PRStatus result;

        PKIX_ENTER(OBJECT, "pkix_UnlockObject");
        PKIX_NULLCHECK_ONE(object);

        if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) {
                goto cleanup;
        }

        PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
        /* The header is sizeof(PKIX_PL_Object) before the object pointer */

        objectHeader = object-1;

        PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
        result = PR_Unlock(objectHeader->lock);

        if (result == PR_FAILURE) {
                PKIX_OBJECT_DEBUG("\tPR_Unlock failed.).\n");
                PKIX_ERROR_FATAL(PKIX_ERRORUNLOCKINGOBJECT);
        }

cleanup:

        PKIX_RETURN(OBJECT);
}
コード例 #2
0
/*
 * FUNCTION: pkix_pl_CRL_GetSignatureAlgId
 *
 * DESCRIPTION:
 *  Retrieves a pointer to the OID that represents the signature algorithm of
 *  the CRL pointed to by "crl" and stores it at "pSignatureAlgId".
 *
 *  AlgorithmIdentifier  ::=  SEQUENCE  {
 *      algorithm               OBJECT IDENTIFIER,
 *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
 *
 * PARAMETERS:
 *  "crl"
 *      Address of CRL whose signature algorithm OID is to be stored.
 *      Must be non-NULL.
 *  "pSignatureAlgId"
 *      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 CRL 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_CRL_GetSignatureAlgId(
    PKIX_PL_CRL *crl,
    PKIX_PL_OID **pSignatureAlgId,
    void *plContext)
{
    CERTCrl *nssCrl = NULL;
    PKIX_PL_OID *signatureAlgId = NULL;
    SECAlgorithmID algorithm;
    SECItem algBytes;
    char *asciiOID = NULL;

    PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId");
    PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId);

    /* if we don't have a cached copy from before, we create one */
    if (crl->signatureAlgId == NULL) {

        PKIX_OBJECT_LOCK(crl);

        if (crl->signatureAlgId == NULL) {

            nssCrl = &(crl->nssSignedCrl->crl);
            algorithm = nssCrl->signatureAlg;
            algBytes = algorithm.algorithm;

            PKIX_NULLCHECK_ONE(algBytes.data);
            if (algBytes.len == 0) {
                PKIX_ERROR_FATAL(PKIX_OIDBYTESLENGTH0);
            }

            PKIX_CHECK(pkix_pl_oidBytes2Ascii
                       (&algBytes, &asciiOID, plContext),
                       PKIX_OIDBYTES2ASCIIFAILED);

            PKIX_CHECK(PKIX_PL_OID_Create
                       (asciiOID, &signatureAlgId, plContext),
                       PKIX_OIDCREATEFAILED);

            /* save a cached copy in case it is asked for again */
            crl->signatureAlgId = signatureAlgId;
        }

        PKIX_OBJECT_UNLOCK(crl);

    }

    PKIX_INCREF(crl->signatureAlgId);
    *pSignatureAlgId = crl->signatureAlgId;

cleanup:

    PKIX_FREE(asciiOID);

    PKIX_RETURN(CRL);
}
コード例 #3
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h)
 */
PKIX_Error *
PKIX_PL_Object_IsTypeRegistered(
        PKIX_UInt32 objType,
        PKIX_Boolean *pBool,
        void *plContext)
{
#ifdef PKIX_USER_OBJECT_TYPE
        pkix_ClassTable_Entry *ctEntry = NULL;
#endif

        PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered");
        PKIX_NULLCHECK_ONE(pBool);

        /* first, we handle the system types */
        if (objType < PKIX_NUMTYPES) {
                *pBool = PKIX_TRUE;
                goto cleanup;
        }

#ifndef PKIX_USER_OBJECT_TYPE
        PORT_Assert (0);
        pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
        pkixErrorClass = PKIX_FATAL_ERROR;
#else
        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);
        }

        *pBool = (ctEntry != NULL);
#endif /* PKIX_USER_OBJECT_TYPE */

cleanup:

        PKIX_RETURN(OBJECT);
}
コード例 #4
0
/*
 * FUNCTION: pkix_pl_ipAddrBytes2Ascii
 * DESCRIPTION:
 *
 *  Converts the DER encoding of an IPAddress pointed to by "secItem" to an
 *  ASCII representation and stores the result at "pAscii". The ASCII
 *  representation is guaranteed to end with a NUL character. The input
 *  SECItem must contain non-NULL data and must have a positive length.
 *
 *  The return value "pAscii" is not reference-counted and will need to
 *  be freed with PKIX_PL_Free.
 *  XXX this function assumes that IPv4 addresses are being used
 *  XXX what about IPv6? can NSS tell the difference
 *
 * PARAMETERS
 *  "secItem"
 *      Address of SECItem which contains bytes and length of DER encoding.
 *      Must be non-NULL.
 *  "pAscii"
 *      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 an Object 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_ipAddrBytes2Ascii(
        SECItem *secItem,
        char **pAscii,
        void *plContext)
{
        char *data = NULL;
        PKIX_UInt32 *tokens = NULL;
        PKIX_UInt32 numTokens = 0;
        PKIX_UInt32 i = 0;
        char *asciiString = NULL;

        PKIX_ENTER(OBJECT, "pkix_pl_ipAddrBytes2Ascii");
        PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data);

        if (secItem->len == 0) {
                PKIX_ERROR_FATAL(PKIX_IPADDRBYTES2ASCIIDATALENGTHZERO);
        }

        data = (char *)(secItem->data);
        numTokens = secItem->len;

        /* allocate space for array of integers */
        PKIX_CHECK(PKIX_PL_Malloc
                    (numTokens * sizeof (PKIX_UInt32),
                    (void **)&tokens,
                    plContext),
                    PKIX_MALLOCFAILED);

        /* populate array of integers */
        for (i = 0; i < numTokens; i++){
                tokens[i] = data[i];
        }

        /* convert array of integers to ASCII */
        PKIX_CHECK(pkix_pl_helperBytes2Ascii
                    (tokens, numTokens, &asciiString, plContext),
                    PKIX_HELPERBYTES2ASCIIFAILED);

        *pAscii = asciiString;

cleanup:

        PKIX_FREE(tokens);

        PKIX_RETURN(OBJECT);
}
コード例 #5
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * FUNCTION: pkix_Destroy_Object
 * DESCRIPTION:
 *
 *  Destroys and deallocates Object pointed to by "object". The caller is
 *  assumed to hold the Object's lock, which is acquired in
 *  PKIX_PL_Object_DecRef().
 *
 * PARAMETERS:
 *  "object"
 *      Address of Object to destroy. 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 Fatal Error if the function fails in an unrecoverable way.
 */
static PKIX_Error *
pkix_pl_Object_Destroy(
        PKIX_PL_Object *object,
        void *plContext)
{
        PKIX_PL_Object *objectHeader = NULL;

        PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy");
        PKIX_NULLCHECK_ONE(object);

#ifdef PKIX_OBJECT_LEAK_TEST
        PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
#else
        PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
#endif /* PKIX_OBJECT_LEAK_TEST */

        /* Attempt to delete an object still being used */
        if (objectHeader->references != 0) {
                PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED);
        }

        PKIX_DECREF(objectHeader->stringRep);

        /* Destroy this object's lock */
        PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n");
        PR_DestroyLock(objectHeader->lock);
        objectHeader->lock = NULL;
        object = NULL;

        objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED;

#ifdef PKIX_OBJECT_LEAK_TEST
        memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSize);
#endif

        PKIX_FREE(objectHeader);

cleanup:
#ifdef PKIX_OBJECT_LEAK_TEST
fatal:
#endif

        PKIX_RETURN(OBJECT);
}
コード例 #6
0
/*
 * FUNCTION: pkix_pl_LdapCertStore_GetCert
 *  (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
 */
PKIX_Error *
pkix_pl_LdapCertStore_GetCert(
        PKIX_CertStore *store,
        PKIX_CertSelector *selector,
        PKIX_VerifyNode *verifyNode,
        void **pNBIOContext,
        PKIX_List **pCertList,
        void *plContext)
{
        PRArenaPool *requestArena = NULL;
        LDAPRequestParams requestParams;
        void *pollDesc = NULL;
        PKIX_Int32 minPathLen = 0;
        PKIX_Boolean cacheFlag = PKIX_FALSE;
        PKIX_ComCertSelParams *params = NULL;
        PKIX_PL_LdapCertStoreContext *lcs = NULL;
        PKIX_List *responses = NULL;
        PKIX_List *unfilteredCerts = NULL;
        PKIX_List *filteredCerts = NULL;
        PKIX_PL_X500Name *subjectName = 0;

        PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCert");
        PKIX_NULLCHECK_THREE(store, selector, pCertList);

        requestParams.baseObject = "c=US";
        requestParams.scope = WHOLE_SUBTREE;
        requestParams.derefAliases = NEVER_DEREF;
        requestParams.sizeLimit = 0;
        requestParams.timeLimit = 0;

        /* Prepare elements for request filter */

        /*
         * Get a short-lived arena. We'll be done with this space once
         * the request is encoded.
         */
        requestArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (!requestArena) {
                PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
        }

        PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
                (selector, &params, plContext),
                PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED);

        /*
         * If we have the subject name for the desired subject,
         * ask the server for Certs with that subject.
         */
        PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
                (params, &subjectName, plContext),
                PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);

        PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints
                (params, &minPathLen, plContext),
                PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED);

        if (subjectName) {
                PKIX_CHECK(pkix_pl_LdapCertStore_MakeNameAVAList
                        (requestArena,
                        subjectName,
                        &(requestParams.nc),
                        plContext),
                        PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED);

                if (*requestParams.nc == NULL) {
                        /*
                         * The subjectName may not include any components
                         * that we know how to encode. We do not return
                         * an error, because the caller did not necessarily
                         * do anything wrong, but we return an empty List.
                         */
                        PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
                                (requestArena, PR_FALSE));

                        PKIX_CHECK(PKIX_List_Create(&filteredCerts, plContext),
                                PKIX_LISTCREATEFAILED);

                        PKIX_CHECK(PKIX_List_SetImmutable
                                (filteredCerts, plContext),
                                PKIX_LISTSETIMMUTABLEFAILED);

                        *pNBIOContext = NULL;
                        *pCertList = filteredCerts;
                        filteredCerts = NULL;
                        goto cleanup;
                }
        } else {
                PKIX_ERROR(PKIX_INSUFFICIENTCRITERIAFORCERTQUERY);
        }

        /* Prepare attribute field of request */

        requestParams.attributes = 0;

        if (minPathLen < 0) {
                requestParams.attributes |= LDAPATTR_USERCERT;
        }

        if (minPathLen > -2) {
                requestParams.attributes |=
                        LDAPATTR_CACERT | LDAPATTR_CROSSPAIRCERT;
        }

        /* All request fields are done */

        PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
                (store, (PKIX_PL_Object **)&lcs, plContext),
                PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);

        PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
                ((PKIX_PL_LdapClient *)lcs,
                &requestParams,
                &pollDesc,
                &responses,
                plContext),
                PKIX_LDAPCLIENTINITIATEREQUESTFAILED);

        PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList
                (requestParams.nc, plContext),
                PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED);

        if (requestArena) {
                PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
                        (requestArena, PR_FALSE));
                requestArena = NULL;
        }

        if (pollDesc != NULL) {
                /* client is waiting for non-blocking I/O to complete */
                *pNBIOContext = (void *)pollDesc;
                *pCertList = NULL;
                goto cleanup;
        }
        /* LdapClient has given us a response! */

        if (responses) {
                PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
                        (store, &cacheFlag, plContext),
                        PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);

                PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
                        (responses, &unfilteredCerts, plContext),
                        PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);

                PKIX_CHECK(pkix_CertSelector_Select
                        (selector, unfilteredCerts, &filteredCerts, plContext),
                        PKIX_CERTSELECTORSELECTFAILED);
        }

        *pNBIOContext = NULL;
        *pCertList = filteredCerts;
        filteredCerts = NULL;

cleanup:

        PKIX_DECREF(params);
        PKIX_DECREF(subjectName);
        PKIX_DECREF(responses);
        PKIX_DECREF(unfilteredCerts);
        PKIX_DECREF(filteredCerts);
        PKIX_DECREF(lcs);

        PKIX_RETURN(CERTSTORE);
}
コード例 #7
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h)
 */
PKIX_Error *
PKIX_PL_Object_Hashcode(
        PKIX_PL_Object *object,
        PKIX_UInt32 *pValue,
        void *plContext)
{
        PKIX_PL_Object *objectHeader = NULL;
        PKIX_PL_HashcodeCallback func = NULL;
        pkix_ClassTable_Entry entry;
        PKIX_UInt32 objectHash;

        PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode");
        PKIX_NULLCHECK_TWO(object, pValue);

        /* Shift pointer from user data to object header */
        PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);

        /* if we don't have a cached copy from before, we create one */
        if (!objectHeader->hashcodeCached){

                PKIX_UInt32 objType = objectHeader->type;

                /* first, special handling for system types */
                if (objType >= PKIX_NUMTYPES){
#ifdef PKIX_USER_OBJECT_TYPE            
                        pkix_ClassTable_Entry *ctEntry = NULL;

                        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_ERRORGETTINGCLASSTABLEENTRY);
                        }

                        if ((ctEntry == NULL) ||
                            (ctEntry->hashcodeFunction == NULL)) {
                                PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
                        }

                        func = ctEntry->hashcodeFunction;
#else
                        PORT_Assert (0);
                        pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
                        pkixErrorClass = PKIX_FATAL_ERROR;
                        goto cleanup;
#endif /* PKIX_USER_OBJECT_TYPE */
                } else {
                        entry = systemClasses[objType];
                        func = entry.hashcodeFunction;
                        if (func == NULL){
                                func = pkix_pl_Object_Hashcode_Default;
                        }
                }

                PKIX_CHECK(func(object, &objectHash, plContext),
                            PKIX_OBJECTSPECIFICFUNCTIONFAILED);

                if (!objectHeader->hashcodeCached){

                        PKIX_CHECK(pkix_LockObject(object, plContext),
                                    PKIX_ERRORLOCKINGOBJECT);

                        if (!objectHeader->hashcodeCached){
                                /* save cached copy in case we need it again */
                                objectHeader->hashcode = objectHash;
                                objectHeader->hashcodeCached = PKIX_TRUE;
                        }

                        PKIX_CHECK(pkix_UnlockObject(object, plContext),
                                    PKIX_ERRORUNLOCKINGOBJECT);
                }
        }

        *pValue = objectHeader->hashcode;

cleanup:

        PKIX_RETURN(OBJECT);
}
コード例 #8
0
/*
 * FUNCTION: pkix_pl_oidBytes2Ascii
 * DESCRIPTION:
 *
 *  Converts the DER encoding of an OID pointed to by "secItem" to an ASCII
 *  representation and stores it at "pAscii". The ASCII representation is
 *  guaranteed to end with a NUL character. The input SECItem must contain
 *  non-NULL data and must have a positive length.
 *
 *  Example: the six bytes {2a 86 48 86 f7 0d} represent the
 *  four integer tokens {1, 2, 840, 113549}, which we will convert
 *  into ASCII yielding "1.2.840.113549"
 *
 *  The return value "pAscii" is not reference-counted and will need to
 *  be freed with PKIX_PL_Free.
 *
 * PARAMETERS
 *  "secItem"
 *      Address of SECItem which contains bytes and length of DER encoding.
 *      Must be non-NULL.
 *  "pAscii"
 *      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 an OID 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_oidBytes2Ascii(
        SECItem *secItem,
        char **pAscii,
        void *plContext)
{
        char *data = NULL;
        PKIX_UInt32 *tokens = NULL;
        PKIX_UInt32 token = 0;
        PKIX_UInt32 numBytes = 0;
        PKIX_UInt32 numTokens = 0;
        PKIX_UInt32 i = 0, x = 0, y = 0;
        PKIX_UInt32 index = 0;
        char *asciiString = NULL;

        PKIX_ENTER(OID, "pkix_pl_oidBytes2Ascii");
        PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data);

        if (secItem->len == 0) {
                PKIX_ERROR_FATAL(PKIX_OIDBYTES2ASCIIDATALENGTHZERO);
        }

        data = (char *)(secItem->data);
        numBytes = secItem->len;
        numTokens = 0;

        /* calculate how many integer tokens are represented by the bytes. */
        for (i = 0; i < numBytes; i++){
                if ((data[i] & 0x080) == 0){
                        numTokens++;
                }
        }

        /* if we are unable to retrieve any tokens at all, we throw an error */
        if (numTokens == 0){
                PKIX_ERROR(PKIX_INVALIDDERENCODINGFOROID);
        }

        /* add one more token b/c the first byte always contains two tokens */
        numTokens++;

        /* allocate space for array of integers */
        PKIX_CHECK(PKIX_PL_Malloc
                    (numTokens * sizeof (PKIX_UInt32),
                    (void **)&tokens,
                    plContext),
                    PKIX_MALLOCFAILED);

        /* populate array of integers */
        for (i = 0; i < numTokens; i++){

                /* retrieve integer token */
                PKIX_CHECK(pkix_pl_getOIDToken
                            (data, index, &token, &index, plContext),
                            PKIX_GETOIDTOKENFAILED);

                if (i == 0){

                        /*
                         * special case: the first DER-encoded byte represents
                         * two tokens. We take advantage of fact that first
                         * token must be 0, 1, or 2; and second token must be
                         * between {0, 39} inclusive if first token is 0 or 1.
                         */

                        if (token < 40)
                                x = 0;
                        else if (token < 80)
                                x = 1;
                        else
                                x = 2;
                        y = token - (x * 40);

                        tokens[0] = x;
                        tokens[1] = y;
                        i++;
                } else {
                        tokens[i] = token;
                }
        }

        /* convert array of integers to ASCII */
        PKIX_CHECK(pkix_pl_helperBytes2Ascii
                    (tokens, numTokens, &asciiString, plContext),
                    PKIX_HELPERBYTES2ASCIIFAILED);

        *pAscii = asciiString;

cleanup:

        PKIX_FREE(tokens);
        PKIX_RETURN(OID);

}
コード例 #9
0
/*
 * FUNCTION: pkix_pl_helperBytes2Ascii
 * DESCRIPTION:
 *
 *  Converts an array of integers pointed to by "tokens" with a length of
 *  "numTokens", to an ASCII string consisting of those integers with dots in
 *  between them and stores the result at "pAscii". The ASCII representation is
 *  guaranteed to end with a NUL character. This is particularly useful for
 *  OID's and IP Addresses.
 *
 *  The return value "pAscii" is not reference-counted and will need to
 *  be freed with PKIX_PL_Free.
 *
 * PARAMETERS
 *  "tokens"
 *      Address of array of integers. Must be non-NULL.
 *  "numTokens"
 *      Length of array of integers. Must be non-zero.
 *  "pAscii"
 *      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 an Object 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_helperBytes2Ascii(
        PKIX_UInt32 *tokens,
        PKIX_UInt32 numTokens,
        char **pAscii,
        void *plContext)
{
        char *tempString = NULL;
        char *outputString = NULL;
        char *format = "%d";
        PKIX_UInt32 i = 0;
        PKIX_UInt32 outputLen = 0;
        PKIX_Int32 error;

        PKIX_ENTER(OBJECT, "pkix_pl_helperBytes2Ascii");
        PKIX_NULLCHECK_TWO(tokens, pAscii);

        if (numTokens == 0) {
                PKIX_ERROR_FATAL(PKIX_HELPERBYTES2ASCIINUMTOKENSZERO);
        }

        /*
         * tempString will hold the string representation of a PKIX_UInt32 type
         * The maximum value that can be held by an unsigned 32-bit integer
         * is (2^32 - 1) = 4294967295 (which is ten digits long)
         * Since tempString will hold the string representation of a
         * PKIX_UInt32, we allocate 11 bytes for it (1 byte for '\0')
         */

        PKIX_CHECK(PKIX_PL_Malloc
                    (MAX_DIGITS_32 + 1, (void **)&tempString, plContext),
                    PKIX_MALLOCFAILED);

        for (i = 0; i < numTokens; i++){
                PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n");
                error = PR_snprintf(tempString,
                                    MAX_DIGITS_32 + 1,
                                    format,
                                    tokens[i]);
                if (error == -1){
                        PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
                }

                PKIX_OBJECT_DEBUG("\tCalling PL_strlen).\n");
                outputLen += PL_strlen(tempString);

                /* Include a dot to separate each number */
                outputLen++;
        }

        /* Allocate space for the destination string */
        PKIX_CHECK(PKIX_PL_Malloc
                    (outputLen, (void **)&outputString, plContext),
                    PKIX_MALLOCFAILED);

        *outputString = '\0';

        /* Concatenate all strings together */
        for (i = 0; i < numTokens; i++){

                PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n");
                error = PR_snprintf(tempString,
                                    MAX_DIGITS_32 + 1,
                                    format,
                                    tokens[i]);
                if (error == -1){
                        PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
                }

                PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n");
                (void) PL_strcat(outputString, tempString);

                /* we don't want to put a "." at the very end */
                if (i < (numTokens - 1)){
                        PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n");
                        (void) PL_strcat(outputString, ".");
                }
        }

        /* Ensure output string ends with terminating null */
        outputString[outputLen-1] = '\0';

        *pAscii = outputString;
        outputString = NULL;

cleanup:
        
        PKIX_FREE(outputString);
        PKIX_FREE(tempString);

        PKIX_RETURN(OBJECT);

}
コード例 #10
0
PKIX_Error *
pkix_pl_AIAMgr_GetLDAPCerts(
        PKIX_PL_AIAMgr *aiaMgr,
	PKIX_PL_InfoAccess *ia,
	void **pNBIOContext,
	PKIX_List **pCerts,
        void *plContext)
{
        PKIX_List *result = NULL;
        PKIX_PL_GeneralName *location = NULL;
        PKIX_PL_LdapClient *client = NULL;
        LDAPRequestParams request;
        PLArenaPool *arena = NULL;
        char *domainName = NULL;
	void *nbio = NULL;

        PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetLDAPCerts");
        PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts);

        nbio = *pNBIOContext;
        *pNBIOContext = NULL;
        *pCerts = NULL;

        if (nbio == NULL) { /* a new request */

                /* Initiate an LDAP request */

                request.scope = WHOLE_SUBTREE;
                request.derefAliases = NEVER_DEREF;
                request.sizeLimit = 0;
                request.timeLimit = 0;

                PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation
                        (ia, &location, plContext),
                        PKIX_INFOACCESSGETLOCATIONFAILED);

                /*
                 * Get a short-lived arena. We'll be done with
                 * this space once the request is encoded.
                 */
                arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
                if (!arena) {
                        PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
                }

                PKIX_CHECK(pkix_pl_InfoAccess_ParseLocation
                        (location, arena, &request, &domainName, plContext),
                        PKIX_INFOACCESSPARSELOCATIONFAILED);

                PKIX_DECREF(location);

                /* Find or create a connection to LDAP server */
                PKIX_CHECK(pkix_pl_AiaMgr_FindLDAPClient
                        (aiaMgr, domainName, &client, plContext),
                        PKIX_AIAMGRFINDLDAPCLIENTFAILED);

                aiaMgr->client.ldapClient = client;

                PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
                        (aiaMgr->client.ldapClient,
			&request,
			&nbio,
			&result,
			plContext),
                        PKIX_LDAPCLIENTINITIATEREQUESTFAILED);

                PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));

        } else {

                PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
                        (aiaMgr->client.ldapClient, &nbio, &result, plContext),
                        PKIX_LDAPCLIENTRESUMEREQUESTFAILED);

        }

        if (nbio != NULL) { /* WOULDBLOCK */
                *pNBIOContext = nbio;
                *pCerts = NULL;
                goto cleanup;
        }

	PKIX_DECREF(aiaMgr->client.ldapClient);

	if (result == NULL) {
		*pCerts = NULL;
	} else {
		PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
			(result, pCerts, plContext),
			PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
	}

	*pNBIOContext = nbio;

cleanup:

        if (arena && (PKIX_ERROR_RECEIVED)) {
                PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));
        }

        if (PKIX_ERROR_RECEIVED) {
	        PKIX_DECREF(aiaMgr->client.ldapClient);
	}

        PKIX_DECREF(location);

        PKIX_RETURN(AIAMGR);
}
コード例 #11
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h)
 */
PKIX_Error *
PKIX_PL_Object_Equals(
        PKIX_PL_Object *firstObject,
        PKIX_PL_Object *secondObject,
        PKIX_Boolean *pResult,
        void *plContext)
{
        PKIX_PL_Object *firstObjectHeader = NULL;
        PKIX_PL_Object *secondObjectHeader = NULL;
        PKIX_PL_EqualsCallback func = NULL;
        pkix_ClassTable_Entry entry;
        PKIX_UInt32 objType;

        PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals");
        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);

        PKIX_CHECK(pkix_pl_Object_GetHeader
                    (firstObject, &firstObjectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);

        PKIX_CHECK(pkix_pl_Object_GetHeader
                    (secondObject, &secondObjectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);

        /* if hashcodes are cached but not equal, objects can't be equal */
        if (firstObjectHeader->hashcodeCached &&
            secondObjectHeader->hashcodeCached){
                if (firstObjectHeader->hashcode !=
                    secondObjectHeader->hashcode){
                        *pResult = PKIX_FALSE;
                        goto cleanup;
                }
        }

        objType = firstObjectHeader->type;

        if (objType >= PKIX_NUMTYPES) {
#ifdef PKIX_USER_OBJECT_TYPE
                pkix_ClassTable_Entry *ctEntry = NULL;
                PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
                PR_Lock(classTableLock);
                pkixErrorResult = pkix_pl_PrimHashTable_Lookup
                        (classTable,
                        (void *)&firstObjectHeader->type,
                        firstObjectHeader->type,
                        NULL,
                        (void **)&ctEntry,
                        plContext);
                PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
                PR_Unlock(classTableLock);

                if (pkixErrorResult){
                        PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
                }

                if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) {
                        PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
                } else {
                        func = ctEntry->equalsFunction;
                }
#else
                PORT_Assert (0);
                pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
                pkixErrorClass = PKIX_FATAL_ERROR;
                goto cleanup;
#endif /* PKIX_USER_OBJECT_TYPE */
        } else {
                entry = systemClasses[objType];
                func = entry.equalsFunction;
                if (func == NULL){
                        func = pkix_pl_Object_Equals_Default;
                }
        }

        PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
                    PKIX_OBJECTSPECIFICFUNCTIONFAILED);

cleanup:

        PKIX_RETURN(OBJECT);
}
コード例 #12
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h)
 */
PKIX_Error *
PKIX_PL_Object_Duplicate(
        PKIX_PL_Object *firstObject,
        PKIX_PL_Object **pNewObject,
        void *plContext)
{
        PKIX_PL_Object *firstObjectHeader = NULL;
        PKIX_PL_DuplicateCallback func = NULL;
        pkix_ClassTable_Entry entry;
        PKIX_UInt32 objType;

        PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate");
        PKIX_NULLCHECK_TWO(firstObject, pNewObject);

        PKIX_CHECK(pkix_pl_Object_GetHeader
                    (firstObject, &firstObjectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);

        objType = firstObjectHeader->type;

        if (objType >= PKIX_NUMTYPES) {
#ifdef PKIX_USER_OBJECT_TYPE
                pkix_ClassTable_Entry *ctEntry = NULL;

                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_ERRORGETTINGCLASSTABLEENTRY);
                }

                if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) {
                        PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
                } else {
                        func = ctEntry->duplicateFunction;
                }
#else
                PORT_Assert (0);
                pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
                pkixErrorClass = PKIX_FATAL_ERROR;
                goto cleanup;
#endif /* PKIX_USER_OBJECT_TYPE */
        } else {
                entry = systemClasses[objType];
                func = entry.duplicateFunction;
                if (!func){
                        PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION);
                }
        }

        PKIX_CHECK(func(firstObject, pNewObject, plContext),
                    PKIX_OBJECTSPECIFICFUNCTIONFAILED);

cleanup:

        PKIX_RETURN(OBJECT);
}
コード例 #13
0
/*
 * FUNCTION: pkix_pl_LdapCertStore_GetCRL
 *  (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
 */
PKIX_Error *
pkix_pl_LdapCertStore_GetCRL(
        PKIX_CertStore *store,
        PKIX_CRLSelector *selector,
        void **pNBIOContext,
        PKIX_List **pCrlList,
        void *plContext)
{
        LDAPRequestParams requestParams;
        void *pollDesc = NULL;
        PRArenaPool *requestArena = NULL;
        PKIX_UInt32 numNames = 0;
        PKIX_UInt32 thisName = 0;
        PKIX_PL_CRL *candidate = NULL;
        PKIX_List *responses = NULL;
        PKIX_List *issuerNames = NULL;
        PKIX_List *filteredCRLs = NULL;
        PKIX_List *unfilteredCRLs = NULL;
        PKIX_PL_X500Name *issuer = NULL;
        PKIX_PL_LdapCertStoreContext *lcs = NULL;
        PKIX_ComCRLSelParams *params = NULL;

        PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCRL");
        PKIX_NULLCHECK_THREE(store, selector, pCrlList);

        requestParams.baseObject = "c=US";
        requestParams.scope = WHOLE_SUBTREE;
        requestParams.derefAliases = NEVER_DEREF;
        requestParams.sizeLimit = 0;
        requestParams.timeLimit = 0;
        requestParams.attributes = LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST;
        /* Prepare elements for request filter */

        /* XXX Place CRLDP code here. Handle the case when */
        /* RFC 5280. Paragraph: 4.2.1.13: */
        /* If the distributionPoint field contains a directoryName, the entry */
        /* for that directoryName contains the current CRL for the associated */
        /* reasons and the CRL is issued by the associated cRLIssuer.  The CRL */
        /* may be stored in either the certificateRevocationList or */
        /* authorityRevocationList attribute.  The CRL is to be obtained by the */
        /* application from whatever directory server is locally configured. */
        /* The protocol the application uses to access the directory (e.g., DAP */
        /* or LDAP) is a local matter. */



        /*
         * Get a short-lived arena. We'll be done with this space once
         * the request is encoded.
         */
        PKIX_PL_NSSCALLRV
            (CERTSTORE, requestArena, PORT_NewArena, (DER_DEFAULT_CHUNKSIZE));

        if (!requestArena) {
                PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
        }

        PKIX_CHECK(PKIX_CRLSelector_GetCommonCRLSelectorParams
                (selector, &params, plContext),
                PKIX_CRLSELECTORGETCOMCERTSELPARAMSFAILED);

        PKIX_CHECK(PKIX_ComCRLSelParams_GetIssuerNames
                (params, &issuerNames, plContext),
                PKIX_COMCRLSELPARAMSGETISSUERNAMESFAILED);

        /*
         * The specification for PKIX_ComCRLSelParams_GetIssuerNames in
         * pkix_crlsel.h says that if the criterion is not set we get a null
         * pointer. If we get an empty List the criterion is impossible to
         * meet ("must match at least one of the names in the List").
         */
        if (issuerNames) {

                PKIX_CHECK(PKIX_List_GetLength
                        (issuerNames, &numNames, plContext),
                        PKIX_LISTGETLENGTHFAILED);

                if (numNames > 0) {
                        for (thisName = 0; thisName < numNames; thisName++) {
                                PKIX_CHECK(PKIX_List_GetItem
                                (issuerNames,
                                thisName,
                                (PKIX_PL_Object **)&issuer,
                                plContext),
                                PKIX_LISTGETITEMFAILED);

                                PKIX_CHECK
                                        (pkix_pl_LdapCertStore_MakeNameAVAList
                                        (requestArena,
                                        issuer,
                                        &(requestParams.nc),
                                        plContext),
                                        PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED);

                                PKIX_DECREF(issuer);

                                if (*requestParams.nc == NULL) {
                                        /*
                                         * The issuer may not include any
                                         * components that we know how to
                                         * encode. We do not return an error,
                                         * because the caller did not
                                         * necessarily do anything wrong, but
                                         * we return an empty List.
                                         */
                                        PKIX_PL_NSSCALL
                                                (CERTSTORE, PORT_FreeArena,
                                                (requestArena, PR_FALSE));

                                        PKIX_CHECK(PKIX_List_Create
                                                (&filteredCRLs, plContext),
                                                PKIX_LISTCREATEFAILED);

                                        PKIX_CHECK(PKIX_List_SetImmutable
                                                (filteredCRLs, plContext),
                                               PKIX_LISTSETIMMUTABLEFAILED);

                                        *pNBIOContext = NULL;
                                        *pCrlList = filteredCRLs;
                                        goto cleanup;
                                }

                                /*
                                 * LDAP Servers don't seem to be able to handle
                                 * requests with more than more than one name.
                                 */
                                break;
                        }
                } else {
                        PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY);
                }
        } else {
                PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY);
        }

        /* All request fields are done */

        PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
                (store, (PKIX_PL_Object **)&lcs, plContext),
                PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);

        PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
                ((PKIX_PL_LdapClient *)lcs,
                &requestParams,
                &pollDesc,
                &responses,
                plContext),
                PKIX_LDAPCLIENTINITIATEREQUESTFAILED);

        PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList
                (requestParams.nc, plContext),
                PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED);

        if (requestArena) {
                PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
                        (requestArena, PR_FALSE));
        }

        if (pollDesc != NULL) {
                /* client is waiting for non-blocking I/O to complete */
                *pNBIOContext = (void *)pollDesc;
                *pCrlList = NULL;
                goto cleanup;
        }
        /* client has finished! */

        if (responses) {

                /*
                 * We have a List of LdapResponse objects that still have to be
                 * turned into Crls.
                 */
                PKIX_CHECK(pkix_pl_LdapCertStore_BuildCrlList
                        (responses, &unfilteredCRLs, plContext),
                        PKIX_LDAPCERTSTOREBUILDCRLLISTFAILED);

                PKIX_CHECK(pkix_CRLSelector_Select
                        (selector, unfilteredCRLs, &filteredCRLs, plContext),
                        PKIX_CRLSELECTORSELECTFAILED);

        }

        /* Don't throw away the list if one CRL was bad! */
        pkixTempErrorReceived = PKIX_FALSE;

        *pNBIOContext = NULL;
        *pCrlList = filteredCRLs;

cleanup:

        if (PKIX_ERROR_RECEIVED) {
                PKIX_DECREF(filteredCRLs);
        }

        PKIX_DECREF(params);
        PKIX_DECREF(issuerNames);
        PKIX_DECREF(issuer);
        PKIX_DECREF(candidate);
        PKIX_DECREF(responses);
        PKIX_DECREF(unfilteredCRLs);
        PKIX_DECREF(lcs);

        PKIX_RETURN(CERTSTORE);
}
コード例 #14
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * FUNCTION: pkix_pl_Object_GetHeader
 * DESCRIPTION:
 *
 *  Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and
 *  stores the value at "pObjectHeader".
 *
 * PARAMETERS:
 *  "object"
 *      Address of Object to shift. Must be non-NULL.
 *  "pObjectHeader"
 *      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 Fatal Error if the function fails in an unrecoverable way.
 */
static PKIX_Error *
pkix_pl_Object_GetHeader(
        PKIX_PL_Object *object,
        PKIX_PL_Object **pObjectHeader,
        void *plContext)
{
        PKIX_PL_Object *header = NULL;
        PKIX_UInt32 objType;

        PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader");
        PKIX_NULLCHECK_TWO(object, pObjectHeader);

        PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");

        /* The header is sizeof(PKIX_PL_Object) before the object pointer */
        header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object));

        objType = header->type;

        if (objType >= PKIX_NUMTYPES) { /* if this is a user-defined type */
#ifdef PKIX_USER_OBJECT_TYPE
                pkix_ClassTable_Entry *ctEntry = NULL;

                PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
                PR_Lock(classTableLock);

                PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
                            (classTable,
                            (void *)&objType,
                            objType,
                            NULL,
                            (void **)&ctEntry,
                            plContext),
                            PKIX_ERRORGETTINGCLASSTABLEENTRY);

                PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
                PR_Unlock(classTableLock);

                if (ctEntry == NULL) {
                        PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE);
                }
#else
                PORT_Assert(objType < PKIX_NUMTYPES);
                pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
                pkixErrorClass = PKIX_FATAL_ERROR;
                goto cleanup;
#endif /* PKIX_USER_OBJECT_TYPE */
        }

#ifdef PKIX_OBJECT_LEAK_TEST
        PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER);
#endif /* PKIX_OBJECT_LEAK_TEST */

        if ((header == NULL)||
            (header->magicHeader != PKIX_MAGIC_HEADER)) {
                PKIX_ERROR_ALLOC_ERROR();
        }

        *pObjectHeader = header;

cleanup:

        PKIX_RETURN(OBJECT);
}
コード例 #15
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * 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);
}
コード例 #16
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * FUNCTION: pkix_pl_Object_ToString_Default
 * DESCRIPTION:
 *
 *  Default Object_ToString callback: Creates a string consisting of the
 *  typename and address of the Object pointed to by "object" and stores
 *  the result at "pString". The format for the string is
 *  "TypeName@Address: <address>", where the default typename is "Object".
 *
 * PARAMETERS:
 *  "object"
 *      Address of Object to convert to a string. 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 an Object 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_Object_ToString_Default(
        PKIX_PL_Object *object,
        PKIX_PL_String **pString,
        void *plContext)
{
        PKIX_PL_String *formatString = NULL;
        PKIX_PL_String *descString = NULL;
        char *format = "%s@Address: %x";
        char *description = NULL;
        PKIX_UInt32 objType;

        PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default");
        PKIX_NULLCHECK_TWO(object, pString);

        PKIX_CHECK(PKIX_PL_Object_GetType(object, &objType, plContext),
                    PKIX_OBJECTGETTYPEFAILED);

        if (objType >= PKIX_NUMTYPES){
#ifdef PKIX_USER_OBJECT_TYPE
                pkix_ClassTable_Entry *ctEntry = NULL;

                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_ERRORGETTINGCLASSTABLEENTRY);
                }

                if (ctEntry == NULL){
                        PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY);
                } else {
                        description = ctEntry->description;
                        if (description == NULL) {
                            description = "User Type Object";
                        }
                }
#else
                PORT_Assert (0);
                pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
                pkixErrorClass = PKIX_FATAL_ERROR;
                goto cleanup;
#endif /* PKIX_USER_OBJECT_TYPE */
        } else {
                description = systemClasses[objType].description;
        }
        PKIX_CHECK(PKIX_PL_String_Create
                    (PKIX_ESCASCII,
                    (void *)format,
                    0,
                    &formatString,
                    plContext),
                    PKIX_STRINGCREATEFAILED);

        PKIX_CHECK(PKIX_PL_String_Create
                    (PKIX_ESCASCII,
                    (void *)description,
                    0,
                    &descString,
                    plContext),
                    PKIX_STRINGCREATEFAILED);

        PKIX_CHECK(PKIX_PL_Sprintf
                    (pString,
                    plContext,
                    formatString,
                    descString,
                    object),
                    PKIX_SPRINTFFAILED);

cleanup:

        PKIX_DECREF(formatString);
        PKIX_DECREF(descString);

        PKIX_RETURN(OBJECT);
}
コード例 #17
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h)
 */
PKIX_Error *
PKIX_PL_Object_Compare(
        PKIX_PL_Object *firstObject,
        PKIX_PL_Object *secondObject,
        PKIX_Int32 *pResult,
        void *plContext)
{
        PKIX_PL_Object *firstObjectHeader = NULL;
        PKIX_PL_Object *secondObjectHeader = NULL;
        PKIX_PL_ComparatorCallback func = NULL;
        pkix_ClassTable_Entry entry;
        PKIX_UInt32 objType;

        PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare");
        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);

        /* Shift pointer from user data to object header */
        PKIX_CHECK(pkix_pl_Object_GetHeader
                    (firstObject, &firstObjectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);

        /* Shift pointer from user data to object header */
        PKIX_CHECK(pkix_pl_Object_GetHeader
                    (secondObject, &secondObjectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);

        objType = firstObjectHeader->type;

        if (objType >= PKIX_NUMTYPES){
#ifdef PKIX_USER_OBJECT_TYPE
                pkix_ClassTable_Entry *ctEntry = NULL;

                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_ERRORGETTINGCLASSTABLEENTRY);
                }

                if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) {
                        PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR);
                }

                func = ctEntry->comparator;
#else
                PORT_Assert (0);
                pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
                pkixErrorClass = PKIX_FATAL_ERROR;
                goto cleanup;
#endif /* PKIX_USER_OBJECT_TYPE */
        } else {
                /* special handling for system types */
                entry = systemClasses[objType];
                func = entry.comparator;
                if (!func){
                        PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR);
                }
        }

        PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
                    PKIX_OBJECTSPECIFICFUNCTIONFAILED);

cleanup:

        PKIX_RETURN(OBJECT);
}
コード例 #18
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h)
 */
PKIX_Error *
PKIX_PL_Object_ToString(
        PKIX_PL_Object *object,
        PKIX_PL_String **pString,
        void *plContext)
{
        PKIX_PL_Object *objectHeader = NULL;
        PKIX_PL_ToStringCallback func = NULL;
        pkix_ClassTable_Entry entry;
        PKIX_PL_String *objectString = NULL;

        PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString");
        PKIX_NULLCHECK_TWO(object, pString);

        /* Shift pointer from user data to object header */
        PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);

        /* if we don't have a cached copy from before, we create one */
        if (!objectHeader->stringRep){

                PKIX_UInt32 objType = objectHeader->type;

                if (objType >= PKIX_NUMTYPES){
#ifdef PKIX_USER_OBJECT_TYPE
                        pkix_ClassTable_Entry *ctEntry = NULL;

                        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_ERRORGETTINGCLASSTABLEENTRY);
                        }

                        if ((ctEntry == NULL) ||
                            (ctEntry->toStringFunction == NULL)) {
                                PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
                        }

                        func = ctEntry->toStringFunction;
#else
                        PORT_Assert (0);
                        pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
                        pkixErrorClass = PKIX_FATAL_ERROR;
                        goto cleanup;
#endif /* PKIX_USER_OBJECT_TYPE */
                } else {
                        entry = systemClasses[objType];
                        func = entry.toStringFunction;
                        if (func == NULL){
                                func = pkix_pl_Object_ToString_Default;
                        }
                }

                PKIX_CHECK(func(object, &objectString, plContext),
                            PKIX_OBJECTSPECIFICFUNCTIONFAILED);

                if (!objectHeader->stringRep){

                        PKIX_CHECK(pkix_LockObject(object, plContext),
                                    PKIX_ERRORLOCKINGOBJECT);

                        if (!objectHeader->stringRep){
                                /* save a cached copy */
                                objectHeader->stringRep = objectString;
                                objectString = NULL;
                        }

                        PKIX_CHECK(pkix_UnlockObject(object, plContext),
                                    PKIX_ERRORUNLOCKINGOBJECT);
                }
        }


        *pString = objectHeader->stringRep;
        objectHeader->stringRep = NULL;

cleanup:
        if (objectHeader) {
            PKIX_DECREF(objectHeader->stringRep);
        }
        PKIX_DECREF(objectString);

        PKIX_RETURN(OBJECT);
}
コード例 #19
0
/*
 * FUNCTION: pkix_CrlChecker_CheckRemote
 *
 * 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.
 *  "unreslvdCrtExts"
 *      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
 */
PKIX_Error *
pkix_CrlChecker_CheckExternal(
        PKIX_PL_Cert *cert,
        PKIX_PL_Cert *issuer,
        PKIX_PL_Date *date,
        pkix_RevocationMethod *checkerObject,
        PKIX_ProcessingParams *procParams,
        PKIX_UInt32 methodFlags,
        PKIX_RevocationStatus *pRevStatus,
        PKIX_UInt32 *pReasonCode,
        void **pNBIOContext,
        void *plContext)
{
    PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn = NULL;
    PKIX_CertStore_ImportCrlCallback storeImportCrlFn = NULL;
    PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
    PKIX_CertStore *certStore = NULL;
    PKIX_CertStore *localStore = NULL;
    PKIX_CRLSelector *crlSelector = NULL;
    PKIX_PL_X500Name *issuerName = NULL;
    pkix_CrlChecker *state = NULL; 
    PKIX_UInt32 reasonCode = 0;
    PKIX_UInt32 crlStoreIndex = 0;
    PKIX_UInt32 numCrlStores = 0;
    PKIX_Boolean storeIsLocal = PKIX_FALSE;
    PKIX_List *crlList = NULL;
    PKIX_List *dpList = NULL;
    void *nbioContext = NULL;

    PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckExternal");
    PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, pNBIOContext);
    
    nbioContext = *pNBIOContext;
    *pNBIOContext = NULL; /* prepare for Error exit */

    state = (pkix_CrlChecker*)checkerObject;
    
    PKIX_CHECK(
        PKIX_List_GetLength(state->certStores, &numCrlStores, plContext),
        PKIX_LISTGETLENGTHFAILED);

    /* Find a cert store that is capable of storing crls */
    for (;crlStoreIndex < numCrlStores;crlStoreIndex++) {
        PKIX_CHECK(
            PKIX_List_GetItem(state->certStores, crlStoreIndex,
                              (PKIX_PL_Object **)&certStore,
                              plContext),
            PKIX_LISTGETITEMFAILED);
        
        PKIX_CHECK(
            PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal,
                                        plContext),
            PKIX_CERTSTOREGETLOCALFLAGFAILED);
        if (storeIsLocal) {
            PKIX_CHECK(
                PKIX_CertStore_GetImportCrlCallback(certStore,
                                                    &storeImportCrlFn,
                                                    plContext),
                PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
            
            PKIX_CHECK(
                PKIX_CertStore_GetCrlCheckerFn(certStore,
                                               &storeCheckRevocationFn,
                                               plContext),
                PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
            
            if (storeImportCrlFn && storeCheckRevocationFn) {
                localStore = certStore;
                certStore = NULL;
                break;
            }
        }
        PKIX_DECREF(certStore);
    } /* while */

    /* Report unknown status if we can not check crl in one of the
     * local stores. */
    if (!localStore) {
        PKIX_ERROR_FATAL(PKIX_CRLCHECKERNOLOCALCERTSTOREFOUND);
    }
    PKIX_CHECK(
        PKIX_PL_Cert_VerifyKeyUsage(issuer, PKIX_CRL_SIGN, plContext),
        PKIX_CERTCHECKKEYUSAGEFAILED);
    PKIX_CHECK(
        PKIX_PL_Cert_GetCrlDp(cert, &dpList, plContext),
        PKIX_CERTGETCRLDPFAILED);
    if (!(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
        (!dpList || !dpList->length)) {
        goto cleanup;
    }
    PKIX_CHECK(
        PKIX_PL_Cert_GetIssuer(cert, &issuerName, plContext),
        PKIX_CERTGETISSUERFAILED);
    PKIX_CHECK(
        PKIX_CRLSelector_Create(issuer, dpList, date, &crlSelector, plContext),
        PKIX_CRLCHECKERSETSELECTORFAILED);
    /* Fetch crl and store in a local cert store */
    for (crlStoreIndex = 0;crlStoreIndex < numCrlStores;crlStoreIndex++) {
        PKIX_CertStore_CRLCallback getCrlsFn;

        PKIX_CHECK(
            PKIX_List_GetItem(state->certStores, crlStoreIndex,
                              (PKIX_PL_Object **)&certStore,
                              plContext),
            PKIX_LISTGETITEMFAILED);
        
        PKIX_CHECK(
            PKIX_CertStore_GetCRLCallback(certStore, &getCrlsFn,
                                          plContext),
            PKIX_CERTSTOREGETCRLCALLBACKFAILED);
        
        PKIX_CHECK(
            (*getCrlsFn)(certStore, crlSelector, &nbioContext,
                      &crlList, plContext),
            PKIX_GETCRLSFAILED);

        PKIX_CHECK(
            (*storeImportCrlFn)(localStore, issuerName, crlList, plContext),
            PKIX_CERTSTOREFAILTOIMPORTCRLLIST);
        
        PKIX_CHECK(
            (*storeCheckRevocationFn)(certStore, cert, issuer, date,
                                      /* done with crl downloading */
                                      PKIX_TRUE,
                                      &reasonCode, &revStatus, plContext),
            PKIX_CERTSTORECRLCHECKFAILED);
        if (revStatus != PKIX_RevStatus_NoInfo) {
            break;
        }
        PKIX_DECREF(crlList);
        PKIX_DECREF(certStore);
    } /* while */

cleanup:
    /* Update return flags */
    if (revStatus == PKIX_RevStatus_NoInfo && 
	((dpList && dpList->length > 0) ||
	 (methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE)) &&
        methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
        revStatus = PKIX_RevStatus_Revoked;
    }
    *pRevStatus = revStatus;

    PKIX_DECREF(dpList);
    PKIX_DECREF(crlList);
    PKIX_DECREF(certStore);
    PKIX_DECREF(issuerName);
    PKIX_DECREF(localStore);
    PKIX_DECREF(crlSelector);

    PKIX_RETURN(CERTCHAINCHECKER);
}
コード例 #20
0
ファイル: pkix_pl_object.c プロジェクト: venkatarajasekhar/Qt
/*
 * 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);
}