Blame nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c

Packit 40b132
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit 40b132
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit 40b132
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit 40b132
/*
Packit 40b132
 * pkix_pl_infoaccess.c
Packit 40b132
 *
Packit 40b132
 * InfoAccess Object Definitions
Packit 40b132
 *
Packit 40b132
 */
Packit 40b132
Packit 40b132
#include "pkix_pl_infoaccess.h"
Packit 40b132
Packit 40b132
/* --Private-InfoAccess-Functions----------------------------------*/
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_pl_InfoAccess_Create
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  This function creates an InfoAccess from the method provided in "method" and
Packit 40b132
 *  the GeneralName provided in "generalName" and stores the result at
Packit 40b132
 *  "pInfoAccess".
Packit 40b132
 *
Packit 40b132
 * PARAMETERS
Packit 40b132
 *  "method"
Packit 40b132
 *      The UInt32 value to be stored as the method field of the InfoAccess.
Packit 40b132
 *  "generalName"
Packit 40b132
 *      The GeneralName to be stored as the generalName field of the InfoAccess.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "pInfoAccess"
Packit 40b132
 *      Address where the result is stored. Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
static PKIX_Error *
Packit 40b132
pkix_pl_InfoAccess_Create(
Packit 40b132
        PKIX_UInt32 method,
Packit 40b132
        PKIX_PL_GeneralName *generalName,
Packit 40b132
        PKIX_PL_InfoAccess **pInfoAccess,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
Packit 40b132
        PKIX_PL_InfoAccess *infoAccess = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Create");
Packit 40b132
        PKIX_NULLCHECK_TWO(generalName, pInfoAccess);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_Object_Alloc
Packit 40b132
                (PKIX_INFOACCESS_TYPE,
Packit 40b132
                sizeof (PKIX_PL_InfoAccess),
Packit 40b132
                (PKIX_PL_Object **)&infoAccess,
Packit 40b132
                plContext),
Packit 40b132
                PKIX_COULDNOTCREATEINFOACCESSOBJECT);
Packit 40b132
Packit 40b132
        infoAccess->method = method;
Packit 40b132
Packit 40b132
        PKIX_INCREF(generalName);
Packit 40b132
        infoAccess->location = generalName;
Packit 40b132
Packit 40b132
        *pInfoAccess = infoAccess;
Packit 40b132
        infoAccess = NULL;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
        PKIX_DECREF(infoAccess);
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_pl_InfoAccess_Destroy
Packit 40b132
 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h)
Packit 40b132
 */
Packit 40b132
static PKIX_Error *
Packit 40b132
pkix_pl_InfoAccess_Destroy(
Packit 40b132
        PKIX_PL_Object *object,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_PL_InfoAccess *infoAccess = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Destroy");
Packit 40b132
        PKIX_NULLCHECK_ONE(object);
Packit 40b132
Packit 40b132
        PKIX_CHECK(pkix_CheckType(object, PKIX_INFOACCESS_TYPE, plContext),
Packit 40b132
                PKIX_OBJECTNOTANINFOACCESS);
Packit 40b132
Packit 40b132
        infoAccess = (PKIX_PL_InfoAccess *)object;
Packit 40b132
Packit 40b132
        PKIX_DECREF(infoAccess->location);
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_pl_InfoAccess_ToString
Packit 40b132
 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_pki.h)
Packit 40b132
 */
