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 PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
22 * Sun Microsystems, Inc.
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_DECREF(infoAccess
);
113 PKIX_RETURN(INFOACCESS
);
117 * FUNCTION: pkix_pl_InfoAccess_Destroy
118 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h)
121 pkix_pl_InfoAccess_Destroy(
122 PKIX_PL_Object
*object
,
125 PKIX_PL_InfoAccess
*infoAccess
= NULL
;
127 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_Destroy");
128 PKIX_NULLCHECK_ONE(object
);
130 PKIX_CHECK(pkix_CheckType(object
, PKIX_INFOACCESS_TYPE
, plContext
),
131 PKIX_OBJECTNOTANINFOACCESS
);
133 infoAccess
= (PKIX_PL_InfoAccess
*)object
;
135 PKIX_DECREF(infoAccess
->location
);
139 PKIX_RETURN(INFOACCESS
);
143 * FUNCTION: pkix_pl_InfoAccess_ToString
144 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_pki.h)
147 pkix_pl_InfoAccess_ToString(
148 PKIX_PL_Object
*object
,
149 PKIX_PL_String
**pString
,
152 PKIX_PL_InfoAccess
*infoAccess
;
153 PKIX_PL_String
*infoAccessString
= NULL
;
154 char *asciiFormat
= NULL
;
155 char *asciiMethod
= NULL
;
156 PKIX_PL_String
*formatString
= NULL
;
157 PKIX_PL_String
*methodString
= NULL
;
158 PKIX_PL_String
*locationString
= NULL
;
160 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_ToString");
161 PKIX_NULLCHECK_TWO(object
, pString
);
163 PKIX_CHECK(pkix_CheckType
164 (object
, PKIX_INFOACCESS_TYPE
, plContext
),
165 PKIX_OBJECTNOTINFOACCESS
);
167 infoAccess
= (PKIX_PL_InfoAccess
*)object
;
175 PKIX_CHECK(PKIX_PL_String_Create
181 PKIX_STRINGCREATEFAILED
);
183 switch(infoAccess
->method
) {
184 case PKIX_INFOACCESS_CA_ISSUERS
:
185 asciiMethod
= "caIssuers";
187 case PKIX_INFOACCESS_OCSP
:
188 asciiMethod
= "ocsp";
190 case PKIX_INFOACCESS_TIMESTAMPING
:
191 asciiMethod
= "timestamping";
193 case PKIX_INFOACCESS_CA_REPOSITORY
:
194 asciiMethod
= "caRepository";
197 asciiMethod
= "unknown";
200 PKIX_CHECK(PKIX_PL_String_Create
206 PKIX_STRINGCREATEFAILED
);
208 PKIX_TOSTRING(infoAccess
->location
, &locationString
, plContext
,
209 PKIX_GENERALNAMETOSTRINGFAILED
);
211 PKIX_CHECK(PKIX_PL_Sprintf
219 *pString
= infoAccessString
;
223 PKIX_DECREF(formatString
);
224 PKIX_DECREF(methodString
);
225 PKIX_DECREF(locationString
);
227 PKIX_RETURN(INFOACCESS
);
231 * FUNCTION: pkix_pl_InfoAccess_Hashcode
232 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_pki.h)
235 pkix_pl_InfoAccess_Hashcode(
236 PKIX_PL_Object
*object
,
237 PKIX_UInt32
*pHashcode
,
240 PKIX_PL_InfoAccess
*infoAccess
= NULL
;
241 PKIX_UInt32 infoAccessHash
;
243 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_Hashcode");
244 PKIX_NULLCHECK_TWO(object
, pHashcode
);
246 PKIX_CHECK(pkix_CheckType
247 (object
, PKIX_INFOACCESS_TYPE
, plContext
),
248 PKIX_OBJECTNOTINFOACCESS
);
250 infoAccess
= (PKIX_PL_InfoAccess
*)object
;
252 PKIX_HASHCODE(infoAccess
->location
, &infoAccessHash
, plContext
,
253 PKIX_OBJECTHASHCODEFAILED
);
255 infoAccessHash
+= (infoAccess
->method
<< 7);
257 *pHashcode
= infoAccessHash
;
261 PKIX_RETURN(INFOACCESS
);
266 * FUNCTION: pkix_pl_InfoAccess_Equals
267 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_pki.h)
270 pkix_pl_InfoAccess_Equals(
271 PKIX_PL_Object
*firstObject
,
272 PKIX_PL_Object
*secondObject
,
273 PKIX_Boolean
*pResult
,
276 PKIX_PL_InfoAccess
*firstInfoAccess
= NULL
;
277 PKIX_PL_InfoAccess
*secondInfoAccess
= NULL
;
278 PKIX_UInt32 secondType
;
279 PKIX_Boolean cmpResult
;
281 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_Equals");
282 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
284 /* test that firstObject is a InfoAccess */
285 PKIX_CHECK(pkix_CheckType
286 (firstObject
, PKIX_INFOACCESS_TYPE
, plContext
),
287 PKIX_FIRSTOBJECTNOTINFOACCESS
);
290 * Since we know firstObject is a InfoAccess, if both references are
291 * identical, they must be equal
293 if (firstObject
== secondObject
){
294 *pResult
= PKIX_TRUE
;
299 * If secondObject isn't a InfoAccess, we don't throw an error.
300 * We simply return a Boolean result of FALSE
302 *pResult
= PKIX_FALSE
;
303 PKIX_CHECK(PKIX_PL_Object_GetType
304 (secondObject
, &secondType
, plContext
),
305 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT
);
306 if (secondType
!= PKIX_INFOACCESS_TYPE
) goto cleanup
;
308 firstInfoAccess
= (PKIX_PL_InfoAccess
*)firstObject
;
309 secondInfoAccess
= (PKIX_PL_InfoAccess
*)secondObject
;
311 *pResult
= PKIX_FALSE
;
313 if (firstInfoAccess
->method
!= secondInfoAccess
->method
) {
317 PKIX_EQUALS(firstInfoAccess
, secondInfoAccess
, &cmpResult
, plContext
,
318 PKIX_OBJECTEQUALSFAILED
);
320 *pResult
= cmpResult
;
324 PKIX_RETURN(INFOACCESS
);
328 * FUNCTION: pkix_pl_InfoAccess_RegisterSelf
330 * Registers PKIX_INFOACCESS_TYPE and its related functions with systemClasses[]
332 * Not Thread Safe - for performance and complexity reasons
334 * Since this function is only called by PKIX_PL_Initialize, which should
335 * only be called once, it is acceptable that this function is not
339 pkix_pl_InfoAccess_RegisterSelf(void *plContext
)
341 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
342 pkix_ClassTable_Entry entry
;
344 PKIX_ENTER(INFOACCESS
,
345 "pkix_pl_InfoAccess_RegisterSelf");
347 entry
.description
= "InfoAccess";
348 entry
.objCounter
= 0;
349 entry
.typeObjectSize
= sizeof(PKIX_PL_InfoAccess
);
350 entry
.destructor
= pkix_pl_InfoAccess_Destroy
;
351 entry
.equalsFunction
= pkix_pl_InfoAccess_Equals
;
352 entry
.hashcodeFunction
= pkix_pl_InfoAccess_Hashcode
;
353 entry
.toStringFunction
= pkix_pl_InfoAccess_ToString
;
354 entry
.comparator
= NULL
;
355 entry
.duplicateFunction
= pkix_duplicateImmutable
;
357 systemClasses
[PKIX_INFOACCESS_TYPE
] = entry
;
359 PKIX_RETURN(INFOACCESS
);
363 * FUNCTION: pkix_pl_InfoAccess_CreateList
366 * Based on data in CERTAuthInfoAccess array "nssInfoAccess", this function
367 * creates and returns a PKIX_List of PKIX_PL_InfoAccess at "pInfoAccessList".
371 * The pointer array of CERTAuthInfoAccess that contains access data.
374 * Address where a list of PKIX_PL_InfoAccess is returned.
377 * Platform-specific context pointer.
379 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
381 * Returns NULL if the function succeeds.
382 * Returns a Fatal Error if the function fails in an unrecoverable way.
385 pkix_pl_InfoAccess_CreateList(
386 CERTAuthInfoAccess
**nssInfoAccess
,
387 PKIX_List
**pInfoAccessList
, /* of PKIX_PL_InfoAccess */
390 PKIX_List
*infoAccessList
= NULL
;
391 PKIX_PL_InfoAccess
*infoAccess
= NULL
;
392 PKIX_PL_GeneralName
*location
= NULL
;
396 PKIX_ENTER(INFOACCESS
, "PKIX_PL_InfoAccess_CreateList");
397 PKIX_NULLCHECK_ONE(pInfoAccessList
);
399 PKIX_CHECK(PKIX_List_Create(&infoAccessList
, plContext
),
400 PKIX_LISTCREATEFAILED
);
402 if (nssInfoAccess
== NULL
) {
406 for (i
= 0; nssInfoAccess
[i
] != NULL
; i
++) {
408 if (nssInfoAccess
[i
]->location
== NULL
) {
412 PKIX_CHECK(pkix_pl_GeneralName_Create
413 (nssInfoAccess
[i
]->location
, &location
, plContext
),
414 PKIX_GENERALNAMECREATEFAILED
);
416 PKIX_CERT_DEBUG("\t\tCalling SECOID_FindOIDTag).\n");
417 method
= SECOID_FindOIDTag(&nssInfoAccess
[i
]->method
);
422 * This part of code is definitely hacking, need NSS decode
423 * support. We can reuse the CERT_DecodeAuthInfoAccessExtension
424 * since SIA and AIA are all the same type. However NSS need
425 * to add SIA, CaRepository, TimeStamping OID definitions and
426 * the numerical method, timeStamping and caRepository values.
428 * We assume now, since method is 0, implies the method for SIA
429 * was not decoded by CERT_DecodeAuthInfoAccessExtension()
430 * so we compare and put value in. This part should be taken
431 * out eventually if CERT_DecodeInfoAccessExtension (*renamed*)
435 PKIX_CERT_DEBUG("\t\tCalling PORT_Strncmp).\n");
437 ((char *)nssInfoAccess
[i
]->method
.data
,
438 (char *)siaTimeStampingOID
,
439 nssInfoAccess
[i
]->method
.len
) == 0) {
440 method
= SEC_OID_PKIX_TIMESTAMPING
;
441 } else if (PORT_Strncmp
442 ((char *)nssInfoAccess
[i
]->method
.data
,
443 (char *)siaCaRepositoryOID
,
444 nssInfoAccess
[i
]->method
.len
) == 0) {
445 method
= SEC_OID_PKIX_CA_REPOSITORY
;
449 /* Map NSS access method value into PKIX constant */
451 case SEC_OID_PKIX_CA_ISSUERS
:
452 method
= PKIX_INFOACCESS_CA_ISSUERS
;
454 case SEC_OID_PKIX_OCSP
:
455 method
= PKIX_INFOACCESS_OCSP
;
457 case SEC_OID_PKIX_TIMESTAMPING
:
458 method
= PKIX_INFOACCESS_TIMESTAMPING
;
460 case SEC_OID_PKIX_CA_REPOSITORY
:
461 method
= PKIX_INFOACCESS_CA_REPOSITORY
;
467 PKIX_CHECK(pkix_pl_InfoAccess_Create
468 (method
, location
, &infoAccess
, plContext
),
469 PKIX_INFOACCESSCREATEFAILED
);
471 PKIX_CHECK(PKIX_List_AppendItem
473 (PKIX_PL_Object
*)infoAccess
,
475 PKIX_LISTAPPENDITEMFAILED
);
476 PKIX_DECREF(infoAccess
);
477 PKIX_DECREF(location
);
480 *pInfoAccessList
= infoAccessList
;
481 infoAccessList
= NULL
;
485 PKIX_DECREF(infoAccessList
);
486 PKIX_DECREF(infoAccess
);
487 PKIX_DECREF(location
);
489 PKIX_RETURN(INFOACCESS
);
492 /* --Public-Functions------------------------------------------------------- */
495 * FUNCTION: PKIX_PL_InfoAccess_GetMethod (see comments in pkix_pl_pki.h)
498 PKIX_PL_InfoAccess_GetMethod(
499 PKIX_PL_InfoAccess
*infoAccess
,
500 PKIX_UInt32
*pMethod
,
503 PKIX_ENTER(INFOACCESS
, "PKIX_PL_InfoAccess_GetMethod");
504 PKIX_NULLCHECK_TWO(infoAccess
, pMethod
);
506 *pMethod
= infoAccess
->method
;
508 PKIX_RETURN(INFOACCESS
);
512 * FUNCTION: PKIX_PL_InfoAccess_GetLocation (see comments in pkix_pl_pki.h)
515 PKIX_PL_InfoAccess_GetLocation(
516 PKIX_PL_InfoAccess
*infoAccess
,
517 PKIX_PL_GeneralName
**pLocation
,
520 PKIX_ENTER(INFOACCESS
, "PKIX_PL_InfoAccess_GetLocation");
521 PKIX_NULLCHECK_TWO(infoAccess
, pLocation
);
523 PKIX_INCREF(infoAccess
->location
);
525 *pLocation
= infoAccess
->location
;
528 PKIX_RETURN(INFOACCESS
);
532 * FUNCTION: PKIX_PL_InfoAccess_GetLocationType (see comments in pkix_pl_pki.h)
535 PKIX_PL_InfoAccess_GetLocationType(
536 PKIX_PL_InfoAccess
*infoAccess
,
540 PKIX_PL_String
*locationString
= NULL
;
541 PKIX_UInt32 type
= PKIX_INFOACCESS_LOCATION_UNKNOWN
;
543 void *location
= NULL
;
545 PKIX_ENTER(INFOACCESS
, "PKIX_PL_InfoAccess_GetLocationType");
546 PKIX_NULLCHECK_TWO(infoAccess
, pType
);
548 if (infoAccess
->location
!= NULL
) {
550 PKIX_TOSTRING(infoAccess
->location
, &locationString
, plContext
,
551 PKIX_GENERALNAMETOSTRINGFAILED
);
553 PKIX_CHECK(PKIX_PL_String_GetEncoded
554 (locationString
, PKIX_ESCASCII
, &location
, &len
, plContext
),
555 PKIX_STRINGGETENCODEDFAILED
);
557 PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n");
558 if (PORT_Strncmp(location
, "ldap:", 5) == 0){
559 type
= PKIX_INFOACCESS_LOCATION_LDAP
;
561 if (PORT_Strncmp(location
, "http:", 5) == 0){
562 type
= PKIX_INFOACCESS_LOCATION_HTTP
;
570 PKIX_PL_Free(location
, plContext
);
571 PKIX_DECREF(locationString
);
573 PKIX_RETURN(INFOACCESS
);
577 * FUNCTION: pkix_pl_InfoAccess_ParseTokens
580 * This function parses the string beginning at "startPos" into tokens using
581 * the separator contained in "separator" and the terminator contained in
582 * "terminator", copying the tokens into space allocated from the arena
583 * pointed to by "arena". It stores in "tokens" a null-terminated array of
584 * pointers to those tokens.
588 * Address of a PRArenaPool to be used in populating the LDAPLocation.
591 * The address of char string that contains a subset of ldap location.
593 * The address of an array of char string for storing returned tokens.
596 * The character that is taken as token separator. Must be non-NULL.
598 * The character that is taken as parsing terminator. Must be non-NULL.
600 * Platform-specific context pointer.
602 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
604 * Returns NULL if the function succeeds.
605 * Returns an InfoAccess Error if the function fails in a non-fatal way.
606 * Returns a Fatal Error if the function fails in an unrecoverable way.
609 pkix_pl_InfoAccess_ParseTokens(
611 char **startPos
, /* return update */
618 PKIX_UInt32 numFilters
= 0;
619 PKIX_Int32 cmpResult
= -1;
622 char **filterP
= NULL
;
624 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_ParseTokens");
625 PKIX_NULLCHECK_THREE(arena
, startPos
, tokens
);
629 /* First pass: parse to <terminator> to count number of components */
631 while (*endPos
!= terminator
&& *endPos
!= '\0') {
633 if (*endPos
== separator
) {
638 if (*endPos
!= terminator
) {
639 PKIX_ERROR(PKIX_LOCATIONSTRINGNOTPROPERLYTERMINATED
);
642 /* Last one doesn't have a "," as separator, although we allow it */
643 if (*(endPos
-1) != ',') {
648 * If string is a=xx, b=yy, c=zz, etc., use a=xx for filter,
649 * and everything else for the base
651 if (numFilters
> 2) numFilters
= 2;
654 (INFOACCESS
, *tokens
, PORT_ArenaZAlloc
,
655 (arena
, (numFilters
+1)*sizeof(void *)));
657 /* Second pass: parse to fill in components in token array */
662 if (*endPos
== separator
|| *endPos
== terminator
) {
663 len
= endPos
- *startPos
;
664 PKIX_PL_NSSCALLRV(INFOACCESS
, p
, PORT_ArenaZAlloc
,
670 if (**startPos
== '%') {
671 /* replace %20 by blank */
672 PKIX_PL_NSSCALLRV(INFOACCESS
, cmpResult
,
673 strncmp
, ((void *)*startPos
, "%20", 3));
674 if (cmpResult
== 0) {
691 separator
= terminator
;
693 if (endPos
== '\0') {
708 PKIX_RETURN(INFOACCESS
);
712 * FUNCTION: pkix_pl_InfoAccess_ParseLocation
715 * This function parses the GeneralName pointed to by "generalName" into the
716 * fields of the LDAPRequestParams pointed to by "request" and a domainName
717 * pointed to by "pDomainName", using the PRArenaPool pointed to by "arena" to
718 * allocate storage for the request components and for the domainName string.
720 * The expected GeneralName string should be in the format described by the
723 * ldap://<ldap-server-site>/[cn=<cname>][,o=<org>][,c=<country>]?
724 * [caCertificate|crossCertificatPair|certificateRevocationList];
725 * [binary|<other-type>]
726 * [[,caCertificate|crossCertificatPair|certificateRevocationList]
727 * [binary|<other-type>]]*
731 * Address of the GeneralName whose LDAPLocation is to be parsed. Must be
734 * Address of PRArenaPool to be used for the domainName and for components
735 * of the LDAPRequest. Must be non-NULL.
737 * Address of the LDAPRequestParams into which request components are
738 * stored. Must be non-NULL.
740 * Address at which the domainName is stored. Must be non-NULL.
742 * Platform-specific context pointer.
744 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
746 * Returns NULL if the function succeeds.
747 * Returns an InfoAccess Error if the function fails in a non-fatal way.
748 * Returns a Fatal Error if the function fails in an unrecoverable way.
751 pkix_pl_InfoAccess_ParseLocation(
752 PKIX_PL_GeneralName
*generalName
,
754 LDAPRequestParams
*request
,
758 PKIX_PL_String
*locationString
= NULL
;
760 PKIX_UInt32 ncIndex
= 0;
761 char *domainName
= NULL
;
762 char **avaArray
= NULL
;
763 char **attrArray
= NULL
;
765 char *locationAscii
= NULL
;
766 char *startPos
= NULL
;
769 LdapAttrMask attrBit
= 0;
770 LDAPNameComponent
**setOfNameComponent
= NULL
;
771 LDAPNameComponent
*nameComponent
= NULL
;
774 PKIX_ENTER(INFOACCESS
, "pkix_pl_InfoAccess_ParseLocation");
775 PKIX_NULLCHECK_FOUR(generalName
, arena
, request
, pDomainName
);
777 PKIX_TOSTRING(generalName
, &locationString
, plContext
,
778 PKIX_GENERALNAMETOSTRINGFAILED
);
780 PKIX_CHECK(PKIX_PL_String_GetEncoded
783 (void **)&locationAscii
,
786 PKIX_STRINGGETENCODEDFAILED
);
789 /* For testing inside the firewall... */
790 locationAscii
= "ldap://nss.red.iplanet.com:1389/cn=Good%20CA,o="
791 "Test%20Certificates,c=US?caCertificate;binary";
795 endPos
= locationAscii
;
796 while (*endPos
!= ':' && *endPos
!= '\0') {
799 if (*endPos
== '\0') {
800 PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGLOCATIONTYPE
);
805 if (*endPos
!= '\0' && *(endPos
+1) != '0' &&
806 *endPos
== '/' && *(endPos
+1) == '/') {
809 PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGDOUBLESLASH
);
812 /* Get the server-site */
814 while(*endPos
!= '/' && *(endPos
) != '\0') {
817 if (*endPos
== '\0') {
818 PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGSERVERSITE
);
821 len
= endPos
- startPos
;
824 PKIX_PL_NSSCALLRV(INFOACCESS
, domainName
, PORT_ArenaZAlloc
,
827 PKIX_PL_NSSCALL(INFOACCESS
, PORT_Memcpy
, (domainName
, startPos
, len
));
829 domainName
[len
] = '\0';
831 *pDomainName
= domainName
;
834 * Get a list of AttrValueAssertions (such as
835 * "cn=CommonName, o=Organization, c=US" into a null-terminated array
838 PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
841 (char ***) &avaArray
,
845 PKIX_INFOACCESSPARSETOKENSFAILED
);
847 /* Count how many AVAs we have */
848 for (len
= 0; avaArray
[len
] != NULL
; len
++) {}
851 PKIX_ERROR(PKIX_NOTENOUGHNAMECOMPONENTSINGENERALNAME
);
854 /* Use last name component for baseObject */
855 request
->baseObject
= avaArray
[len
- 1];
857 /* Use only one component for filter. LDAP servers aren't too smart. */
858 len
= 2; /* Eliminate this when servers get smarter. */
860 avaArray
[len
- 1] = NULL
;
862 /* Get room for null-terminated array of (LdapNameComponent *) */
864 (INFOACCESS
, v
, PORT_ArenaZAlloc
,
865 (arena
, len
*sizeof(LDAPNameComponent
*)));
867 setOfNameComponent
= (LDAPNameComponent
**)v
;
869 /* Get room for the remaining LdapNameComponents */
871 (INFOACCESS
, v
, PORT_ArenaZNewArray
,
872 (arena
, LDAPNameComponent
, --len
));
874 nameComponent
= (LDAPNameComponent
*)v
;
876 /* Convert remaining AVAs to LDAPNameComponents */
877 for (ncIndex
= 0; ncIndex
< len
; ncIndex
++) {
878 setOfNameComponent
[ncIndex
] = nameComponent
;
879 avaPtr
= avaArray
[ncIndex
];
880 nameComponent
->attrType
= (unsigned char *)avaPtr
;
881 while ((*avaPtr
!= '=') && (*avaPtr
!= '\0')) {
883 if (avaPtr
== '\0') {
884 PKIX_ERROR(PKIX_NAMECOMPONENTWITHNOEQ
);
888 nameComponent
->attrValue
= (unsigned char *)avaPtr
;
892 setOfNameComponent
[len
] = NULL
;
893 request
->nc
= setOfNameComponent
;
896 * Get a list of AttrTypes (such as
897 * "caCertificate;binary, crossCertificatePair;binary") into
898 * a null-terminated array
901 PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
904 (char ***) &attrArray
,
908 PKIX_INFOACCESSPARSETOKENSFAILED
);
910 /* Convert array of Attr Types into a bit mask */
911 request
->attributes
= 0;
913 while (attr
!= NULL
) {
914 PKIX_CHECK(pkix_pl_LdapRequest_AttrStringToBit
915 (attr
, &attrBit
, plContext
),
916 PKIX_LDAPREQUESTATTRSTRINGTOBITFAILED
);
917 request
->attributes
|= attrBit
;
918 attr
= *(++attrArray
);
923 PKIX_PL_Free(locationAscii
, plContext
);
924 PKIX_DECREF(locationString
);
926 PKIX_RETURN(INFOACCESS
);