| OLD | NEW |
| (Empty) |
| 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 && aiaMgr) { | |
| 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 } | |
| OLD | NEW |