Packit 40b132
static PKIX_Error *
Packit 40b132
pkix_pl_InfoAccess_ToString(
Packit 40b132
        PKIX_PL_Object *object,
Packit 40b132
        PKIX_PL_String **pString,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_PL_InfoAccess *infoAccess;
Packit 40b132
        PKIX_PL_String *infoAccessString = NULL;
Packit 40b132
        char *asciiFormat = NULL;
Packit 40b132
        char *asciiMethod = NULL;
Packit 40b132
        PKIX_PL_String *formatString = NULL;
Packit 40b132
        PKIX_PL_String *methodString = NULL;
Packit 40b132
        PKIX_PL_String *locationString = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ToString");
Packit 40b132
        PKIX_NULLCHECK_TWO(object, pString);
Packit 40b132
Packit 40b132
        PKIX_CHECK(pkix_CheckType
Packit 40b132
                    (object, PKIX_INFOACCESS_TYPE, plContext),
Packit 40b132
                    PKIX_OBJECTNOTINFOACCESS);
Packit 40b132
Packit 40b132
        infoAccess = (PKIX_PL_InfoAccess *)object;
Packit 40b132
Packit 40b132
        asciiFormat =
Packit 40b132
                "["
Packit 40b132
                "method:%s, "
Packit 40b132
                "location:%s"
Packit 40b132
                "]";
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_String_Create
Packit 40b132
                    (PKIX_ESCASCII,
Packit 40b132
                    asciiFormat,
Packit 40b132
                    0,
Packit 40b132
                    &formatString,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_STRINGCREATEFAILED);
Packit 40b132
Packit 40b132
        switch(infoAccess->method) {
Packit 40b132
            case PKIX_INFOACCESS_CA_ISSUERS:
Packit 40b132
                    asciiMethod = "caIssuers";
Packit 40b132
                    break;
Packit 40b132
            case PKIX_INFOACCESS_OCSP:
Packit 40b132
                    asciiMethod = "ocsp";
Packit 40b132
                    break;
Packit 40b132
            case PKIX_INFOACCESS_TIMESTAMPING:
Packit 40b132
                    asciiMethod = "timestamping";
Packit 40b132
                    break;
Packit 40b132
            case PKIX_INFOACCESS_CA_REPOSITORY:
Packit 40b132
                    asciiMethod = "caRepository";
Packit 40b132
                    break;
Packit 40b132
            default:
Packit 40b132
                    asciiMethod = "unknown";
Packit 40b132
        }
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_String_Create
Packit 40b132
                    (PKIX_ESCASCII,
Packit 40b132
                    asciiMethod,
Packit 40b132
                    0,
Packit 40b132
                    &methodString,
Packit 40b132
                    plContext),
Packit 40b132
                    PKIX_STRINGCREATEFAILED);
Packit 40b132
Packit 40b132
        PKIX_TOSTRING(infoAccess->location, &locationString, plContext,
Packit 40b132
                    PKIX_GENERALNAMETOSTRINGFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_Sprintf
Packit 40b132
                    (&infoAccessString,
Packit 40b132
                    plContext,
Packit 40b132
                    formatString,
Packit 40b132
                    methodString,
Packit 40b132
                    locationString),
Packit 40b132
                    PKIX_SPRINTFFAILED);
Packit 40b132
Packit 40b132
        *pString = infoAccessString;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DECREF(formatString);
Packit 40b132
        PKIX_DECREF(methodString);
Packit 40b132
        PKIX_DECREF(locationString);
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_pl_InfoAccess_Hashcode
Packit 40b132
 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_pki.h)
Packit 40b132
 */
Packit 40b132
static PKIX_Error *
Packit 40b132
pkix_pl_InfoAccess_Hashcode(
Packit 40b132
        PKIX_PL_Object *object,
Packit 40b132
        PKIX_UInt32 *pHashcode,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_PL_InfoAccess *infoAccess = NULL;
Packit 40b132
        PKIX_UInt32 infoAccessHash;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Hashcode");
Packit 40b132
        PKIX_NULLCHECK_TWO(object, pHashcode);
Packit 40b132
Packit 40b132
        PKIX_CHECK(pkix_CheckType
Packit 40b132
                    (object, PKIX_INFOACCESS_TYPE, plContext),
Packit 40b132
                    PKIX_OBJECTNOTINFOACCESS);
Packit 40b132
Packit 40b132
        infoAccess = (PKIX_PL_InfoAccess *)object;
Packit 40b132
Packit 40b132
        PKIX_HASHCODE(infoAccess->location, &infoAccessHash, plContext,
Packit 40b132
                    PKIX_OBJECTHASHCODEFAILED);
Packit 40b132
Packit 40b132
        infoAccessHash += (infoAccess->method << 7);
Packit 40b132
Packit 40b132
        *pHashcode = infoAccessHash;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_pl_InfoAccess_Equals
Packit 40b132
 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_pki.h)
Packit 40b132
 */
