mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-09-05 23:54:38 +00:00
700 lines
22 KiB
C
700 lines
22 KiB
C
/* 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);
|
|
}
|