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