Packit 40b132
static PKIX_Error *
Packit 40b132
pkix_pl_InfoAccess_Equals(
Packit 40b132
        PKIX_PL_Object *firstObject,
Packit 40b132
        PKIX_PL_Object *secondObject,
Packit 40b132
        PKIX_Boolean *pResult,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_PL_InfoAccess *firstInfoAccess = NULL;
Packit 40b132
        PKIX_PL_InfoAccess *secondInfoAccess = NULL;
Packit 40b132
        PKIX_UInt32 secondType;
Packit 40b132
        PKIX_Boolean cmpResult;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Equals");
Packit 40b132
        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
Packit 40b132
Packit 40b132
        /* test that firstObject is a InfoAccess */
Packit 40b132
        PKIX_CHECK(pkix_CheckType
Packit 40b132
                (firstObject, PKIX_INFOACCESS_TYPE, plContext),
Packit 40b132
                PKIX_FIRSTOBJECTNOTINFOACCESS);
Packit 40b132
Packit 40b132
        /*
Packit 40b132
         * Since we know firstObject is a InfoAccess, if both references are
Packit 40b132
         * identical, they must be equal
Packit 40b132
         */
Packit 40b132
        if (firstObject == secondObject){
Packit 40b132
                *pResult = PKIX_TRUE;
Packit 40b132
                goto cleanup;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        /*
Packit 40b132
         * If secondObject isn't a InfoAccess, we don't throw an error.
Packit 40b132
         * We simply return a Boolean result of FALSE
Packit 40b132
         */
Packit 40b132
        *pResult = PKIX_FALSE;
Packit 40b132
        PKIX_CHECK(PKIX_PL_Object_GetType
Packit 40b132
                    (secondObject, &secondType, plContext),
Packit 40b132
                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
Packit 40b132
        if (secondType != PKIX_INFOACCESS_TYPE) goto cleanup;
Packit 40b132
Packit 40b132
        firstInfoAccess = (PKIX_PL_InfoAccess *)firstObject;
Packit 40b132
        secondInfoAccess = (PKIX_PL_InfoAccess *)secondObject;
Packit 40b132
Packit 40b132
        *pResult = PKIX_FALSE;
Packit 40b132
Packit 40b132
        if (firstInfoAccess->method != secondInfoAccess->method) {
Packit 40b132
                goto cleanup;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        PKIX_EQUALS(firstInfoAccess, secondInfoAccess, &cmpResult, plContext,
Packit 40b132
                PKIX_OBJECTEQUALSFAILED);
Packit 40b132
Packit 40b132
        *pResult = cmpResult;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_pl_InfoAccess_RegisterSelf
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *  Registers PKIX_INFOACCESS_TYPE and its related functions with systemClasses[]
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Not Thread Safe - for performance and complexity reasons
Packit 40b132
 *
Packit 40b132
 *  Since this function is only called by PKIX_PL_Initialize, which should
Packit 40b132
 *  only be called once, it is acceptable that this function is not
Packit 40b132
 *  thread-safe.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_pl_InfoAccess_RegisterSelf(void *plContext)
Packit 40b132
{
Packit 40b132
        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
Packit 40b132
        pkix_ClassTable_Entry entry;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS,
Packit 40b132
                "pkix_pl_InfoAccess_RegisterSelf");
Packit 40b132
Packit 40b132
        entry.description = "InfoAccess";
Packit 40b132
        entry.objCounter = 0;
Packit 40b132
        entry.typeObjectSize = sizeof(PKIX_PL_InfoAccess);
Packit 40b132
        entry.destructor = pkix_pl_InfoAccess_Destroy;
Packit 40b132
        entry.equalsFunction = pkix_pl_InfoAccess_Equals;
Packit 40b132
        entry.hashcodeFunction = pkix_pl_InfoAccess_Hashcode;
Packit 40b132
        entry.toStringFunction = pkix_pl_InfoAccess_ToString;
Packit 40b132
        entry.comparator = NULL;
Packit 40b132
        entry.duplicateFunction = pkix_duplicateImmutable;
Packit 40b132
Packit 40b132
        systemClasses[PKIX_INFOACCESS_TYPE] = entry;
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_pl_InfoAccess_CreateList
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  Based on data in CERTAuthInfoAccess array "nssInfoAccess", this function
Packit 40b132
 *  creates and returns a PKIX_List of PKIX_PL_InfoAccess at "pInfoAccessList".
Packit 40b132
 *
Packit 40b132
 * PARAMETERS
Packit 40b132
 *  "nssInfoAccess"
Packit 40b132
 *      The pointer array of CERTAuthInfoAccess that contains access data.
Packit 40b132
 *      May be NULL.
Packit 40b132
 *  "pInfoAccessList"
Packit 40b132
 *      Address where a list of PKIX_PL_InfoAccess is returned.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_pl_InfoAccess_CreateList(
Packit 40b132
        CERTAuthInfoAccess **nssInfoAccess,
Packit 40b132
        PKIX_List **pInfoAccessList, /* of PKIX_PL_InfoAccess */
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_List *infoAccessList = NULL;
Packit 40b132
        PKIX_PL_InfoAccess *infoAccess = NULL;
Packit 40b132
        PKIX_PL_GeneralName *location = NULL;
Packit 40b132
        PKIX_UInt32 method;
Packit 40b132
        int i;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_CreateList");
Packit 40b132
        PKIX_NULLCHECK_ONE(pInfoAccessList);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_List_Create(&infoAccessList, plContext),
Packit 40b132
                PKIX_LISTCREATEFAILED);
Packit 40b132
Packit 40b132
        if (nssInfoAccess == NULL) {
Packit 40b132
                goto cleanup;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        for (i = 0; nssInfoAccess[i] != NULL; i++) {
Packit 40b132
Packit 40b132
                if (nssInfoAccess[i]->location == NULL) {
Packit 40b132
                    continue;
Packit 40b132
                }
Packit 40b132
Packit 40b132
                PKIX_CHECK(pkix_pl_GeneralName_Create
Packit 40b132
                        (nssInfoAccess[i]->location, &location, plContext),
Packit 40b132
                        PKIX_GENERALNAMECREATEFAILED);
Packit 40b132
Packit 40b132
                PKIX_CERT_DEBUG("\t\tCalling SECOID_FindOIDTag).\n");
Packit 40b132
                method = SECOID_FindOIDTag(&nssInfoAccess[i]->method);
Packit 40b132
                /* Map NSS access method value into PKIX constant */
Packit 40b132
                switch(method) {
Packit 40b132
                        case SEC_OID_PKIX_CA_ISSUERS:
Packit 40b132
                                method = PKIX_INFOACCESS_CA_ISSUERS;
Packit 40b132
                                break;
Packit 40b132
                        case SEC_OID_PKIX_OCSP:
Packit 40b132
                                method = PKIX_INFOACCESS_OCSP;
Packit 40b132
                                break;
Packit 40b132
                        case SEC_OID_PKIX_TIMESTAMPING:
Packit 40b132
                                method = PKIX_INFOACCESS_TIMESTAMPING;
Packit 40b132
                                break;
Packit 40b132
                        case SEC_OID_PKIX_CA_REPOSITORY:
Packit 40b132
                                method = PKIX_INFOACCESS_CA_REPOSITORY;
Packit 40b132
                                break;
Packit 40b132
                        default:
Packit 40b132
                                PKIX_ERROR(PKIX_UNKNOWNINFOACCESSMETHOD);
Packit 40b132
                }
Packit 40b132
Packit 40b132
                PKIX_CHECK(pkix_pl_InfoAccess_Create
Packit 40b132
                        (method, location, &infoAccess, plContext),
Packit 40b132
                        PKIX_INFOACCESSCREATEFAILED);
Packit 40b132
Packit 40b132
                PKIX_CHECK(PKIX_List_AppendItem
Packit 40b132
                            (infoAccessList,
Packit 40b132
                            (PKIX_PL_Object *)infoAccess,
Packit 40b132
                            plContext),
Packit 40b132
                            PKIX_LISTAPPENDITEMFAILED);
Packit 40b132
                PKIX_DECREF(infoAccess);
Packit 40b132
                PKIX_DECREF(location);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        *pInfoAccessList = infoAccessList;
Packit 40b132
        infoAccessList = NULL;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_DECREF(infoAccessList);
Packit 40b132
        PKIX_DECREF(infoAccess);
Packit 40b132
        PKIX_DECREF(location);
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
/* --Public-Functions------------------------------------------------------- */
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: PKIX_PL_InfoAccess_GetMethod (see comments in pkix_pl_pki.h)
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
PKIX_PL_InfoAccess_GetMethod(
Packit 40b132
        PKIX_PL_InfoAccess *infoAccess,
Packit 40b132
        PKIX_UInt32 *pMethod,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetMethod");
Packit 40b132
        PKIX_NULLCHECK_TWO(infoAccess, pMethod);
Packit 40b132
Packit 40b132
        *pMethod = infoAccess->method;
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: PKIX_PL_InfoAccess_GetLocation (see comments in pkix_pl_pki.h)
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
PKIX_PL_InfoAccess_GetLocation(
Packit 40b132
        PKIX_PL_InfoAccess *infoAccess,
Packit 40b132
        PKIX_PL_GeneralName **pLocation,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetLocation");
Packit 40b132
        PKIX_NULLCHECK_TWO(infoAccess, pLocation);
Packit 40b132
Packit 40b132
        PKIX_INCREF(infoAccess->location);
Packit 40b132
Packit 40b132
        *pLocation = infoAccess->location;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: PKIX_PL_InfoAccess_GetLocationType (see comments in pkix_pl_pki.h)
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
PKIX_PL_InfoAccess_GetLocationType(
Packit 40b132
        PKIX_PL_InfoAccess *infoAccess,
Packit 40b132
        PKIX_UInt32 *pType,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_PL_String *locationString = NULL;
Packit 40b132
        PKIX_UInt32 type = PKIX_INFOACCESS_LOCATION_UNKNOWN;
Packit 40b132
        PKIX_UInt32 len = 0;
Packit 40b132
        void *location = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetLocationType");
Packit 40b132
        PKIX_NULLCHECK_TWO(infoAccess, pType);
Packit 40b132
Packit 40b132
        if (infoAccess->location != NULL) {
Packit 40b132
Packit 40b132
                PKIX_TOSTRING(infoAccess->location, &locationString, plContext,
Packit 40b132
                    PKIX_GENERALNAMETOSTRINGFAILED);
Packit 40b132
Packit 40b132
                PKIX_CHECK(PKIX_PL_String_GetEncoded
Packit 40b132
                    (locationString, PKIX_ESCASCII, &location, &len, plContext),
Packit 40b132
                    PKIX_STRINGGETENCODEDFAILED);
Packit 40b132
Packit 40b132
                PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n");
Packit 40b132
#ifndef NSS_PKIX_NO_LDAP
Packit 40b132
                if (PORT_Strncmp(location, "ldap:", 5) == 0){
Packit 40b132
                        type = PKIX_INFOACCESS_LOCATION_LDAP;
Packit 40b132
                } else
Packit 40b132
#endif
Packit 40b132
                if (PORT_Strncmp(location, "http:", 5) == 0){
Packit 40b132
                        type = PKIX_INFOACCESS_LOCATION_HTTP;
Packit 40b132
                }
Packit 40b132
        }
Packit 40b132
Packit 40b132
        *pType = type;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_PL_Free(location, plContext);
Packit 40b132
        PKIX_DECREF(locationString);
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
#ifndef NSS_PKIX_NO_LDAP
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_pl_InfoAccess_ParseTokens
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  This function parses the string beginning at "startPos" into tokens using
Packit 40b132
 *  the separator contained in "separator" and the terminator contained in
Packit 40b132
 *  "terminator", copying the tokens into space allocated from the arena
Packit 40b132
 *  pointed to by "arena". It stores in "tokens" a null-terminated array of
Packit 40b132
 *  pointers to those tokens.
Packit 40b132
 *
Packit 40b132
 * PARAMETERS
Packit 40b132
 *  "arena"
Packit 40b132
 *      Address of a PLArenaPool to be used in populating the LDAPLocation.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "startPos"
Packit 40b132
 *      The address of char string that contains a subset of ldap location.
Packit 40b132
 *  "tokens"
Packit 40b132
 *      The address of an array of char string for storing returned tokens.
Packit 40b132
 *      Must be non-NULL.
Packit 40b132
 *  "separator"
Packit 40b132
 *      The character that is taken as token separator. Must be non-NULL.
Packit 40b132
 *  "terminator"
Packit 40b132
 *      The character that is taken as parsing terminator. Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an InfoAccess Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
static PKIX_Error *
Packit 40b132
pkix_pl_InfoAccess_ParseTokens(
Packit 40b132
        PLArenaPool *arena,
Packit 40b132
        char **startPos, /* return update */
Packit 40b132
        char ***tokens,
Packit 40b132
        char separator,
Packit 40b132
        char terminator,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_UInt32 numFilters = 0;
Packit 40b132
        char *endPos = NULL;
Packit 40b132
        char **filterP = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseTokens");
Packit 40b132
        PKIX_NULLCHECK_THREE(arena, startPos, tokens);
Packit 40b132
Packit 40b132
        endPos = *startPos;
Packit 40b132
Packit 40b132
        /* First pass: parse to <terminator> to count number of components */
Packit 40b132
        numFilters = 0;
Packit 40b132
        while (*endPos != terminator && *endPos != '\0') {
Packit 40b132
                endPos++;
Packit 40b132
                if (*endPos == separator) {
Packit 40b132
                        numFilters++;
Packit 40b132
                }
Packit 40b132
        }
Packit 40b132
Packit 40b132
        if (*endPos != terminator) {
Packit 40b132
                PKIX_ERROR(PKIX_LOCATIONSTRINGNOTPROPERLYTERMINATED);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        /* Last component doesn't need a separator, although we allow it */
Packit 40b132
        if (endPos > *startPos && *(endPos-1) != separator) {
Packit 40b132
                numFilters++;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        /*
Packit 40b132
         * If string is a=xx, b=yy, c=zz, etc., use a=xx for filter,
Packit 40b132
         * and everything else for the base
Packit 40b132
         */
Packit 40b132
        if (numFilters > 2) numFilters = 2;
Packit 40b132
Packit 40b132
        filterP = PORT_ArenaZNewArray(arena, char*, numFilters+1);
Packit 40b132
        if (filterP == NULL) {
Packit 40b132
            PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        /* Second pass: parse to fill in components in token array */
Packit 40b132
        *tokens = filterP;
Packit 40b132
        endPos = *startPos;
Packit 40b132
Packit 40b132
        while (numFilters) {
Packit 40b132
            if (*endPos == separator || *endPos == terminator) {
Packit 40b132
                    PKIX_UInt32 len = endPos - *startPos;
Packit 40b132
                    char *p = PORT_ArenaZAlloc(arena, len+1);
Packit 40b132
                    if (p == NULL) {
Packit 40b132
                        PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
Packit 40b132
                    }
Packit 40b132
Packit 40b132
                    PORT_Memcpy(p, *startPos, len);
Packit 40b132
                    p[len] = '\0';
Packit 40b132
Packit 40b132
                    *filterP = p;
Packit 40b132
                    filterP++;
Packit 40b132
                    numFilters--;
Packit 40b132
Packit 40b132
                    separator = terminator;
Packit 40b132
Packit 40b132
                    if (*endPos == '\0') {
Packit 40b132
                        *startPos = endPos;
Packit 40b132
                        break;
Packit 40b132
                    } else {
Packit 40b132
                        endPos++;
Packit 40b132
                        *startPos = endPos;
Packit 40b132
                        continue;
Packit 40b132
                    }
Packit 40b132
            }
Packit 40b132
            endPos++;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        *filterP = NULL;
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
Packit 40b132
static int
Packit 40b132
pkix_pl_HexDigitToInt(
Packit 40b132
        int ch)
Packit 40b132
{
Packit 40b132
        if (isdigit(ch)) {
Packit 40b132
                ch = ch - '0';
Packit 40b132
        } else if (isupper(ch)) {
Packit 40b132
                ch = ch - 'A' + 10;
Packit 40b132
        } else {
Packit 40b132
                ch = ch - 'a' + 10;
Packit 40b132
        }
Packit 40b132
        return ch;
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * Convert the "%" hex hex escape sequences in the URL 'location' in place.
Packit 40b132
 */
Packit 40b132
static void
Packit 40b132
pkix_pl_UnescapeURL(
Packit 40b132
        char *location)
Packit 40b132
{
Packit 40b132
        const char *src;
Packit 40b132
        char *dst;
Packit 40b132
Packit 40b132
        for (src = dst = location; *src != '\0'; src++, dst++) {
Packit 40b132
                if (*src == '%' && isxdigit((unsigned char)*(src+1)) &&
Packit 40b132
                    isxdigit((unsigned char)*(src+2))) {
Packit 40b132
                        *dst = pkix_pl_HexDigitToInt((unsigned char)*(src+1));
Packit 40b132
                        *dst *= 16;
Packit 40b132
                        *dst += pkix_pl_HexDigitToInt((unsigned char)*(src+2));
Packit 40b132
                        src += 2;
Packit 40b132
                } else {
Packit 40b132
                        *dst = *src;
Packit 40b132
                }
Packit 40b132
        }
Packit 40b132
        *dst = *src;  /* the terminating null */
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * FUNCTION: pkix_pl_InfoAccess_ParseLocation
Packit 40b132
 * DESCRIPTION:
Packit 40b132
 *
Packit 40b132
 *  This function parses the GeneralName pointed to by "generalName" into the
Packit 40b132
 *  fields of the LDAPRequestParams pointed to by "request" and a domainName
Packit 40b132
 *  pointed to by "pDomainName", using the PLArenaPool pointed to by "arena" to
Packit 40b132
 *  allocate storage for the request components and for the domainName string.
Packit 40b132
 *
Packit 40b132
 *  The expected GeneralName string should be in the format described by the
Packit 40b132
 *  following BNF:
Packit 40b132
 *
Packit 40b132
 *  ldap://<ldap-server-site>/[cn=<cname>][,o=<org>][,c=<country>]?
Packit 40b132
 *  [caCertificate|crossCertificatPair|certificateRevocationList];
Packit 40b132
 *  [binary|<other-type>]
Packit 40b132
 *  [[,caCertificate|crossCertificatPair|certificateRevocationList]
Packit 40b132
 *   [binary|<other-type>]]*
Packit 40b132
 *
Packit 40b132
 * PARAMETERS
Packit 40b132
 *  "generalName"
Packit 40b132
 *      Address of the GeneralName whose LDAPLocation is to be parsed. Must be
Packit 40b132
 *      non-NULL.
Packit 40b132
 *  "arena"
Packit 40b132
 *      Address of PLArenaPool to be used for the domainName and for components
Packit 40b132
 *      of the LDAPRequest. Must be non-NULL.
Packit 40b132
 *  "request"
Packit 40b132
 *      Address of the LDAPRequestParams into which request components are
Packit 40b132
 *      stored. Must be non-NULL.
Packit 40b132
 *  *pDomainName"
Packit 40b132
 *      Address at which the domainName is stored. Must be non-NULL.
Packit 40b132
 *  "plContext"
Packit 40b132
 *      Platform-specific context pointer.
Packit 40b132
 * THREAD SAFETY:
Packit 40b132
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
Packit 40b132
 * RETURNS:
Packit 40b132
 *  Returns NULL if the function succeeds.
Packit 40b132
 *  Returns an InfoAccess Error if the function fails in a non-fatal way.
Packit 40b132
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
Packit 40b132
 */
Packit 40b132
PKIX_Error *
Packit 40b132
pkix_pl_InfoAccess_ParseLocation(
Packit 40b132
        PKIX_PL_GeneralName *generalName,
Packit 40b132
        PLArenaPool *arena,
Packit 40b132
        LDAPRequestParams *request,
Packit 40b132
        char **pDomainName,
Packit 40b132
        void *plContext)
Packit 40b132
{
Packit 40b132
        PKIX_PL_String *locationString = NULL;
Packit 40b132
        PKIX_UInt32 len = 0;
Packit 40b132
        PKIX_UInt32 ncIndex = 0;
Packit 40b132
        char *domainName = NULL;
Packit 40b132
        char **avaArray = NULL;
Packit 40b132
        char **attrArray = NULL;
Packit 40b132
        char *attr = NULL;
Packit 40b132
        char *locationAscii = NULL;
Packit 40b132
        char *startPos = NULL;
Packit 40b132
        char *endPos = NULL;
Packit 40b132
        char *avaPtr = NULL;
Packit 40b132
        LdapAttrMask attrBit = 0;
Packit 40b132
        LDAPNameComponent **setOfNameComponent = NULL;
Packit 40b132
        LDAPNameComponent *nameComponent = NULL;
Packit 40b132
Packit 40b132
        PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseLocation");
Packit 40b132
        PKIX_NULLCHECK_FOUR(generalName, arena, request, pDomainName);
Packit 40b132
Packit 40b132
        PKIX_TOSTRING(generalName, &locationString, plContext,
Packit 40b132
                PKIX_GENERALNAMETOSTRINGFAILED);
Packit 40b132
Packit 40b132
        PKIX_CHECK(PKIX_PL_String_GetEncoded
Packit 40b132
                (locationString,
Packit 40b132
                PKIX_ESCASCII,
Packit 40b132
                (void **)&locationAscii,
Packit 40b132
                &len,
Packit 40b132
                plContext),
Packit 40b132
                PKIX_STRINGGETENCODEDFAILED);
Packit 40b132
Packit 40b132
        pkix_pl_UnescapeURL(locationAscii);
Packit 40b132
Packit 40b132
        /* Skip "ldap:" */
Packit 40b132
        endPos = locationAscii;
Packit 40b132
        while (*endPos != ':' && *endPos != '\0') {
Packit 40b132
                endPos++;
Packit 40b132
        }
Packit 40b132
        if (*endPos == '\0') {
Packit 40b132
                PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGLOCATIONTYPE);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        /* Skip "//" */
Packit 40b132
        endPos++;
Packit 40b132
        if (*endPos != '\0' && *(endPos+1) != '0' &&
Packit 40b132
            *endPos == '/' && *(endPos+1) == '/') {
Packit 40b132
                endPos += 2;
Packit 40b132
        } else {
Packit 40b132
                PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGDOUBLESLASH);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        /* Get the server-site */
Packit 40b132
        startPos = endPos;
Packit 40b132
        while(*endPos != '/' && *(endPos) != '\0') {
Packit 40b132
                endPos++;
Packit 40b132
        }
Packit 40b132
        if (*endPos == '\0') {
Packit 40b132
                PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGSERVERSITE);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        len = endPos - startPos;
Packit 40b132
        endPos++;
Packit 40b132
Packit 40b132
        domainName = PORT_ArenaZAlloc(arena, len + 1);
Packit 40b132
        if (!domainName) {
Packit 40b132
            PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        PORT_Memcpy(domainName, startPos, len);
Packit 40b132
Packit 40b132
        domainName[len] = '\0';
Packit 40b132
Packit 40b132
        *pDomainName = domainName;
Packit 40b132
Packit 40b132
        /*
Packit 40b132
         * Get a list of AttrValueAssertions (such as 
Packit 40b132
         * "cn=CommonName, o=Organization, c=US" into a null-terminated array
Packit 40b132
         */
Packit 40b132
        startPos = endPos;
Packit 40b132
        PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
Packit 40b132
                (arena,
Packit 40b132
                &startPos,
Packit 40b132
                (char ***) &avaArray,
Packit 40b132
                ',',
Packit 40b132
                '?',
Packit 40b132
                plContext),
Packit 40b132
                PKIX_INFOACCESSPARSETOKENSFAILED);
Packit 40b132
Packit 40b132
        /* Count how many AVAs we have */
Packit 40b132
        for (len = 0; avaArray[len] != NULL; len++) {}
Packit 40b132
Packit 40b132
        if (len < 2) {
Packit 40b132
                PKIX_ERROR(PKIX_NOTENOUGHNAMECOMPONENTSINGENERALNAME);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        /* Use last name component for baseObject */
Packit 40b132
        request->baseObject = avaArray[len - 1];
Packit 40b132
Packit 40b132
        /* Use only one component for filter. LDAP servers aren't too smart. */
Packit 40b132
        len = 2;   /* Eliminate this when servers get smarter. */
Packit 40b132
Packit 40b132
        avaArray[len - 1] = NULL;
Packit 40b132
Packit 40b132
        /* Get room for null-terminated array of (LdapNameComponent *) */
Packit 40b132
        setOfNameComponent = PORT_ArenaZNewArray(arena, LDAPNameComponent *, len);
Packit 40b132
        if (setOfNameComponent == NULL) {
Packit 40b132
            PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        /* Get room for the remaining LdapNameComponents */
Packit 40b132
        nameComponent = PORT_ArenaZNewArray(arena, LDAPNameComponent, --len);
Packit 40b132
        if (nameComponent == NULL) {
Packit 40b132
            PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
Packit 40b132
        }
Packit 40b132
Packit 40b132
        /* Convert remaining AVAs to LDAPNameComponents */
Packit 40b132
        for (ncIndex = 0; ncIndex < len; ncIndex ++) {
Packit 40b132
                setOfNameComponent[ncIndex] = nameComponent;
Packit 40b132
                avaPtr = avaArray[ncIndex];
Packit 40b132
                nameComponent->attrType = (unsigned char *)avaPtr;
Packit 40b132
                while ((*avaPtr != '=') && (*avaPtr != '\0')) {
Packit 40b132
                        avaPtr++;
Packit 40b132
                        if (*avaPtr == '\0') {
Packit 40b132
                                PKIX_ERROR(PKIX_NAMECOMPONENTWITHNOEQ);
Packit 40b132
                        }
Packit 40b132
                }
Packit 40b132
                *(avaPtr++) = '\0';
Packit 40b132
                nameComponent->attrValue = (unsigned char *)avaPtr;
Packit 40b132
                nameComponent++;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        setOfNameComponent[len] = NULL;
Packit 40b132
        request->nc = setOfNameComponent;
Packit 40b132
                
Packit 40b132
        /*
Packit 40b132
         * Get a list of AttrTypes (such as 
Packit 40b132
         * "caCertificate;binary, crossCertificatePair;binary") into
Packit 40b132
         * a null-terminated array
Packit 40b132
         */
Packit 40b132
Packit 40b132
        PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
Packit 40b132
                (arena,
Packit 40b132
                (char **) &startPos,
Packit 40b132
                (char ***) &attrArray,
Packit 40b132
                ',',
Packit 40b132
                '\0',
Packit 40b132
                plContext),
Packit 40b132
                PKIX_INFOACCESSPARSETOKENSFAILED);
Packit 40b132
Packit 40b132
        /* Convert array of Attr Types into a bit mask */
Packit 40b132
        request->attributes = 0;
Packit 40b132
        attr = attrArray[0];
Packit 40b132
        while (attr != NULL) {
Packit 40b132
                PKIX_CHECK(pkix_pl_LdapRequest_AttrStringToBit
Packit 40b132
                        (attr, &attrBit, plContext),
Packit 40b132
                        PKIX_LDAPREQUESTATTRSTRINGTOBITFAILED);
Packit 40b132
                request->attributes |= attrBit;
Packit 40b132
                attr = *(++attrArray);
Packit 40b132
        }
Packit 40b132
Packit 40b132
cleanup:
Packit 40b132
Packit 40b132
        PKIX_PL_Free(locationAscii, plContext);
Packit 40b132
        PKIX_DECREF(locationString);
Packit 40b132
Packit 40b132
        PKIX_RETURN(INFOACCESS);
Packit 40b132
}
Packit 40b132
#endif /* !NSS_PKIX_NO_LDAP */