Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_infoaccess.c
blobd2020d93cc18f82aee10815b9a5abfd0ec1fbcd7
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
12 * License.
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.
21 * Contributor(s):
22 * Sun Microsystems
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
60 * DESCRIPTION:
62 * This function creates an InfoAccess from the method provided in "method" and
63 * the GeneralName provided in "generalName" and stores the result at
64 * "pInfoAccess".
66 * PARAMETERS
67 * "method"
68 * The UInt32 value to be stored as the method field of the InfoAccess.
69 * "generalName"
70 * The GeneralName to be stored as the generalName field of the InfoAccess.
71 * Must be non-NULL.
72 * "pInfoAccess"
73 * Address where the result is stored. Must be non-NULL.
74 * "plContext"
75 * Platform-specific context pointer.
76 * THREAD SAFETY:
77 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
78 * RETURNS:
79 * Returns NULL if the function succeeds.
80 * Returns a Fatal Error if the function fails in an unrecoverable way.
82 static PKIX_Error *
83 pkix_pl_InfoAccess_Create(
84 PKIX_UInt32 method,
85 PKIX_PL_GeneralName *generalName,
86 PKIX_PL_InfoAccess **pInfoAccess,
87 void *plContext)
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,
99 plContext),
100 PKIX_COULDNOTCREATEINFOACCESSOBJECT);
102 infoAccess->method = method;
104 PKIX_INCREF(generalName);
105 infoAccess->location = generalName;
107 *pInfoAccess = infoAccess;
109 cleanup:
111 PKIX_RETURN(INFOACCESS);
115 * FUNCTION: pkix_pl_InfoAccess_Destroy
116 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h)
118 static PKIX_Error *
119 pkix_pl_InfoAccess_Destroy(
120 PKIX_PL_Object *object,
121 void *plContext)
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);
135 cleanup:
137 PKIX_RETURN(INFOACCESS);
141 * FUNCTION: pkix_pl_InfoAccess_ToString
142 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_pki.h)
144 static PKIX_Error *
145 pkix_pl_InfoAccess_ToString(
146 PKIX_PL_Object *object,
147 PKIX_PL_String **pString,
148 void *plContext)
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;
167 asciiFormat =
169 "method:%s, "
170 "location:%s"
171 "]";
173 PKIX_CHECK(PKIX_PL_String_Create
174 (PKIX_ESCASCII,
175 asciiFormat,
177 &formatString,
178 plContext),
179 PKIX_STRINGCREATEFAILED);
181 switch(infoAccess->method) {
182 case PKIX_INFOACCESS_CA_ISSUERS:
183 asciiMethod = "caIssuers";
184 break;
185 case PKIX_INFOACCESS_OCSP:
186 asciiMethod = "ocsp";
187 break;
188 case PKIX_INFOACCESS_TIMESTAMPING:
189 asciiMethod = "timestamping";
190 break;
191 case PKIX_INFOACCESS_CA_REPOSITORY:
192 asciiMethod = "caRepository";
193 break;
194 default:
195 asciiMethod = "unknown";
198 PKIX_CHECK(PKIX_PL_String_Create
199 (PKIX_ESCASCII,
200 asciiMethod,
202 &methodString,
203 plContext),
204 PKIX_STRINGCREATEFAILED);
206 PKIX_TOSTRING(infoAccess->location, &locationString, plContext,
207 PKIX_GENERALNAMETOSTRINGFAILED);
209 PKIX_CHECK(PKIX_PL_Sprintf
210 (&infoAccessString,
211 plContext,
212 formatString,
213 methodString,
214 locationString),
215 PKIX_SPRINTFFAILED);
217 *pString = infoAccessString;
219 cleanup:
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)
232 static PKIX_Error *
233 pkix_pl_InfoAccess_Hashcode(
234 PKIX_PL_Object *object,
235 PKIX_UInt32 *pHashcode,
236 void *plContext)
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;
257 cleanup:
259 PKIX_RETURN(INFOACCESS);
264 * FUNCTION: pkix_pl_InfoAccess_Equals
265 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_pki.h)
267 static PKIX_Error *
268 pkix_pl_InfoAccess_Equals(
269 PKIX_PL_Object *firstObject,
270 PKIX_PL_Object *secondObject,
271 PKIX_Boolean *pResult,
272 void *plContext)
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;
293 goto cleanup;
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) {
312 goto cleanup;
315 PKIX_EQUALS(firstInfoAccess, secondInfoAccess, &cmpResult, plContext,
316 PKIX_OBJECTEQUALSFAILED);
318 *pResult = cmpResult;
320 cleanup:
322 PKIX_RETURN(INFOACCESS);
326 * FUNCTION: pkix_pl_InfoAccess_RegisterSelf
327 * DESCRIPTION:
328 * Registers PKIX_INFOACCESS_TYPE and its related functions with systemClasses[]
329 * THREAD SAFETY:
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
334 * thread-safe.
336 PKIX_Error *
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
360 * DESCRIPTION:
362 * Based on data in CERTAuthInfoAccess array "nssInfoAccess", this function
363 * creates and returns a PKIX_List of PKIX_PL_InfoAccess at "pInfoAccessList".
365 * PARAMETERS
366 * "nssInfoAccess"
367 * The pointer array of CERTAuthInfoAccess that contains access data.
368 * May be NULL.
369 * "pInfoAccessList"
370 * Address where a list of PKIX_PL_InfoAccess is returned.
371 * Must be non-NULL.
372 * "plContext"
373 * Platform-specific context pointer.
374 * THREAD SAFETY:
375 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
376 * RETURNS:
377 * Returns NULL if the function succeeds.
378 * Returns a Fatal Error if the function fails in an unrecoverable way.
380 PKIX_Error *
381 pkix_pl_InfoAccess_CreateList(
382 CERTAuthInfoAccess **nssInfoAccess,
383 PKIX_List **pInfoAccessList, /* of PKIX_PL_InfoAccess */
384 void *plContext)
386 PKIX_List *infoAccessList = NULL;
387 PKIX_PL_InfoAccess *infoAccess = NULL;
388 PKIX_PL_GeneralName *location = NULL;
389 PKIX_UInt32 method;
390 int i;
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) {
401 goto cleanup;
404 for (i = 0; nssInfoAccess[i] != NULL; i++) {
406 if (nssInfoAccess[i]->location == NULL) {
407 continue;
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);
417 if (method == 0) {
419 /* XXX
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*)
430 * is doing the job.
433 PKIX_CERT_DEBUG("\t\tCalling PORT_Strncmp).\n");
434 if (PORT_Strncmp
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 */
448 switch(method) {
449 case SEC_OID_PKIX_CA_ISSUERS:
450 method = PKIX_INFOACCESS_CA_ISSUERS;
451 break;
452 case SEC_OID_PKIX_OCSP:
453 method = PKIX_INFOACCESS_OCSP;
454 break;
455 case SEC_OID_PKIX_TIMESTAMPING:
456 method = PKIX_INFOACCESS_TIMESTAMPING;
457 break;
458 case SEC_OID_PKIX_CA_REPOSITORY:
459 method = PKIX_INFOACCESS_CA_REPOSITORY;
460 break;
461 default:
462 break;
465 PKIX_CHECK(pkix_pl_InfoAccess_Create
466 (method, location, &infoAccess, plContext),
467 PKIX_INFOACCESSCREATEFAILED);
469 PKIX_CHECK(PKIX_List_AppendItem
470 (infoAccessList,
471 (PKIX_PL_Object *)infoAccess,
472 plContext),
473 PKIX_LISTAPPENDITEMFAILED);
474 PKIX_DECREF(infoAccess);
477 *pInfoAccessList = infoAccessList;
479 cleanup:
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)
492 PKIX_Error *
493 PKIX_PL_InfoAccess_GetMethod(
494 PKIX_PL_InfoAccess *infoAccess,
495 PKIX_UInt32 *pMethod,
496 void *plContext)
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)
509 PKIX_Error *
510 PKIX_PL_InfoAccess_GetLocation(
511 PKIX_PL_InfoAccess *infoAccess,
512 PKIX_PL_GeneralName **pLocation,
513 void *plContext)
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)
528 PKIX_Error *
529 PKIX_PL_InfoAccess_GetLocationType(
530 PKIX_PL_InfoAccess *infoAccess,
531 PKIX_UInt32 *pType,
532 void *plContext)
534 PKIX_PL_String *locationString = NULL;
535 PKIX_UInt32 type = PKIX_INFOACCESS_LOCATION_UNKNOWN;
536 PKIX_UInt32 len = 0;
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;
554 } else
555 if (PORT_Strncmp(location, "http:", 5) == 0){
556 type = PKIX_INFOACCESS_LOCATION_HTTP;
560 *pType = type;
562 cleanup:
564 PKIX_PL_Free(location, plContext);
565 PKIX_DECREF(locationString);
567 PKIX_RETURN(INFOACCESS);
571 * FUNCTION: pkix_pl_InfoAccess_ParseTokens
572 * DESCRIPTION:
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.
580 * PARAMETERS
581 * "arena"
582 * Address of a PRArenaPool to be used in populating the LDAPLocation.
583 * Must be non-NULL.
584 * "startPos"
585 * The address of char string that contains a subset of ldap location.
586 * "tokens"
587 * The address of an array of char string for storing returned tokens.
588 * Must be non-NULL.
589 * "separator"
590 * The character that is taken as token separator. Must be non-NULL.
591 * "terminator"
592 * The character that is taken as parsing terminator. Must be non-NULL.
593 * "plContext"
594 * Platform-specific context pointer.
595 * THREAD SAFETY:
596 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
597 * RETURNS:
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.
602 static PKIX_Error *
603 pkix_pl_InfoAccess_ParseTokens(
604 PRArenaPool *arena,
605 char **startPos, /* return update */
606 char ***tokens,
607 char separator,
608 char terminator,
609 void *plContext)
611 PKIX_UInt32 len = 0;
612 PKIX_UInt32 numFilters = 0;
613 PKIX_Int32 cmpResult = -1;
614 char *endPos = NULL;
615 char *p = NULL;
616 char **filterP = NULL;
618 PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseTokens");
619 PKIX_NULLCHECK_THREE(arena, startPos, tokens);
621 endPos = *startPos;
623 /* First pass: parse to <terminator> to count number of components */
624 numFilters = 0;
625 while (*endPos != terminator && *endPos != '\0') {
626 endPos++;
627 if (*endPos == separator) {
628 numFilters++;
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) != ',') {
638 numFilters++;
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;
647 PKIX_PL_NSSCALLRV
648 (INFOACCESS, *tokens, PORT_ArenaZAlloc,
649 (arena, (numFilters+1)*sizeof(void *)));
651 /* Second pass: parse to fill in components in token array */
652 filterP = *tokens;
653 endPos = *startPos;
655 while (numFilters) {
656 if (*endPos == separator || *endPos == terminator) {
657 len = endPos - *startPos;
658 PKIX_PL_NSSCALLRV(INFOACCESS, p, PORT_ArenaZAlloc,
659 (arena, (len+1)));
661 *filterP = p;
663 while (len) {
664 if (**startPos == '%') {
665 /* replace %20 by blank */
666 PKIX_PL_NSSCALLRV(INFOACCESS, cmpResult,
667 strncmp, ((void *)*startPos, "%20", 3));
668 if (cmpResult == 0) {
669 *p = ' ';
670 *startPos += 3;
671 len -= 3;
673 } else {
674 *p = **startPos;
675 (*startPos)++;
676 len--;
678 p++;
681 *p = '\0';
682 filterP++;
683 numFilters--;
685 separator = terminator;
687 if (endPos == '\0') {
688 break;
689 } else {
690 endPos++;
691 *startPos = endPos;
692 continue;
695 endPos++;
698 *filterP = NULL;
700 cleanup:
702 PKIX_RETURN(INFOACCESS);
706 * FUNCTION: pkix_pl_InfoAccess_ParseLocation
707 * DESCRIPTION:
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
715 * following BNF:
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>]]*
723 * PARAMETERS
724 * "generalName"
725 * Address of the GeneralName whose LDAPLocation is to be parsed. Must be
726 * non-NULL.
727 * "arena"
728 * Address of PRArenaPool to be used for the domainName and for components
729 * of the LDAPRequest. Must be non-NULL.
730 * "request"
731 * Address of the LDAPRequestParams into which request components are
732 * stored. Must be non-NULL.
733 * *pDomainName"
734 * Address at which the domainName is stored. Must be non-NULL.
735 * "plContext"
736 * Platform-specific context pointer.
737 * THREAD SAFETY:
738 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
739 * RETURNS:
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.
744 PKIX_Error *
745 pkix_pl_InfoAccess_ParseLocation(
746 PKIX_PL_GeneralName *generalName,
747 PRArenaPool *arena,
748 LDAPRequestParams *request,
749 char **pDomainName,
750 void *plContext)
752 PKIX_PL_String *locationString = NULL;
753 PKIX_UInt32 len = 0;
754 PKIX_UInt32 ncIndex = 0;
755 char *domainName = NULL;
756 char **avaArray = NULL;
757 char **attrArray = NULL;
758 char *attr = NULL;
759 char *locationAscii = NULL;
760 char *startPos = NULL;
761 char *endPos = NULL;
762 char *avaPtr = NULL;
763 LdapAttrMask attrBit = 0;
764 LDAPNameComponent **setOfNameComponent = NULL;
765 LDAPNameComponent *nameComponent = NULL;
766 void *v = 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
775 (locationString,
776 PKIX_ESCASCII,
777 (void **)&locationAscii,
778 &len,
779 plContext),
780 PKIX_STRINGGETENCODEDFAILED);
782 #if 0
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";
786 #endif
788 /* Skip "ldap:" */
789 endPos = locationAscii;
790 while (*endPos != ':' && *endPos != '\0') {
791 endPos++;
793 if (*endPos == '\0') {
794 PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGLOCATIONTYPE);
797 /* Skip "//" */
798 endPos++;
799 if (*endPos != '\0' && *(endPos+1) != '0' &&
800 *endPos == '/' && *(endPos+1) == '/') {
801 endPos += 2;
802 } else {
803 PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGDOUBLESLASH);
806 /* Get the server-site */
807 startPos = endPos;
808 while(*endPos != '/' && *(endPos) != '\0') {
809 endPos++;
811 if (*endPos == '\0') {
812 PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGSERVERSITE);
815 len = endPos - startPos;
816 endPos++;
818 PKIX_PL_NSSCALLRV(INFOACCESS, domainName, PORT_ArenaZAlloc,
819 (arena, len + 1));
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
831 startPos = endPos;
832 PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
833 (arena,
834 &startPos,
835 (char ***) &avaArray,
836 ',',
837 '?',
838 plContext),
839 PKIX_INFOACCESSPARSETOKENSFAILED);
841 /* Count how many AVAs we have */
842 for (len = 0; avaArray[len] != NULL; len++) {}
844 if (len < 2) {
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 *) */
857 PKIX_PL_NSSCALLRV
858 (INFOACCESS, v, PORT_ArenaZAlloc,
859 (arena, len*sizeof(LDAPNameComponent *)));
861 setOfNameComponent = (LDAPNameComponent **)v;
863 /* Get room for the remaining LdapNameComponents */
864 PKIX_PL_NSSCALLRV
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')) {
876 avaPtr++;
877 if (avaPtr == '\0') {
878 PKIX_ERROR(PKIX_NAMECOMPONENTWITHNOEQ);
881 *(avaPtr++) = '\0';
882 nameComponent->attrValue = (unsigned char *)avaPtr;
883 nameComponent++;
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
896 (arena,
897 (char **) &startPos,
898 (char ***) &attrArray,
899 ',',
900 '\0',
901 plContext),
902 PKIX_INFOACCESSPARSETOKENSFAILED);
904 /* Convert array of Attr Types into a bit mask */
905 request->attributes = 0;
906 attr = attrArray[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);
915 cleanup:
917 PKIX_PL_Free(locationAscii, plContext);
918 PKIX_DECREF(locationString);
920 PKIX_RETURN(INFOACCESS);