tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_pl_aiamgr.c (22203B)


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