PageRenderTime 90ms CodeModel.GetById 10ms app.highlight 64ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c

http://github.com/zpao/v8monkey
C | 707 lines | 449 code | 120 blank | 138 comment | 71 complexity | 24e9ae8d4be767136f29c25df8c6fb76 MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  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/
  8 *
  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.
 13 *
 14 * The Original Code is the PKIX-C library.
 15 *
 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.
 20 *
 21 * Contributor(s):
 22 *   Sun Microsystems, Inc.
 23 *
 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.
 35 *
 36 * ***** END LICENSE BLOCK ***** */
 37/*
 38 * pkix_pl_aiamgr.c
 39 *
 40 * AIAMgr Object Definitions
 41 *
 42 */
 43
 44#include "pkix_pl_aiamgr.h"
 45extern PKIX_PL_HashTable *aiaConnectionCache;
 46
 47/* --Virtual-LdapClient-Functions------------------------------------ */
 48
 49PKIX_Error *
 50PKIX_PL_LdapClient_InitiateRequest(
 51        PKIX_PL_LdapClient *client,
 52        LDAPRequestParams *requestParams,
 53        void **pNBIO,
 54        PKIX_List **pResponse,
 55        void *plContext)
 56{
 57        PKIX_ENTER(LDAPCLIENT, "PKIX_PL_LdapClient_InitiateRequest");
 58        PKIX_NULLCHECK_TWO(client, client->initiateFcn);
 59
 60        PKIX_CHECK(client->initiateFcn
 61                (client, requestParams, pNBIO, pResponse, plContext),
 62                PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
 63cleanup:
 64
 65        PKIX_RETURN(LDAPCLIENT);
 66
 67}
 68
 69PKIX_Error *
 70PKIX_PL_LdapClient_ResumeRequest(
 71        PKIX_PL_LdapClient *client,
 72        void **pNBIO,
 73        PKIX_List **pResponse,
 74        void *plContext)
 75{
 76        PKIX_ENTER(LDAPCLIENT, "PKIX_PL_LdapClient_ResumeRequest");
 77        PKIX_NULLCHECK_TWO(client, client->resumeFcn);
 78
 79        PKIX_CHECK(client->resumeFcn
 80                (client, pNBIO, pResponse, plContext),
 81                PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
 82cleanup:
 83
 84        PKIX_RETURN(LDAPCLIENT);
 85
 86}
 87
 88/* --Private-AIAMgr-Functions----------------------------------*/
 89
 90/*
 91 * FUNCTION: pkix_pl_AIAMgr_Destroy
 92 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h)
 93 */
 94static PKIX_Error *
 95pkix_pl_AIAMgr_Destroy(
 96        PKIX_PL_Object *object,
 97        void *plContext)
 98{
 99        PKIX_PL_AIAMgr *aiaMgr = NULL;
100
101        PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_Destroy");
102        PKIX_NULLCHECK_ONE(object);
103
104        PKIX_CHECK(pkix_CheckType(object, PKIX_AIAMGR_TYPE, plContext),
105                PKIX_OBJECTNOTAIAMGR);
106
107        aiaMgr = (PKIX_PL_AIAMgr *)object;
108
109        /* pointer to cert cache */
110        /* pointer to crl cache */
111        aiaMgr->method = 0;
112        aiaMgr->aiaIndex = 0;
113        aiaMgr->numAias = 0;
114        PKIX_DECREF(aiaMgr->aia);
115        PKIX_DECREF(aiaMgr->location);
116        PKIX_DECREF(aiaMgr->results);
117        PKIX_DECREF(aiaMgr->client.ldapClient);
118
119cleanup:
120
121        PKIX_RETURN(AIAMGR);
122}
123
124/*
125 * FUNCTION: pkix_pl_AIAMgr_RegisterSelf
126 * DESCRIPTION:
127 *  Registers PKIX_AIAMGR_TYPE and its related functions with systemClasses[]
128 * THREAD SAFETY:
129 *  Not Thread Safe - for performance and complexity reasons
130 *
131 *  Since this function is only called by PKIX_PL_Initialize, which should
132 *  only be called once, it is acceptable that this function is not
133 *  thread-safe.
134 */
135PKIX_Error *
136pkix_pl_AIAMgr_RegisterSelf(void *plContext)
137{
138        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
139        pkix_ClassTable_Entry *entry = &systemClasses[PKIX_AIAMGR_TYPE];
140
141        PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_RegisterSelf");
142
143        entry->description = "AIAMgr";
144        entry->typeObjectSize = sizeof(PKIX_PL_AIAMgr);
145        entry->destructor = pkix_pl_AIAMgr_Destroy;
146
147        PKIX_RETURN(AIAMGR);
148}
149
150/*
151 * FUNCTION: pkix_pl_AiaMgr_FindLDAPClient
152 * DESCRIPTION:
153 *
154 *  This function checks the collection of LDAPClient connections held by the
155 *  AIAMgr pointed to by "aiaMgr" for one matching the domain name given by
156 *  "domainName". The string may include a port number: e.g., "betty.nist.gov"
157 *  or "nss.red.iplanet.com:1389". If a match is found, that LDAPClient is
158 *  stored at "pClient". Otherwise, an LDAPClient is created and added to the
159 *  collection, and then stored at "pClient".
160 *
161 * PARAMETERS:
162 *  "aiaMgr"
163 *      The AIAMgr whose LDAPClient connected are to be managed. Must be
164 *      non-NULL.
165 *  "domainName"
166 *      Address of a string pointing to a server name. Must be non-NULL.
167 *  "pClient"
168 *      Address at which the returned LDAPClient is stored. Must be non-NULL.
169 *  "plContext"
170 *      Platform-specific context pointer.
171 * THREAD SAFETY:
172 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
173 * RETURNS:
174 *  Returns NULL if the function succeeds.
175 *  Returns an AIAMgr Error if the function fails in a non-fatal way
176 *  Returns a Fatal Error if the function fails in an unrecoverable way.
177 */
178static PKIX_Error *
179pkix_pl_AiaMgr_FindLDAPClient(
180        PKIX_PL_AIAMgr *aiaMgr,
181        char *domainName,
182        PKIX_PL_LdapClient **pClient,
183        void *plContext)
184{
185        PKIX_PL_String *domainString = NULL;
186        PKIX_PL_LdapDefaultClient *client = NULL;
187
188        PKIX_ENTER(AIAMGR, "pkix_pl_AiaMgr_FindLDAPClient");
189        PKIX_NULLCHECK_THREE(aiaMgr, domainName, pClient);
190
191        /* create PKIX_PL_String from domain name */
192        PKIX_CHECK(PKIX_PL_String_Create
193                (PKIX_ESCASCII, domainName, 0, &domainString, plContext),
194                PKIX_STRINGCREATEFAILED);
195
196        /* Is this domainName already in cache? */
197        PKIX_CHECK(PKIX_PL_HashTable_Lookup
198                (aiaConnectionCache,
199                (PKIX_PL_Object *)domainString,
200                (PKIX_PL_Object **)&client,
201                plContext),
202                PKIX_HASHTABLELOOKUPFAILED);
203
204        if (client == NULL) {
205
206                /* No, create a connection (and cache it) */
207                PKIX_CHECK(PKIX_PL_LdapDefaultClient_CreateByName
208                        (domainName,
209                         /* Do not use NBIO until we verify, that
210                          * it is working. For now use 1 min timeout. */
211                        PR_SecondsToInterval(
212                            ((PKIX_PL_NssContext*)plContext)->timeoutSeconds),
213                        NULL,
214                        &client,
215                        plContext),
216                        PKIX_LDAPDEFAULTCLIENTCREATEBYNAMEFAILED);
217
218                PKIX_CHECK(PKIX_PL_HashTable_Add
219                        (aiaConnectionCache,
220                        (PKIX_PL_Object *)domainString,
221                        (PKIX_PL_Object *)client,
222                        plContext),
223                        PKIX_HASHTABLEADDFAILED);
224
225        }
226
227        *pClient = (PKIX_PL_LdapClient *)client;
228
229cleanup:
230
231        PKIX_DECREF(domainString);
232
233        PKIX_RETURN(AIAMGR);
234}
235
236PKIX_Error *
237pkix_pl_AIAMgr_GetHTTPCerts(
238        PKIX_PL_AIAMgr *aiaMgr,
239	PKIX_PL_InfoAccess *ia,
240	void **pNBIOContext,
241	PKIX_List **pCerts,
242        void *plContext)
243{
244        PKIX_PL_GeneralName *location = NULL;
245        PKIX_PL_String *locationString = NULL;
246	PKIX_UInt32 len = 0;
247	PRUint16 port = 0;
248	const SEC_HttpClientFcn *httpClient = NULL;
249	const SEC_HttpClientFcnV1 *hcv1 = NULL;
250	SECStatus rv = SECFailure;
251	SEC_HTTP_SERVER_SESSION serverSession = NULL;
252	SEC_HTTP_REQUEST_SESSION requestSession = NULL;	
253	char *path = NULL;
254	char *hostname = NULL;
255	char *locationAscii = NULL;
256	void *nbio = NULL;
257	PRUint16 responseCode = 0;
258	const char *responseContentType = NULL;
259	const char *responseData = NULL;
260
261        PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetHTTPCerts");
262        PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts);
263
264        nbio = *pNBIOContext;
265        *pNBIOContext = NULL;
266        *pCerts = NULL;
267
268        if (nbio == NULL) { /* a new request */
269
270                PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation
271                        (ia, &location, plContext),
272                       PKIX_INFOACCESSGETLOCATIONFAILED);
273
274                /* find or create httpClient = default client */
275		httpClient = SEC_GetRegisteredHttpClient();
276		aiaMgr->client.hdata.httpClient = httpClient;
277		if (!httpClient)
278		    PKIX_ERROR(PKIX_OUTOFMEMORY);
279
280		if (httpClient->version == 1) {
281
282                        PKIX_UInt32 timeout =
283                             ((PKIX_PL_NssContext*)plContext)->timeoutSeconds;
284
285			hcv1 = &(httpClient->fcnTable.ftable1);
286
287			/* create server session */
288			PKIX_TOSTRING(location, &locationString, plContext,
289				PKIX_GENERALNAMETOSTRINGFAILED);
290
291			PKIX_CHECK(PKIX_PL_String_GetEncoded
292				(locationString,
293				PKIX_ESCASCII,
294				(void **)&locationAscii,
295				&len,
296				plContext),
297				PKIX_STRINGGETENCODEDFAILED);
298
299                        rv = CERT_ParseURL(locationAscii, &hostname, &port,
300                                            &path);
301			if ((rv != SECSuccess) ||
302			    (hostname == NULL) ||
303			    (path == NULL)) {
304				PKIX_ERROR(PKIX_URLPARSINGFAILED);
305			}
306
307                        rv = (*hcv1->createSessionFcn)(hostname, port, 
308                                                       &serverSession);
309	                if (rv != SECSuccess) {
310				PKIX_ERROR(PKIX_HTTPCLIENTCREATESESSIONFAILED);
311			}
312
313			aiaMgr->client.hdata.serverSession = serverSession;
314
315			/* create request session */
316                        rv = (*hcv1->createFcn)(serverSession, "http", path,
317                        	"GET", PR_SecondsToInterval(timeout),
318                                 &requestSession);
319                	if (rv != SECSuccess) {
320                        	PKIX_ERROR(PKIX_HTTPSERVERERROR);
321                	}
322
323			aiaMgr->client.hdata.requestSession = requestSession;
324		} else {
325			PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
326		}
327	}
328
329	httpClient = aiaMgr->client.hdata.httpClient;
330
331	if (httpClient->version == 1) {
332                PRUint32 responseDataLen = 
333                   ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
334
335		hcv1 = &(httpClient->fcnTable.ftable1);
336		requestSession = aiaMgr->client.hdata.requestSession;
337
338		/* trySendAndReceive */
339                rv = (*hcv1->trySendAndReceiveFcn)(requestSession,
340                                 (PRPollDesc **)&nbio,
341                                 &responseCode,
342                                 (const char **)&responseContentType,
343                                 NULL, /* &responseHeaders */
344                                 (const char **)&responseData,
345                                 &responseDataLen);
346
347                if (rv != SECSuccess) {
348                        PKIX_ERROR(PKIX_HTTPSERVERERROR);
349                }
350
351                if (nbio != 0) {
352                        *pNBIOContext = nbio;
353                        goto cleanup;
354                }
355
356		PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse
357	                (responseCode,
358	                responseContentType,
359	                responseData,
360	                responseDataLen,
361	                pCerts,
362	                plContext),
363	                PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED);
364                
365                /* Session and request cleanup in case of success */
366                if (aiaMgr->client.hdata.requestSession != NULL) {
367                    (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession);
368                    aiaMgr->client.hdata.requestSession = NULL;
369                }
370                if (aiaMgr->client.hdata.serverSession != NULL) {
371                    (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession);
372                    aiaMgr->client.hdata.serverSession = NULL;
373                }
374                aiaMgr->client.hdata.httpClient = 0; /* callback fn */
375
376        } else  {
377		PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
378	}
379
380cleanup:
381        /* Session and request cleanup in case of error. Passing through without cleanup
382         * if interrupted by blocked IO. */
383        if (PKIX_ERROR_RECEIVED && aiaMgr) {
384            if (aiaMgr->client.hdata.requestSession != NULL) {
385                (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession);
386                aiaMgr->client.hdata.requestSession = NULL;
387            }
388            if (aiaMgr->client.hdata.serverSession != NULL) {
389                (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession);
390                aiaMgr->client.hdata.serverSession = NULL;
391            }
392            aiaMgr->client.hdata.httpClient = 0; /* callback fn */
393        }
394
395        PKIX_DECREF(location);
396        PKIX_DECREF(locationString);
397
398        if (locationAscii) {
399            PORT_Free(locationAscii);
400        }
401        if (hostname) {
402            PORT_Free(hostname);
403        }
404        if (path) {
405            PORT_Free(path);
406        }
407
408        PKIX_RETURN(AIAMGR);
409}
410
411PKIX_Error *
412pkix_pl_AIAMgr_GetLDAPCerts(
413        PKIX_PL_AIAMgr *aiaMgr,
414	PKIX_PL_InfoAccess *ia,
415	void **pNBIOContext,
416	PKIX_List **pCerts,
417        void *plContext)
418{
419        PKIX_List *result = NULL;
420        PKIX_PL_GeneralName *location = NULL;
421        PKIX_PL_LdapClient *client = NULL;
422        LDAPRequestParams request;
423        PRArenaPool *arena = NULL;
424        char *domainName = NULL;
425	void *nbio = NULL;
426
427        PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetLDAPCerts");
428        PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts);
429
430        nbio = *pNBIOContext;
431        *pNBIOContext = NULL;
432        *pCerts = NULL;
433
434        if (nbio == NULL) { /* a new request */
435
436                /* Initiate an LDAP request */
437
438                request.scope = WHOLE_SUBTREE;
439                request.derefAliases = NEVER_DEREF;
440                request.sizeLimit = 0;
441                request.timeLimit = 0;
442
443                PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation
444                        (ia, &location, plContext),
445                        PKIX_INFOACCESSGETLOCATIONFAILED);
446
447                /*
448                 * Get a short-lived arena. We'll be done with
449                 * this space once the request is encoded.
450                 */
451                arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
452                if (!arena) {
453                        PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
454                }
455
456                PKIX_CHECK(pkix_pl_InfoAccess_ParseLocation
457                        (location, arena, &request, &domainName, plContext),
458                        PKIX_INFOACCESSPARSELOCATIONFAILED);
459
460                PKIX_DECREF(location);
461
462                /* Find or create a connection to LDAP server */
463                PKIX_CHECK(pkix_pl_AiaMgr_FindLDAPClient
464                        (aiaMgr, domainName, &client, plContext),
465                        PKIX_AIAMGRFINDLDAPCLIENTFAILED);
466
467                aiaMgr->client.ldapClient = client;
468
469                PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
470                        (aiaMgr->client.ldapClient,
471			&request,
472			&nbio,
473			&result,
474			plContext),
475                        PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
476
477                PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));
478
479        } else {
480
481                PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
482                        (aiaMgr->client.ldapClient, &nbio, &result, plContext),
483                        PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
484
485        }
486
487        if (nbio != NULL) { /* WOULDBLOCK */
488                *pNBIOContext = nbio;
489                *pCerts = NULL;
490                goto cleanup;
491        }
492
493	PKIX_DECREF(aiaMgr->client.ldapClient);
494
495	if (result == NULL) {
496		*pCerts = NULL;
497	} else {
498		PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
499			(result, pCerts, plContext),
500			PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
501	}
502
503	*pNBIOContext = nbio;
504
505cleanup:
506
507        if (arena && (PKIX_ERROR_RECEIVED)) {
508                PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));
509        }
510
511        if (PKIX_ERROR_RECEIVED) {
512	        PKIX_DECREF(aiaMgr->client.ldapClient);
513	}
514
515        PKIX_DECREF(location);
516
517        PKIX_RETURN(AIAMGR);
518}
519
520/*
521 * FUNCTION: PKIX_PL_AIAMgr_Create
522 * DESCRIPTION:
523 *
524 *  This function creates an AIAMgr, storing the result at "pAIAMgr".
525 *
526 * PARAMETERS:
527 *  "pAIAMGR"
528 *      Address at which the returned AIAMgr is stored. Must be non-NULL.
529 *  "plContext"
530 *      Platform-specific context pointer.
531 * THREAD SAFETY:
532 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
533 * RETURNS:
534 *  Returns NULL if the function succeeds.
535 *  Returns an AIAMgr Error if the function fails in a non-fatal way
536 *  Returns a Fatal Error if the function fails in an unrecoverable way.
537 */
538PKIX_Error *
539PKIX_PL_AIAMgr_Create(
540        PKIX_PL_AIAMgr **pAIAMgr,
541        void *plContext)
542{
543        PKIX_PL_AIAMgr *aiaMgr = NULL;
544
545        PKIX_ENTER(AIAMGR, "PKIX_PL_AIAMgr_Create");
546        PKIX_NULLCHECK_ONE(pAIAMgr);
547
548        PKIX_CHECK(PKIX_PL_Object_Alloc
549                (PKIX_AIAMGR_TYPE,
550                sizeof(PKIX_PL_AIAMgr),
551                (PKIX_PL_Object **)&aiaMgr,
552                plContext),
553                PKIX_COULDNOTCREATEAIAMGROBJECT);
554        /* pointer to cert cache */
555        /* pointer to crl cache */
556        aiaMgr->method = 0;
557        aiaMgr->aiaIndex = 0;
558        aiaMgr->numAias = 0;
559        aiaMgr->aia = NULL;
560        aiaMgr->location = NULL;
561        aiaMgr->results = NULL;
562        aiaMgr->client.hdata.httpClient = NULL;
563	aiaMgr->client.hdata.serverSession = NULL;
564	aiaMgr->client.hdata.requestSession = NULL;
565
566        *pAIAMgr = aiaMgr;
567
568cleanup:
569
570        PKIX_RETURN(AIAMGR);
571}
572
573/* --Public-Functions------------------------------------------------------- */
574
575/*
576 * FUNCTION: PKIX_PL_AIAMgr_GetAIACerts (see description in pkix_pl_pki.h)
577 */
578PKIX_Error *
579PKIX_PL_AIAMgr_GetAIACerts(
580        PKIX_PL_AIAMgr *aiaMgr,
581        PKIX_PL_Cert *prevCert,
582        void **pNBIOContext,
583        PKIX_List **pCerts,
584        void *plContext)
585{
586        PKIX_UInt32 numAias = 0;
587        PKIX_UInt32 aiaIndex = 0;
588        PKIX_UInt32 iaType = PKIX_INFOACCESS_LOCATION_UNKNOWN;
589        PKIX_List *certs = NULL;
590        PKIX_PL_InfoAccess *ia = NULL;
591        void *nbio = NULL;
592
593        PKIX_ENTER(AIAMGR, "PKIX_PL_AIAMgr_GetAIACerts");
594        PKIX_NULLCHECK_FOUR(aiaMgr, prevCert, pNBIOContext, pCerts);
595
596        nbio = *pNBIOContext;
597        *pCerts = NULL;
598        *pNBIOContext = NULL;
599
600        if (nbio == NULL) { /* a new request */
601
602                /* Does this Cert have an AIA extension? */
603                PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess
604                        (prevCert, &aiaMgr->aia, plContext),
605                        PKIX_CERTGETAUTHORITYINFOACCESSFAILED);
606
607                if (aiaMgr->aia != NULL) {
608                        PKIX_CHECK(PKIX_List_GetLength
609                                (aiaMgr->aia, &numAias, plContext),
610                                PKIX_LISTGETLENGTHFAILED);
611                }
612
613                /* And if so, does it have any entries? */
614                if ((aiaMgr->aia == NULL) || (numAias == 0)) {
615                        *pCerts = NULL;
616                        goto cleanup;
617                }
618
619                aiaMgr->aiaIndex = 0;
620                aiaMgr->numAias = numAias;
621                aiaMgr->results = NULL;
622
623        }
624
625        for (aiaIndex = aiaMgr->aiaIndex;
626                aiaIndex < aiaMgr->numAias;
627                aiaIndex ++) {
628                PKIX_UInt32 method = 0;
629
630                PKIX_CHECK(PKIX_List_GetItem
631                        (aiaMgr->aia,
632                        aiaIndex,
633                        (PKIX_PL_Object **)&ia,
634                        plContext),
635                        PKIX_LISTGETITEMFAILED);
636
637                PKIX_CHECK(PKIX_PL_InfoAccess_GetMethod
638                        (ia, &method, plContext),
639                        PKIX_INFOACCESSGETMETHODFAILED);
640
641                if (method != PKIX_INFOACCESS_CA_ISSUERS &&
642                    method != PKIX_INFOACCESS_CA_REPOSITORY) {
643                    PKIX_DECREF(ia);
644                    continue;
645                }
646                
647                PKIX_CHECK(PKIX_PL_InfoAccess_GetLocationType
648                        (ia, &iaType, plContext),
649                        PKIX_INFOACCESSGETLOCATIONTYPEFAILED);
650
651                if (iaType == PKIX_INFOACCESS_LOCATION_HTTP) {
652			PKIX_CHECK(pkix_pl_AIAMgr_GetHTTPCerts
653				(aiaMgr, ia, &nbio, &certs, plContext),
654				PKIX_AIAMGRGETHTTPCERTSFAILED);
655                } else if (iaType == PKIX_INFOACCESS_LOCATION_LDAP) {
656			PKIX_CHECK(pkix_pl_AIAMgr_GetLDAPCerts
657				(aiaMgr, ia, &nbio, &certs, plContext),
658				PKIX_AIAMGRGETLDAPCERTSFAILED);
659                } else {
660                        /* We only support http and ldap requests. */
661                        PKIX_DECREF(ia);
662                        continue;
663                }
664
665                if (nbio != NULL) { /* WOULDBLOCK */
666                        aiaMgr->aiaIndex = aiaIndex;
667                        *pNBIOContext = nbio;
668                        *pCerts = NULL;
669                        goto cleanup;
670                }
671
672                /*
673                 * We can't just use and modify the List we received.
674                 * Because it's cached, it's set immutable.
675                 */
676                if (aiaMgr->results == NULL) {
677                        PKIX_CHECK(PKIX_List_Create
678                                (&(aiaMgr->results), plContext),
679                                PKIX_LISTCREATEFAILED);
680                }
681                PKIX_CHECK(pkix_List_AppendList
682                        (aiaMgr->results, certs, plContext),
683                        PKIX_APPENDLISTFAILED);
684                PKIX_DECREF(certs);
685
686                PKIX_DECREF(ia);
687        }
688
689        PKIX_DECREF(aiaMgr->aia);
690
691        *pNBIOContext = NULL;
692        *pCerts = aiaMgr->results;
693        aiaMgr->results = NULL;
694
695cleanup:
696
697        if (PKIX_ERROR_RECEIVED) {
698                PKIX_DECREF(aiaMgr->aia);
699                PKIX_DECREF(aiaMgr->results);
700                PKIX_DECREF(aiaMgr->client.ldapClient);
701        }
702
703        PKIX_DECREF(certs);
704        PKIX_DECREF(ia);
705
706        PKIX_RETURN(AIAMGR);
707}