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