summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c')
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c699
1 files changed, 699 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c
new file mode 100644
index 000000000..d9f566230
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c
@@ -0,0 +1,699 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_aiamgr.c
+ *
+ * AIAMgr Object Definitions
+ *
+ */
+
+#include "pkix_pl_aiamgr.h"
+extern PKIX_PL_HashTable *aiaConnectionCache;
+
+#ifndef NSS_PKIX_NO_LDAP
+/* --Virtual-LdapClient-Functions------------------------------------ */
+
+PKIX_Error *
+PKIX_PL_LdapClient_InitiateRequest(
+ PKIX_PL_LdapClient *client,
+ LDAPRequestParams *requestParams,
+ void **pNBIO,
+ PKIX_List **pResponse,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPCLIENT, "PKIX_PL_LdapClient_InitiateRequest");
+ PKIX_NULLCHECK_TWO(client, client->initiateFcn);
+
+ PKIX_CHECK(client->initiateFcn
+ (client, requestParams, pNBIO, pResponse, plContext),
+ PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
+cleanup:
+
+ PKIX_RETURN(LDAPCLIENT);
+
+}
+
+PKIX_Error *
+PKIX_PL_LdapClient_ResumeRequest(
+ PKIX_PL_LdapClient *client,
+ void **pNBIO,
+ PKIX_List **pResponse,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPCLIENT, "PKIX_PL_LdapClient_ResumeRequest");
+ PKIX_NULLCHECK_TWO(client, client->resumeFcn);
+
+ PKIX_CHECK(client->resumeFcn
+ (client, pNBIO, pResponse, plContext),
+ PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
+cleanup:
+
+ PKIX_RETURN(LDAPCLIENT);
+
+}
+#endif /* !NSS_PKIX_NO_LDAP */
+
+/* --Private-AIAMgr-Functions----------------------------------*/
+
+/*
+ * FUNCTION: pkix_pl_AIAMgr_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_AIAMgr_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_AIAMgr *aiaMgr = NULL;
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_AIAMGR_TYPE, plContext),
+ PKIX_OBJECTNOTAIAMGR);
+
+ aiaMgr = (PKIX_PL_AIAMgr *)object;
+
+ /* pointer to cert cache */
+ /* pointer to crl cache */
+ aiaMgr->method = 0;
+ aiaMgr->aiaIndex = 0;
+ aiaMgr->numAias = 0;
+ PKIX_DECREF(aiaMgr->aia);
+ PKIX_DECREF(aiaMgr->location);
+ PKIX_DECREF(aiaMgr->results);
+#ifndef NSS_PKIX_NO_LDAP
+ PKIX_DECREF(aiaMgr->client.ldapClient);
+#endif
+
+cleanup:
+
+ PKIX_RETURN(AIAMGR);
+}
+
+/*
+ * FUNCTION: pkix_pl_AIAMgr_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_AIAMGR_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_AIAMgr_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_AIAMGR_TYPE];
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_RegisterSelf");
+
+ entry->description = "AIAMgr";
+ entry->typeObjectSize = sizeof(PKIX_PL_AIAMgr);
+ entry->destructor = pkix_pl_AIAMgr_Destroy;
+
+ PKIX_RETURN(AIAMGR);
+}
+
+#ifndef NSS_PKIX_NO_LDAP
+/*
+ * FUNCTION: pkix_pl_AiaMgr_FindLDAPClient
+ * DESCRIPTION:
+ *
+ * This function checks the collection of LDAPClient connections held by the
+ * AIAMgr pointed to by "aiaMgr" for one matching the domain name given by
+ * "domainName". The string may include a port number: e.g., "betty.nist.gov"
+ * or "nss.red.iplanet.com:1389". If a match is found, that LDAPClient is
+ * stored at "pClient". Otherwise, an LDAPClient is created and added to the
+ * collection, and then stored at "pClient".
+ *
+ * PARAMETERS:
+ * "aiaMgr"
+ * The AIAMgr whose LDAPClient connected are to be managed. Must be
+ * non-NULL.
+ * "domainName"
+ * Address of a string pointing to a server name. Must be non-NULL.
+ * An empty string (which means no <host> is given in the LDAP URL) is
+ * not supported.
+ * "pClient"
+ * Address at which the returned LDAPClient is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an AIAMgr Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_AiaMgr_FindLDAPClient(
+ PKIX_PL_AIAMgr *aiaMgr,
+ char *domainName,
+ PKIX_PL_LdapClient **pClient,
+ void *plContext)
+{
+ PKIX_PL_String *domainString = NULL;
+ PKIX_PL_LdapDefaultClient *client = NULL;
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AiaMgr_FindLDAPClient");
+ PKIX_NULLCHECK_THREE(aiaMgr, domainName, pClient);
+
+ /*
+ * An LDAP URL may not have a <host> part, for example,
+ * ldap:///o=University%20of%20Michigan,c=US
+ * PKIX_PL_LdapDefaultClient doesn't know how to discover the default
+ * LDAP server, so we don't support this kind of LDAP URL.
+ */
+ if (*domainName == '\0') {
+ /* Simulate a PKIX_PL_LdapDefaultClient_CreateByName failure. */
+ PKIX_ERROR(PKIX_LDAPDEFAULTCLIENTCREATEBYNAMEFAILED);
+ }
+
+ /* create PKIX_PL_String from domain name */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, domainName, 0, &domainString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Is this domainName already in cache? */
+ PKIX_CHECK(PKIX_PL_HashTable_Lookup
+ (aiaConnectionCache,
+ (PKIX_PL_Object *)domainString,
+ (PKIX_PL_Object **)&client,
+ plContext),
+ PKIX_HASHTABLELOOKUPFAILED);
+
+ if (client == NULL) {
+
+ /* No, create a connection (and cache it) */
+ PKIX_CHECK(PKIX_PL_LdapDefaultClient_CreateByName
+ (domainName,
+ /* Do not use NBIO until we verify, that
+ * it is working. For now use 1 min timeout. */
+ PR_SecondsToInterval(
+ ((PKIX_PL_NssContext*)plContext)->timeoutSeconds),
+ NULL,
+ &client,
+ plContext),
+ PKIX_LDAPDEFAULTCLIENTCREATEBYNAMEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Add
+ (aiaConnectionCache,
+ (PKIX_PL_Object *)domainString,
+ (PKIX_PL_Object *)client,
+ plContext),
+ PKIX_HASHTABLEADDFAILED);
+
+ }
+
+ *pClient = (PKIX_PL_LdapClient *)client;
+
+cleanup:
+
+ PKIX_DECREF(domainString);
+
+ PKIX_RETURN(AIAMGR);
+}
+#endif /* !NSS_PKIX_NO_LDAP */
+
+PKIX_Error *
+pkix_pl_AIAMgr_GetHTTPCerts(
+ PKIX_PL_AIAMgr *aiaMgr,
+ PKIX_PL_InfoAccess *ia,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *location = NULL;
+ PKIX_PL_String *locationString = NULL;
+ PKIX_UInt32 len = 0;
+ PRUint16 port = 0;
+ const SEC_HttpClientFcn *httpClient = NULL;
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ SECStatus rv = SECFailure;
+ SEC_HTTP_SERVER_SESSION serverSession = NULL;
+ SEC_HTTP_REQUEST_SESSION requestSession = NULL;
+ char *path = NULL;
+ char *hostname = NULL;
+ char *locationAscii = NULL;
+ void *nbio = NULL;
+ PRUint16 responseCode = 0;
+ const char *responseContentType = NULL;
+ const char *responseData = NULL;
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetHTTPCerts");
+ PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts);
+
+ nbio = *pNBIOContext;
+ *pNBIOContext = NULL;
+ *pCerts = NULL;
+
+ if (nbio == NULL) { /* a new request */
+
+ PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation
+ (ia, &location, plContext),
+ PKIX_INFOACCESSGETLOCATIONFAILED);
+
+ /* find or create httpClient = default client */
+ httpClient = SEC_GetRegisteredHttpClient();
+ aiaMgr->client.hdata.httpClient = httpClient;
+ if (!httpClient)
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+
+ if (httpClient->version == 1) {
+
+ PKIX_UInt32 timeout =
+ ((PKIX_PL_NssContext*)plContext)->timeoutSeconds;
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+
+ /* create server session */
+ PKIX_TOSTRING(location, &locationString, plContext,
+ PKIX_GENERALNAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (locationString,
+ PKIX_ESCASCII,
+ (void **)&locationAscii,
+ &len,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ rv = CERT_ParseURL(locationAscii, &hostname, &port,
+ &path);
+ if ((rv != SECSuccess) ||
+ (hostname == NULL) ||
+ (path == NULL)) {
+ PKIX_ERROR(PKIX_URLPARSINGFAILED);
+ }
+
+ rv = (*hcv1->createSessionFcn)(hostname, port,
+ &serverSession);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPCLIENTCREATESESSIONFAILED);
+ }
+
+ aiaMgr->client.hdata.serverSession = serverSession;
+
+ /* create request session */
+ rv = (*hcv1->createFcn)(serverSession, "http", path,
+ "GET", PR_SecondsToInterval(timeout),
+ &requestSession);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPSERVERERROR);
+ }
+
+ aiaMgr->client.hdata.requestSession = requestSession;
+ } else {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+ }
+
+ httpClient = aiaMgr->client.hdata.httpClient;
+
+ if (httpClient->version == 1) {
+ PRUint32 responseDataLen =
+ ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+ requestSession = aiaMgr->client.hdata.requestSession;
+
+ /* trySendAndReceive */
+ rv = (*hcv1->trySendAndReceiveFcn)(requestSession,
+ (PRPollDesc **)&nbio,
+ &responseCode,
+ (const char **)&responseContentType,
+ NULL, /* &responseHeaders */
+ (const char **)&responseData,
+ &responseDataLen);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPSERVERERROR);
+ }
+
+ if (nbio != 0) {
+ *pNBIOContext = nbio;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse
+ (responseCode,
+ responseContentType,
+ responseData,
+ responseDataLen,
+ pCerts,
+ plContext),
+ PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED);
+
+ /* Session and request cleanup in case of success */
+ if (aiaMgr->client.hdata.requestSession != NULL) {
+ (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession);
+ aiaMgr->client.hdata.requestSession = NULL;
+ }
+ if (aiaMgr->client.hdata.serverSession != NULL) {
+ (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession);
+ aiaMgr->client.hdata.serverSession = NULL;
+ }
+ aiaMgr->client.hdata.httpClient = 0; /* callback fn */
+
+ } else {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+
+cleanup:
+ /* Session and request cleanup in case of error. Passing through without cleanup
+ * if interrupted by blocked IO. */
+ if (PKIX_ERROR_RECEIVED) {
+ if (aiaMgr->client.hdata.requestSession != NULL) {
+ (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession);
+ aiaMgr->client.hdata.requestSession = NULL;
+ }
+ if (aiaMgr->client.hdata.serverSession != NULL) {
+ (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession);
+ aiaMgr->client.hdata.serverSession = NULL;
+ }
+ aiaMgr->client.hdata.httpClient = 0; /* callback fn */
+ }
+
+ PKIX_DECREF(location);
+ PKIX_DECREF(locationString);
+
+ if (locationAscii) {
+ PORT_Free(locationAscii);
+ }
+ if (hostname) {
+ PORT_Free(hostname);
+ }
+ if (path) {
+ PORT_Free(path);
+ }
+
+ PKIX_RETURN(AIAMGR);
+}
+
+#ifndef NSS_PKIX_NO_LDAP
+PKIX_Error *
+pkix_pl_AIAMgr_GetLDAPCerts(
+ PKIX_PL_AIAMgr *aiaMgr,
+ PKIX_PL_InfoAccess *ia,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ PKIX_List *result = NULL;
+ PKIX_PL_GeneralName *location = NULL;
+ PKIX_PL_LdapClient *client = NULL;
+ LDAPRequestParams request;
+ PLArenaPool *arena = NULL;
+ char *domainName = NULL;
+ void *nbio = NULL;
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetLDAPCerts");
+ PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts);
+
+ nbio = *pNBIOContext;
+ *pNBIOContext = NULL;
+ *pCerts = NULL;
+
+ if (nbio == NULL) { /* a new request */
+
+ /* Initiate an LDAP request */
+
+ request.scope = WHOLE_SUBTREE;
+ request.derefAliases = NEVER_DEREF;
+ request.sizeLimit = 0;
+ request.timeLimit = 0;
+
+ PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation
+ (ia, &location, plContext),
+ PKIX_INFOACCESSGETLOCATIONFAILED);
+
+ /*
+ * Get a short-lived arena. We'll be done with
+ * this space once the request is encoded.
+ */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CHECK(pkix_pl_InfoAccess_ParseLocation
+ (location, arena, &request, &domainName, plContext),
+ PKIX_INFOACCESSPARSELOCATIONFAILED);
+
+ PKIX_DECREF(location);
+
+ /* Find or create a connection to LDAP server */
+ PKIX_CHECK(pkix_pl_AiaMgr_FindLDAPClient
+ (aiaMgr, domainName, &client, plContext),
+ PKIX_AIAMGRFINDLDAPCLIENTFAILED);
+
+ aiaMgr->client.ldapClient = client;
+
+ PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
+ (aiaMgr->client.ldapClient,
+ &request,
+ &nbio,
+ &result,
+ plContext),
+ PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
+
+ PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));
+
+ } else {
+
+ PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
+ (aiaMgr->client.ldapClient, &nbio, &result, plContext),
+ PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
+
+ }
+
+ if (nbio != NULL) { /* WOULDBLOCK */
+ *pNBIOContext = nbio;
+ *pCerts = NULL;
+ goto cleanup;
+ }
+
+ PKIX_DECREF(aiaMgr->client.ldapClient);
+
+ if (result == NULL) {
+ *pCerts = NULL;
+ } else {
+ PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
+ (result, pCerts, plContext),
+ PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
+ }
+
+ *pNBIOContext = nbio;
+
+cleanup:
+
+ if (arena && (PKIX_ERROR_RECEIVED)) {
+ PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));
+ }
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(aiaMgr->client.ldapClient);
+ }
+
+ PKIX_DECREF(location);
+
+ PKIX_RETURN(AIAMGR);
+}
+#endif /* !NSS_PKIX_NO_LDAP */
+
+/*
+ * FUNCTION: PKIX_PL_AIAMgr_Create
+ * DESCRIPTION:
+ *
+ * This function creates an AIAMgr, storing the result at "pAIAMgr".
+ *
+ * PARAMETERS:
+ * "pAIAMGR"
+ * Address at which the returned AIAMgr is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an AIAMgr Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_AIAMgr_Create(
+ PKIX_PL_AIAMgr **pAIAMgr,
+ void *plContext)
+{
+ PKIX_PL_AIAMgr *aiaMgr = NULL;
+
+ PKIX_ENTER(AIAMGR, "PKIX_PL_AIAMgr_Create");
+ PKIX_NULLCHECK_ONE(pAIAMgr);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_AIAMGR_TYPE,
+ sizeof(PKIX_PL_AIAMgr),
+ (PKIX_PL_Object **)&aiaMgr,
+ plContext),
+ PKIX_COULDNOTCREATEAIAMGROBJECT);
+ /* pointer to cert cache */
+ /* pointer to crl cache */
+ aiaMgr->method = 0;
+ aiaMgr->aiaIndex = 0;
+ aiaMgr->numAias = 0;
+ aiaMgr->aia = NULL;
+ aiaMgr->location = NULL;
+ aiaMgr->results = NULL;
+ aiaMgr->client.hdata.httpClient = NULL;
+ aiaMgr->client.hdata.serverSession = NULL;
+ aiaMgr->client.hdata.requestSession = NULL;
+
+ *pAIAMgr = aiaMgr;
+
+cleanup:
+
+ PKIX_RETURN(AIAMGR);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_AIAMgr_GetAIACerts (see description in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_AIAMgr_GetAIACerts(
+ PKIX_PL_AIAMgr *aiaMgr,
+ PKIX_PL_Cert *prevCert,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ PKIX_UInt32 numAias = 0;
+ PKIX_UInt32 aiaIndex = 0;
+ PKIX_UInt32 iaType = PKIX_INFOACCESS_LOCATION_UNKNOWN;
+ PKIX_List *certs = NULL;
+ PKIX_PL_InfoAccess *ia = NULL;
+ void *nbio = NULL;
+
+ PKIX_ENTER(AIAMGR, "PKIX_PL_AIAMgr_GetAIACerts");
+ PKIX_NULLCHECK_FOUR(aiaMgr, prevCert, pNBIOContext, pCerts);
+
+ nbio = *pNBIOContext;
+ *pCerts = NULL;
+ *pNBIOContext = NULL;
+
+ if (nbio == NULL) { /* a new request */
+
+ /* Does this Cert have an AIA extension? */
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess
+ (prevCert, &aiaMgr->aia, plContext),
+ PKIX_CERTGETAUTHORITYINFOACCESSFAILED);
+
+ if (aiaMgr->aia != NULL) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (aiaMgr->aia, &numAias, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ /* And if so, does it have any entries? */
+ if ((aiaMgr->aia == NULL) || (numAias == 0)) {
+ *pCerts = NULL;
+ goto cleanup;
+ }
+
+ aiaMgr->aiaIndex = 0;
+ aiaMgr->numAias = numAias;
+ aiaMgr->results = NULL;
+
+ }
+
+ for (aiaIndex = aiaMgr->aiaIndex;
+ aiaIndex < aiaMgr->numAias;
+ aiaIndex ++) {
+ PKIX_UInt32 method = 0;
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (aiaMgr->aia,
+ aiaIndex,
+ (PKIX_PL_Object **)&ia,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_InfoAccess_GetMethod
+ (ia, &method, plContext),
+ PKIX_INFOACCESSGETMETHODFAILED);
+
+ if (method != PKIX_INFOACCESS_CA_ISSUERS &&
+ method != PKIX_INFOACCESS_CA_REPOSITORY) {
+ PKIX_DECREF(ia);
+ continue;
+ }
+
+ PKIX_CHECK(PKIX_PL_InfoAccess_GetLocationType
+ (ia, &iaType, plContext),
+ PKIX_INFOACCESSGETLOCATIONTYPEFAILED);
+
+ if (iaType == PKIX_INFOACCESS_LOCATION_HTTP) {
+ PKIX_CHECK(pkix_pl_AIAMgr_GetHTTPCerts
+ (aiaMgr, ia, &nbio, &certs, plContext),
+ PKIX_AIAMGRGETHTTPCERTSFAILED);
+#ifndef NSS_PKIX_NO_LDAP
+ } else if (iaType == PKIX_INFOACCESS_LOCATION_LDAP) {
+ PKIX_CHECK(pkix_pl_AIAMgr_GetLDAPCerts
+ (aiaMgr, ia, &nbio, &certs, plContext),
+ PKIX_AIAMGRGETLDAPCERTSFAILED);
+#endif
+ } else {
+ /* We only support http and ldap requests. */
+ PKIX_DECREF(ia);
+ continue;
+ }
+
+ if (nbio != NULL) { /* WOULDBLOCK */
+ aiaMgr->aiaIndex = aiaIndex;
+ *pNBIOContext = nbio;
+ *pCerts = NULL;
+ goto cleanup;
+ }
+
+ /*
+ * We can't just use and modify the List we received.
+ * Because it's cached, it's set immutable.
+ */
+ if (aiaMgr->results == NULL) {
+ PKIX_CHECK(PKIX_List_Create
+ (&(aiaMgr->results), plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+ PKIX_CHECK(pkix_List_AppendList
+ (aiaMgr->results, certs, plContext),
+ PKIX_APPENDLISTFAILED);
+ PKIX_DECREF(certs);
+
+ PKIX_DECREF(ia);
+ }
+
+ PKIX_DECREF(aiaMgr->aia);
+
+ *pNBIOContext = NULL;
+ *pCerts = aiaMgr->results;
+ aiaMgr->results = NULL;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(aiaMgr->aia);
+ PKIX_DECREF(aiaMgr->results);
+#ifndef NSS_PKIX_NO_LDAP
+ PKIX_DECREF(aiaMgr->client.ldapClient);
+#endif
+ }
+
+ PKIX_DECREF(certs);
+ PKIX_DECREF(ia);
+
+ PKIX_RETURN(AIAMGR);
+}