1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_pl_infoaccess.c
40 * InfoAccess Object Definitions
44 #include "pkix_pl_infoaccess.h"
46 /* XXX Following SEC_OID_PKIX defines should be merged in NSS */
47 #define SEC_OID_PKIX_CA_REPOSITORY 1003
48 #define SEC_OID_PKIX_TIMESTAMPING 1005
49 /* XXX Following OID defines hould be moved to NSS */
50 static const unsigned char siaTimeStampingOID
[] = {0x2b, 0x06, 0x01, 0x05,
51 0x05, 0x07, 0x030, 0x03};
52 static const unsigned char siaCaRepositoryOID
[] = {0x2b, 0x06, 0x01, 0x05,
53 0x05, 0x07, 0x030, 0x05};
56 /* --Private-InfoAccess-Functions----------------------------------*/
59 * FUNCTION: pkix_pl_InfoAccess_Create
62 * This function creates an InfoAccess from the method provided in "method" and
63 * the GeneralName provided in "generalName" and stores the result at
68 * The UInt32 value to be stored as the method field of the InfoAccess.
70 * The GeneralName to be stored as the generalName field of the InfoAccess.
73 * Address where the result is stored. Must be non-NULL.
75 * Platform-specific context pointer.
77 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
79 * Returns NULL if the function succeeds.
80 * Returns a Fatal Error if the function fails in an unrecoverable way.
83 pkix_pl_InfoAccess_Create(
85 PKIX_PL_GeneralName
*generalName
,
86 PKIX_PL_InfoAccess
**pInfoAccess
,
90 PKIX_PL_InfoAccess
*infoAccess
= NULL
;
92 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_Create");
93 PKIX_NULLCHECK_TWO(generalName
, pInfoAccess
);
95 PKIX_CHECK(PKIX_PL_Object_Alloc
96 (PKIX_INFOACCESS_TYPE
,
97 sizeof (PKIX_PL_InfoAccess
),
98 (PKIX_PL_Object
**)&infoAccess
,
100 PKIX_COULDNOTCREATEINFOACCESSOBJECT
);
102 infoAccess
->method
= method
;
104 PKIX_INCREF(generalName
);
105 infoAccess
->location
= generalName
;
107 *pInfoAccess
= infoAccess
;
111 PKIX_RETURN(INFOACCESS
);
115 * FUNCTION: pkix_pl_InfoAccess_Destroy
116 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h)
119 pkix_pl_InfoAccess_Destroy(
120 PKIX_PL_Object
*object
,
123 PKIX_PL_InfoAccess
*infoAccess
= NULL
;
125 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_Destroy");
126 PKIX_NULLCHECK_ONE(object
);
128 PKIX_CHECK(pkix_CheckType(object
, PKIX_INFOACCESS_TYPE
, plContext
),
129 PKIX_OBJECTNOTANINFOACCESS
);
131 infoAccess
= (PKIX_PL_InfoAccess
*)object
;
133 PKIX_DECREF(infoAccess
->location
);
137 PKIX_RETURN(INFOACCESS
);
141 * FUNCTION: pkix_pl_InfoAccess_ToString
142 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_pki.h)
145 pkix_pl_InfoAccess_ToString(
146 PKIX_PL_Object
*object
,
147 PKIX_PL_String
**pString
,
150 PKIX_PL_InfoAccess
*infoAccess
;
151 PKIX_PL_String
*infoAccessString
= NULL
;
152 char *asciiFormat
= NULL
;
153 char *asciiMethod
= NULL
;
154 PKIX_PL_String
*formatString
= NULL
;
155 PKIX_PL_String
*methodString
= NULL
;
156 PKIX_PL_String
*locationString
= NULL
;
158 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_ToString");
159 PKIX_NULLCHECK_TWO(object
, pString
);
161 PKIX_CHECK(pkix_CheckType
162 (object
, PKIX_INFOACCESS_TYPE
, plContext
),
163 PKIX_OBJECTNOTINFOACCESS
);
165 infoAccess
= (PKIX_PL_InfoAccess
*)object
;
173 PKIX_CHECK(PKIX_PL_String_Create
179 PKIX_STRINGCREATEFAILED
);
181 switch(infoAccess
->method
) {
182 case PKIX_INFOACCESS_CA_ISSUERS
:
183 asciiMethod
= "caIssuers";
185 case PKIX_INFOACCESS_OCSP
:
186 asciiMethod
= "ocsp";
188 case PKIX_INFOACCESS_TIMESTAMPING
:
189 asciiMethod
= "timestamping";
191 case PKIX_INFOACCESS_CA_REPOSITORY
:
192 asciiMethod
= "caRepository";
195 asciiMethod
= "unknown";
198 PKIX_CHECK(PKIX_PL_String_Create
204 PKIX_STRINGCREATEFAILED
);
206 PKIX_TOSTRING(infoAccess
->location
, &locationString
, plContext
,
207 PKIX_GENERALNAMETOSTRINGFAILED
);
209 PKIX_CHECK(PKIX_PL_Sprintf
217 *pString
= infoAccessString
;
221 PKIX_DECREF(formatString
);
222 PKIX_DECREF(methodString
);
223 PKIX_DECREF(locationString
);
225 PKIX_RETURN(INFOACCESS
);
229 * FUNCTION: pkix_pl_InfoAccess_Hashcode
230 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_pki.h)
233 pkix_pl_InfoAccess_Hashcode(
234 PKIX_PL_Object
*object
,
235 PKIX_UInt32
*pHashcode
,
238 PKIX_PL_InfoAccess
*infoAccess
= NULL
;
239 PKIX_UInt32 infoAccessHash
;
241 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_Hashcode");
242 PKIX_NULLCHECK_TWO(object
, pHashcode
);
244 PKIX_CHECK(pkix_CheckType
245 (object
, PKIX_INFOACCESS_TYPE
, plContext
),
246 PKIX_OBJECTNOTINFOACCESS
);
248 infoAccess
= (PKIX_PL_InfoAccess
*)object
;
250 PKIX_HASHCODE(infoAccess
->location
, &infoAccessHash
, plContext
,
251 PKIX_OBJECTHASHCODEFAILED
);
253 infoAccessHash
+= (infoAccess
->method
<< 7);
255 *pHashcode
= infoAccessHash
;
259 PKIX_RETURN(INFOACCESS
);
264 * FUNCTION: pkix_pl_InfoAccess_Equals
265 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_pki.h)
268 pkix_pl_InfoAccess_Equals(
269 PKIX_PL_Object
*firstObject
,
270 PKIX_PL_Object
*secondObject
,
271 PKIX_Boolean
*pResult
,
274 PKIX_PL_InfoAccess
*firstInfoAccess
= NULL
;
275 PKIX_PL_InfoAccess
*secondInfoAccess
= NULL
;
276 PKIX_UInt32 secondType
;
277 PKIX_Boolean cmpResult
;
279 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_Equals");
280 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
282 /* test that firstObject is a InfoAccess */
283 PKIX_CHECK(pkix_CheckType
284 (firstObject
, PKIX_INFOACCESS_TYPE
, plContext
),
285 PKIX_FIRSTOBJECTNOTINFOACCESS
);
288 * Since we know firstObject is a InfoAccess, if both references are
289 * identical, they must be equal
291 if (firstObject
== secondObject
){
292 *pResult
= PKIX_TRUE
;
297 * If secondObject isn't a InfoAccess, we don't throw an error.
298 * We simply return a Boolean result of FALSE
300 *pResult
= PKIX_FALSE
;
301 PKIX_CHECK(PKIX_PL_Object_GetType
302 (secondObject
, &secondType
, plContext
),
303 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT
);
304 if (secondType
!= PKIX_INFOACCESS_TYPE
) goto cleanup
;
306 firstInfoAccess
= (PKIX_PL_InfoAccess
*)firstObject
;
307 secondInfoAccess
= (PKIX_PL_InfoAccess
*)secondObject
;
309 *pResult
= PKIX_FALSE
;
311 if (firstInfoAccess
->method
!= secondInfoAccess
->method
) {
315 PKIX_EQUALS(firstInfoAccess
, secondInfoAccess
, &cmpResult
, plContext
,
316 PKIX_OBJECTEQUALSFAILED
);
318 *pResult
= cmpResult
;
322 PKIX_RETURN(INFOACCESS
);
326 * FUNCTION: pkix_pl_InfoAccess_RegisterSelf
328 * Registers PKIX_INFOACCESS_TYPE and its related functions with systemClasses[]
330 * Not Thread Safe - for performance and complexity reasons
332 * Since this function is only called by PKIX_PL_Initialize, which should
333 * only be called once, it is acceptable that this function is not
337 pkix_pl_InfoAccess_RegisterSelf(void *plContext
)
339 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
340 pkix_ClassTable_Entry entry
;
342 PKIX_ENTER(INFOACCESS
,
343 "pkix_pl_InfoAccess_RegisterSelf");
345 entry
.description
= "InfoAccess";
346 entry
.destructor
= pkix_pl_InfoAccess_Destroy
;
347 entry
.equalsFunction
= pkix_pl_InfoAccess_Equals
;
348 entry
.hashcodeFunction
= pkix_pl_InfoAccess_Hashcode
;
349 entry
.toStringFunction
= pkix_pl_InfoAccess_ToString
;
350 entry
.comparator
= NULL
;
351 entry
.duplicateFunction
= pkix_duplicateImmutable
;
353 systemClasses
[PKIX_INFOACCESS_TYPE
] = entry
;
355 PKIX_RETURN(INFOACCESS
);
359 * FUNCTION: pkix_pl_InfoAccess_CreateList
362 * Based on data in CERTAuthInfoAccess array "nssInfoAccess", this function
363 * creates and returns a PKIX_List of PKIX_PL_InfoAccess at "pInfoAccessList".
367 * The pointer array of CERTAuthInfoAccess that contains access data.
370 * Address where a list of PKIX_PL_InfoAccess is returned.
373 * Platform-specific context pointer.
375 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
377 * Returns NULL if the function succeeds.
378 * Returns a Fatal Error if the function fails in an unrecoverable way.
381 pkix_pl_InfoAccess_CreateList(
382 CERTAuthInfoAccess
**nssInfoAccess
,
383 PKIX_List
**pInfoAccessList
, /* of PKIX_PL_InfoAccess */
386 PKIX_List
*infoAccessList
= NULL
;
387 PKIX_PL_InfoAccess
*infoAccess
= NULL
;
388 PKIX_PL_GeneralName
*location
= NULL
;
392 PKIX_ENTER(INFOACCESS
, "PKIX_PL_InfoAccess_CreateList");
393 PKIX_NULLCHECK_ONE(pInfoAccessList
);
395 PKIX_CHECK(PKIX_List_Create(&infoAccessList
, plContext
),
396 PKIX_LISTCREATEFAILED
);
398 *pInfoAccessList
= infoAccessList
;
400 if (nssInfoAccess
== NULL
) {
404 for (i
= 0; nssInfoAccess
[i
] != NULL
; i
++) {
406 if (nssInfoAccess
[i
]->location
== NULL
) {
410 PKIX_CHECK(pkix_pl_GeneralName_Create
411 (nssInfoAccess
[i
]->location
, &location
, plContext
),
412 PKIX_GENERALNAMECREATEFAILED
);
414 PKIX_CERT_DEBUG("\t\tCalling SECOID_FindOIDTag).\n");
415 method
= SECOID_FindOIDTag(&nssInfoAccess
[i
]->method
);
420 * This part of code is definitely hacking, need NSS decode
421 * support. We can reuse the CERT_DecodeAuthInfoAccessExtension
422 * since SIA and AIA are all the same type. However NSS need
423 * to add SIA, CaRepository, TimeStamping OID definitions and
424 * the numerical method, timeStamping and caRepository values.
426 * We assume now, since method is 0, implies the method for SIA
427 * was not decoded by CERT_DecodeAuthInfoAccessExtension()
428 * so we compare and put value in. This part should be taken
429 * out eventually if CERT_DecodeInfoAccessExtension (*renamed*)
433 PKIX_CERT_DEBUG("\t\tCalling PORT_Strncmp).\n");
435 ((char *)nssInfoAccess
[i
]->method
.data
,
436 (char *)siaTimeStampingOID
,
437 nssInfoAccess
[i
]->method
.len
) == 0) {
438 method
= SEC_OID_PKIX_TIMESTAMPING
;
439 } else if (PORT_Strncmp
440 ((char *)nssInfoAccess
[i
]->method
.data
,
441 (char *)siaCaRepositoryOID
,
442 nssInfoAccess
[i
]->method
.len
) == 0) {
443 method
= SEC_OID_PKIX_CA_REPOSITORY
;
447 /* Map NSS access method value into PKIX constant */
449 case SEC_OID_PKIX_CA_ISSUERS
:
450 method
= PKIX_INFOACCESS_CA_ISSUERS
;
452 case SEC_OID_PKIX_OCSP
:
453 method
= PKIX_INFOACCESS_OCSP
;
455 case SEC_OID_PKIX_TIMESTAMPING
:
456 method
= PKIX_INFOACCESS_TIMESTAMPING
;
458 case SEC_OID_PKIX_CA_REPOSITORY
:
459 method
= PKIX_INFOACCESS_CA_REPOSITORY
;
465 PKIX_CHECK(pkix_pl_InfoAccess_Create
466 (method
, location
, &infoAccess
, plContext
),
467 PKIX_INFOACCESSCREATEFAILED
);
469 PKIX_CHECK(PKIX_List_AppendItem
471 (PKIX_PL_Object
*)infoAccess
,
473 PKIX_LISTAPPENDITEMFAILED
);
474 PKIX_DECREF(infoAccess
);
477 *pInfoAccessList
= infoAccessList
;
481 PKIX_DECREF(infoAccess
);
482 PKIX_DECREF(location
);
484 PKIX_RETURN(INFOACCESS
);
487 /* --Public-Functions------------------------------------------------------- */
490 * FUNCTION: PKIX_PL_InfoAccess_GetMethod (see comments in pkix_pl_pki.h)
493 PKIX_PL_InfoAccess_GetMethod(
494 PKIX_PL_InfoAccess
*infoAccess
,
495 PKIX_UInt32
*pMethod
,
498 PKIX_ENTER(INFOACCESS
, "PKIX_PL_InfoAccess_GetMethod");
499 PKIX_NULLCHECK_TWO(infoAccess
, pMethod
);
501 *pMethod
= infoAccess
->method
;
503 PKIX_RETURN(INFOACCESS
);
507 * FUNCTION: PKIX_PL_InfoAccess_GetLocation (see comments in pkix_pl_pki.h)
510 PKIX_PL_InfoAccess_GetLocation(
511 PKIX_PL_InfoAccess
*infoAccess
,
512 PKIX_PL_GeneralName
**pLocation
,
515 PKIX_ENTER(INFOACCESS
, "PKIX_PL_InfoAccess_GetLocation");
516 PKIX_NULLCHECK_TWO(infoAccess
, pLocation
);
518 PKIX_INCREF(infoAccess
->location
);
520 *pLocation
= infoAccess
->location
;
522 PKIX_RETURN(INFOACCESS
);
526 * FUNCTION: PKIX_PL_InfoAccess_GetLocationType (see comments in pkix_pl_pki.h)
529 PKIX_PL_InfoAccess_GetLocationType(
530 PKIX_PL_InfoAccess
*infoAccess
,
534 PKIX_PL_String
*locationString
= NULL
;
535 PKIX_UInt32 type
= PKIX_INFOACCESS_LOCATION_UNKNOWN
;
537 void *location
= NULL
;
539 PKIX_ENTER(INFOACCESS
, "PKIX_PL_InfoAccess_GetLocationType");
540 PKIX_NULLCHECK_TWO(infoAccess
, pType
);
542 if (infoAccess
->location
!= NULL
) {
544 PKIX_TOSTRING(infoAccess
->location
, &locationString
, plContext
,
545 PKIX_GENERALNAMETOSTRINGFAILED
);
547 PKIX_CHECK(PKIX_PL_String_GetEncoded
548 (locationString
, PKIX_ESCASCII
, &location
, &len
, plContext
),
549 PKIX_STRINGGETENCODEDFAILED
);
551 PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n");
552 if (PORT_Strncmp(location
, "ldap:", 5) == 0){
553 type
= PKIX_INFOACCESS_LOCATION_LDAP
;
555 if (PORT_Strncmp(location
, "http:", 5) == 0){
556 type
= PKIX_INFOACCESS_LOCATION_HTTP
;
564 PKIX_PL_Free(location
, plContext
);
565 PKIX_DECREF(locationString
);
567 PKIX_RETURN(INFOACCESS
);
571 * FUNCTION: pkix_pl_InfoAccess_ParseTokens
574 * This function parses the string beginning at "startPos" into tokens using
575 * the separator contained in "separator" and the terminator contained in
576 * "terminator", copying the tokens into space allocated from the arena
577 * pointed to by "arena". It stores in "tokens" a null-terminated array of
578 * pointers to those tokens.
582 * Address of a PRArenaPool to be used in populating the LDAPLocation.
585 * The address of char string that contains a subset of ldap location.
587 * The address of an array of char string for storing returned tokens.
590 * The character that is taken as token separator. Must be non-NULL.
592 * The character that is taken as parsing terminator. Must be non-NULL.
594 * Platform-specific context pointer.
596 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
598 * Returns NULL if the function succeeds.
599 * Returns an InfoAccess Error if the function fails in a non-fatal way.
600 * Returns a Fatal Error if the function fails in an unrecoverable way.
603 pkix_pl_InfoAccess_ParseTokens(
605 char **startPos
, /* return update */
612 PKIX_UInt32 numFilters
= 0;
613 PKIX_Int32 cmpResult
= -1;
616 char **filterP
= NULL
;
618 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_ParseTokens");
619 PKIX_NULLCHECK_THREE(arena
, startPos
, tokens
);
623 /* First pass: parse to <terminator> to count number of components */
625 while (*endPos
!= terminator
&& *endPos
!= '\0') {
627 if (*endPos
== separator
) {
632 if (*endPos
!= terminator
) {
633 PKIX_ERROR(PKIX_LOCATIONSTRINGNOTPROPERLYTERMINATED
);
636 /* Last one doesn't have a "," as separator, although we allow it */
637 if (*(endPos
-1) != ',') {
642 * If string is a=xx, b=yy, c=zz, etc., use a=xx for filter,
643 * and everything else for the base
645 if (numFilters
> 2) numFilters
= 2;
648 (INFOACCESS
, *tokens
, PORT_ArenaZAlloc
,
649 (arena
, (numFilters
+1)*sizeof(void *)));
651 /* Second pass: parse to fill in components in token array */
656 if (*endPos
== separator
|| *endPos
== terminator
) {
657 len
= endPos
- *startPos
;
658 PKIX_PL_NSSCALLRV(INFOACCESS
, p
, PORT_ArenaZAlloc
,
664 if (**startPos
== '%') {
665 /* replace %20 by blank */
666 PKIX_PL_NSSCALLRV(INFOACCESS
, cmpResult
,
667 strncmp
, ((void *)*startPos
, "%20", 3));
668 if (cmpResult
== 0) {
685 separator
= terminator
;
687 if (endPos
== '\0') {
702 PKIX_RETURN(INFOACCESS
);
706 * FUNCTION: pkix_pl_InfoAccess_ParseLocation
709 * This function parses the GeneralName pointed to by "generalName" into the
710 * fields of the LDAPRequestParams pointed to by "request" and a domainName
711 * pointed to by "pDomainName", using the PRArenaPool pointed to by "arena" to
712 * allocate storage for the request components and for the domainName string.
714 * The expected GeneralName string should be in the format described by the
717 * ldap://<ldap-server-site>/[cn=<cname>][,o=<org>][,c=<country>]?
718 * [caCertificate|crossCertificatPair|certificateRevocationList];
719 * [binary|<other-type>]
720 * [[,caCertificate|crossCertificatPair|certificateRevocationList]
721 * [binary|<other-type>]]*
725 * Address of the GeneralName whose LDAPLocation is to be parsed. Must be
728 * Address of PRArenaPool to be used for the domainName and for components
729 * of the LDAPRequest. Must be non-NULL.
731 * Address of the LDAPRequestParams into which request components are
732 * stored. Must be non-NULL.
734 * Address at which the domainName is stored. Must be non-NULL.
736 * Platform-specific context pointer.
738 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
740 * Returns NULL if the function succeeds.
741 * Returns an InfoAccess Error if the function fails in a non-fatal way.
742 * Returns a Fatal Error if the function fails in an unrecoverable way.
745 pkix_pl_InfoAccess_ParseLocation(
746 PKIX_PL_GeneralName
*generalName
,
748 LDAPRequestParams
*request
,
752 PKIX_PL_String
*locationString
= NULL
;
754 PKIX_UInt32 ncIndex
= 0;
755 char *domainName
= NULL
;
756 char **avaArray
= NULL
;
757 char **attrArray
= NULL
;
759 char *locationAscii
= NULL
;
760 char *startPos
= NULL
;
763 LdapAttrMask attrBit
= 0;
764 LDAPNameComponent
**setOfNameComponent
= NULL
;
765 LDAPNameComponent
*nameComponent
= NULL
;
768 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_ParseLocation");
769 PKIX_NULLCHECK_FOUR(generalName
, arena
, request
, pDomainName
);
771 PKIX_TOSTRING(generalName
, &locationString
, plContext
,
772 PKIX_GENERALNAMETOSTRINGFAILED
);
774 PKIX_CHECK(PKIX_PL_String_GetEncoded
777 (void **)&locationAscii
,
780 PKIX_STRINGGETENCODEDFAILED
);
783 /* For testing inside the firewall... */
784 locationAscii
= "ldap://nss.red.iplanet.com:1389/cn=Good%20CA,o="
785 "Test%20Certificates,c=US?caCertificate;binary";
789 endPos
= locationAscii
;
790 while (*endPos
!= ':' && *endPos
!= '\0') {
793 if (*endPos
== '\0') {
794 PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGLOCATIONTYPE
);
799 if (*endPos
!= '\0' && *(endPos
+1) != '0' &&
800 *endPos
== '/' && *(endPos
+1) == '/') {
803 PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGDOUBLESLASH
);
806 /* Get the server-site */
808 while(*endPos
!= '/' && *(endPos
) != '\0') {
811 if (*endPos
== '\0') {
812 PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGSERVERSITE
);
815 len
= endPos
- startPos
;
818 PKIX_PL_NSSCALLRV(INFOACCESS
, domainName
, PORT_ArenaZAlloc
,
821 PKIX_PL_NSSCALL(INFOACCESS
, PORT_Memcpy
, (domainName
, startPos
, len
));
823 domainName
[len
] = '\0';
825 *pDomainName
= domainName
;
828 * Get a list of AttrValueAssertions (such as
829 * "cn=CommonName, o=Organization, c=US" into a null-terminated array
832 PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
835 (char ***) &avaArray
,
839 PKIX_INFOACCESSPARSETOKENSFAILED
);
841 /* Count how many AVAs we have */
842 for (len
= 0; avaArray
[len
] != NULL
; len
++) {}
845 PKIX_ERROR(PKIX_NOTENOUGHNAMECOMPONENTSINGENERALNAME
);
848 /* Use last name component for baseObject */
849 request
->baseObject
= avaArray
[len
- 1];
851 /* Use only one component for filter. LDAP servers aren't too smart. */
852 len
= 2; /* Eliminate this when servers get smarter. */
854 avaArray
[len
- 1] = NULL
;
856 /* Get room for null-terminated array of (LdapNameComponent *) */
858 (INFOACCESS
, v
, PORT_ArenaZAlloc
,
859 (arena
, len
*sizeof(LDAPNameComponent
*)));
861 setOfNameComponent
= (LDAPNameComponent
**)v
;
863 /* Get room for the remaining LdapNameComponents */
865 (INFOACCESS
, v
, PORT_ArenaZNewArray
,
866 (arena
, LDAPNameComponent
, --len
));
868 nameComponent
= (LDAPNameComponent
*)v
;
870 /* Convert remaining AVAs to LDAPNameComponents */
871 for (ncIndex
= 0; ncIndex
< len
; ncIndex
++) {
872 setOfNameComponent
[ncIndex
] = nameComponent
;
873 avaPtr
= avaArray
[ncIndex
];
874 nameComponent
->attrType
= (unsigned char *)avaPtr
;
875 while ((*avaPtr
!= '=') && (*avaPtr
!= '\0')) {
877 if (avaPtr
== '\0') {
878 PKIX_ERROR(PKIX_NAMECOMPONENTWITHNOEQ
);
882 nameComponent
->attrValue
= (unsigned char *)avaPtr
;
886 setOfNameComponent
[len
] = NULL
;
887 request
->nc
= setOfNameComponent
;
890 * Get a list of AttrTypes (such as
891 * "caCertificate;binary, crossCertificatePair;binary") into
892 * a null-terminated array
895 PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
898 (char ***) &attrArray
,
902 PKIX_INFOACCESSPARSETOKENSFAILED
);
904 /* Convert array of Attr Types into a bit mask */
905 request
->attributes
= 0;
907 while (attr
!= NULL
) {
908 PKIX_CHECK(pkix_pl_LdapRequest_AttrStringToBit
909 (attr
, &attrBit
, plContext
),
910 PKIX_LDAPREQUESTATTRSTRINGTOBITFAILED
);
911 request
->attributes
|= attrBit
;
912 attr
= *(++attrArray
);
917 PKIX_PL_Free(locationAscii
, plContext
);
918 PKIX_DECREF(locationString
);
920 PKIX_RETURN(INFOACCESS
);