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_httpcertstore.c | |
6 * | |
7 * HTTPCertStore Function Definitions | |
8 * | |
9 */ | |
10 | |
11 /* We can't decode the length of a message without at least this many bytes */ | |
12 | |
13 #include "pkix_pl_httpcertstore.h" | |
14 extern PKIX_PL_HashTable *httpSocketCache; | |
15 SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate) | |
16 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) | |
17 SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate) | |
18 SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate) | |
19 | |
20 SEC_ASN1_CHOOSER_DECLARE(CERT_IssuerAndSNTemplate) | |
21 SEC_ASN1_CHOOSER_DECLARE(SECOID_AlgorithmIDTemplate) | |
22 /* SEC_ASN1_CHOOSER_DECLARE(SEC_SetOfAnyTemplate) | |
23 SEC_ASN1_CHOOSER_DECLARE(CERT_SetOfSignedCrlTemplate) | |
24 | |
25 const SEC_ASN1Template CERT_IssuerAndSNTemplate[] = { | |
26 { SEC_ASN1_SEQUENCE, | |
27 0, NULL, sizeof(CERTIssuerAndSN) }, | |
28 { SEC_ASN1_SAVE, | |
29 offsetof(CERTIssuerAndSN,derIssuer) }, | |
30 { SEC_ASN1_INLINE, | |
31 offsetof(CERTIssuerAndSN,issuer), | |
32 CERT_NameTemplate }, | |
33 { SEC_ASN1_INTEGER, | |
34 offsetof(CERTIssuerAndSN,serialNumber) }, | |
35 { 0 } | |
36 }; | |
37 | |
38 const SEC_ASN1Template SECOID_AlgorithmIDTemplate[] = { | |
39 { SEC_ASN1_SEQUENCE, | |
40 0, NULL, sizeof(SECAlgorithmID) }, | |
41 { SEC_ASN1_OBJECT_ID, | |
42 offsetof(SECAlgorithmID,algorithm) }, | |
43 { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, | |
44 offsetof(SECAlgorithmID,parameters) }, | |
45 { 0 } | |
46 }; */ | |
47 | |
48 /* --Private-HttpCertStoreContext-Object Functions----------------------- */ | |
49 | |
50 /* | |
51 * FUNCTION: pkix_pl_HttpCertStoreContext_Destroy | |
52 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
53 */ | |
54 static PKIX_Error * | |
55 pkix_pl_HttpCertStoreContext_Destroy( | |
56 PKIX_PL_Object *object, | |
57 void *plContext) | |
58 { | |
59 const SEC_HttpClientFcnV1 *hcv1 = NULL; | |
60 PKIX_PL_HttpCertStoreContext *context = NULL; | |
61 | |
62 PKIX_ENTER | |
63 (HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStoreContext_Destroy"); | |
64 PKIX_NULLCHECK_ONE(object); | |
65 | |
66 PKIX_CHECK(pkix_CheckType | |
67 (object, PKIX_HTTPCERTSTORECONTEXT_TYPE, plContext), | |
68 PKIX_OBJECTNOTANHTTPCERTSTORECONTEXT); | |
69 | |
70 context = (PKIX_PL_HttpCertStoreContext *)object; | |
71 hcv1 = (const SEC_HttpClientFcnV1 *)(context->client); | |
72 if (context->requestSession != NULL) { | |
73 (*hcv1->freeFcn)(context->requestSession); | |
74 context->requestSession = NULL; | |
75 } | |
76 if (context->serverSession != NULL) { | |
77 (*hcv1->freeSessionFcn)(context->serverSession); | |
78 context->serverSession = NULL; | |
79 } | |
80 if (context->path != NULL) { | |
81 PORT_Free(context->path); | |
82 context->path = NULL; | |
83 } | |
84 | |
85 cleanup: | |
86 | |
87 PKIX_RETURN(HTTPCERTSTORECONTEXT); | |
88 } | |
89 | |
90 /* | |
91 * FUNCTION: pkix_pl_HttpCertStoreContext_RegisterSelf | |
92 * | |
93 * DESCRIPTION: | |
94 * Registers PKIX_PL_HTTPCERTSTORECONTEXT_TYPE and its related | |
95 * functions with systemClasses[] | |
96 * | |
97 * THREAD SAFETY: | |
98 * Not Thread Safe - for performance and complexity reasons | |
99 * | |
100 * Since this function is only called by PKIX_PL_Initialize, which should | |
101 * only be called once, it is acceptable that this function is not | |
102 * thread-safe. | |
103 */ | |
104 PKIX_Error * | |
105 pkix_pl_HttpCertStoreContext_RegisterSelf(void *plContext) | |
106 { | |
107 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
108 pkix_ClassTable_Entry *entry = &systemClasses[PKIX_HTTPCERTSTORECONTEXT_
TYPE]; | |
109 | |
110 PKIX_ENTER(HTTPCERTSTORECONTEXT, | |
111 "pkix_pl_HttpCertStoreContext_RegisterSelf"); | |
112 | |
113 entry->description = "HttpCertStoreContext"; | |
114 entry->typeObjectSize = sizeof(PKIX_PL_HttpCertStoreContext); | |
115 entry->destructor = pkix_pl_HttpCertStoreContext_Destroy; | |
116 | |
117 PKIX_RETURN(HTTPCERTSTORECONTEXT); | |
118 } | |
119 | |
120 | |
121 /* --Private-Http-CertStore-Database-Functions----------------------- */ | |
122 | |
123 typedef struct callbackContextStruct { | |
124 PKIX_List *pkixCertList; | |
125 PKIX_Error *error; | |
126 void *plContext; | |
127 } callbackContext; | |
128 | |
129 | |
130 /* | |
131 * FUNCTION: certCallback | |
132 * DESCRIPTION: | |
133 * | |
134 * This function processes the null-terminated array of SECItems produced by | |
135 * extracting the contents of a signedData message received in response to an | |
136 * HTTP cert query. Its address is supplied as a callback function to | |
137 * CERT_DecodeCertPackage; it is not expected to be called directly. | |
138 * | |
139 * Note that it does not conform to the libpkix API standard of returning | |
140 * a PKIX_Error*. It returns a SECStatus. | |
141 * | |
142 * PARAMETERS: | |
143 * "arg" | |
144 * The address of the callbackContext provided as a void* argument to | |
145 * CERT_DecodeCertPackage. Must be non-NULL. | |
146 * "secitemCerts" | |
147 * The address of the null-terminated array of SECItems. Must be non-NULL. | |
148 * "numcerts" | |
149 * The number of SECItems found in the signedData. Must be non-NULL. | |
150 * "plContext" | |
151 * Platform-specific context pointer. | |
152 * THREAD SAFETY: | |
153 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
154 * RETURNS: | |
155 * Returns SECSuccess if the function succeeds. | |
156 * Returns SECFailure if the function fails. | |
157 */ | |
158 static SECStatus | |
159 certCallback(void *arg, SECItem **secitemCerts, int numcerts) | |
160 { | |
161 callbackContext *cbContext; | |
162 PKIX_List *pkixCertList = NULL; | |
163 PKIX_Error *error = NULL; | |
164 void *plContext = NULL; | |
165 int itemNum = 0; | |
166 | |
167 if ((arg == NULL) || (secitemCerts == NULL)) { | |
168 return (SECFailure); | |
169 } | |
170 | |
171 cbContext = (callbackContext *)arg; | |
172 plContext = cbContext->plContext; | |
173 pkixCertList = cbContext->pkixCertList; | |
174 | |
175 for (; itemNum < numcerts; itemNum++ ) { | |
176 error = pkix_pl_Cert_CreateToList(secitemCerts[itemNum], | |
177 pkixCertList, plContext); | |
178 if (error != NULL) { | |
179 if (error->errClass == PKIX_FATAL_ERROR) { | |
180 cbContext->error = error; | |
181 return SECFailure; | |
182 } | |
183 /* reuse "error" since we could not destruct the old * | |
184 * value */ | |
185 error = PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, | |
186 plContext); | |
187 if (error) { | |
188 /* Treat decref failure as a fatal error. | |
189 * In this case will leak error, but can not do | |
190 * anything about it. */ | |
191 error->errClass = PKIX_FATAL_ERROR; | |
192 cbContext->error = error; | |
193 return SECFailure; | |
194 } | |
195 } | |
196 } | |
197 | |
198 return SECSuccess; | |
199 } | |
200 | |
201 | |
202 typedef SECStatus (*pkix_DecodeCertsFunc)(char *certbuf, int certlen, | |
203 CERTImportCertificateFunc f, void *arg
); | |
204 #ifdef NSS_STATIC | |
205 extern SECStatus CERT_DecodeCertPackage(char* certbuf, int certlen, | |
206 CERTImportCertificateFunc f, void* arg); | |
207 #endif | |
208 | |
209 struct pkix_DecodeFuncStr { | |
210 pkix_DecodeCertsFunc func; /* function pointer to the | |
211 * CERT_DecodeCertPackage function */ | |
212 PRLibrary *smimeLib; /* Pointer to the smime shared lib*/ | |
213 PRCallOnceType once; | |
214 }; | |
215 | |
216 static struct pkix_DecodeFuncStr pkix_decodeFunc; | |
217 static const PRCallOnceType pkix_pristine; | |
218 | |
219 #define SMIME_LIB_NAME SHLIB_PREFIX"smime3."SHLIB_SUFFIX | |
220 | |
221 /* | |
222 * load the smime library and look up the SEC_ReadPKCS7Certs function. | |
223 * we do this so we don't have a circular depenency on the smime library, | |
224 * and also so we don't have to load the smime library in applications that | |
225 * don't use it. | |
226 */ | |
227 static PRStatus PR_CALLBACK pkix_getDecodeFunction(void) | |
228 { | |
229 #ifdef NSS_STATIC | |
230 pkix_decodeFunc.smimeLib = NULL; | |
231 pkix_decodeFunc.func = CERT_DecodeCertPackage; | |
232 return PR_SUCCESS; | |
233 #else | |
234 pkix_decodeFunc.smimeLib = | |
235 PR_LoadLibrary(SHLIB_PREFIX"smime3."SHLIB_SUFFIX); | |
236 if (pkix_decodeFunc.smimeLib == NULL) { | |
237 return PR_FAILURE; | |
238 } | |
239 | |
240 pkix_decodeFunc.func = (pkix_DecodeCertsFunc) PR_FindFunctionSymbol( | |
241 pkix_decodeFunc.smimeLib, "CERT_DecodeCertPackage"); | |
242 if (!pkix_decodeFunc.func) { | |
243 return PR_FAILURE; | |
244 } | |
245 return PR_SUCCESS; | |
246 #endif | |
247 } | |
248 | |
249 /* | |
250 * clears our global state on shutdown. | |
251 */ | |
252 void | |
253 pkix_pl_HttpCertStore_Shutdown(void *plContext) | |
254 { | |
255 if (pkix_decodeFunc.smimeLib) { | |
256 PR_UnloadLibrary(pkix_decodeFunc.smimeLib); | |
257 pkix_decodeFunc.smimeLib = NULL; | |
258 } | |
259 /* the function pointer just need to be cleared, not freed */ | |
260 pkix_decodeFunc.func = NULL; | |
261 pkix_decodeFunc.once = pkix_pristine; | |
262 } | |
263 | |
264 /* | |
265 * This function is based on CERT_DecodeCertPackage from lib/pkcs7/certread.c | |
266 * read an old style ascii or binary certificate chain | |
267 */ | |
268 PKIX_Error * | |
269 pkix_pl_HttpCertStore_DecodeCertPackage | |
270 (const char *certbuf, | |
271 int certlen, | |
272 CERTImportCertificateFunc f, | |
273 void *arg, | |
274 void *plContext) | |
275 { | |
276 | |
277 PRStatus status; | |
278 SECStatus rv; | |
279 | |
280 PKIX_ENTER | |
281 (HTTPCERTSTORECONTEXT, | |
282 "pkix_pl_HttpCertStore_DecodeCertPackage"); | |
283 PKIX_NULLCHECK_TWO(certbuf, f); | |
284 | |
285 status = PR_CallOnce(&pkix_decodeFunc.once, pkix_getDecodeFunction); | |
286 | |
287 if (status != PR_SUCCESS) { | |
288 PKIX_ERROR(PKIX_CANTLOADLIBSMIME); | |
289 } | |
290 | |
291 /* paranoia, shouldn't happen if status == PR_SUCCESS); */ | |
292 if (!pkix_decodeFunc.func) { | |
293 PKIX_ERROR(PKIX_CANTLOADLIBSMIME); | |
294 } | |
295 | |
296 rv = (*pkix_decodeFunc.func)((char*)certbuf, certlen, f, arg); | |
297 | |
298 if (rv != SECSuccess) { | |
299 PKIX_ERROR (PKIX_SECREADPKCS7CERTSFAILED); | |
300 } | |
301 | |
302 | |
303 cleanup: | |
304 | |
305 PKIX_RETURN(HTTPCERTSTORECONTEXT); | |
306 } | |
307 | |
308 | |
309 /* | |
310 * FUNCTION: pkix_pl_HttpCertStore_ProcessCertResponse | |
311 * DESCRIPTION: | |
312 * | |
313 * This function verifies that the response code pointed to by "responseCode" | |
314 * and the content type pointed to by "responseContentType" are as expected, | |
315 * and then decodes the data pointed to by "responseData", of length | |
316 * "responseDataLen", into a List of Certs, possibly empty, which is returned | |
317 * at "pCertList". | |
318 * | |
319 * PARAMETERS: | |
320 * "responseCode" | |
321 * The value of the HTTP response code. | |
322 * "responseContentType" | |
323 * The address of the Content-type string. Must be non-NULL. | |
324 * "responseData" | |
325 * The address of the message data. Must be non-NULL. | |
326 * "responseDataLen" | |
327 * The length of the message data. | |
328 * "pCertList" | |
329 * The address of the List that is created. Must be non-NULL. | |
330 * "plContext" | |
331 * Platform-specific context pointer. | |
332 * THREAD SAFETY: | |
333 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
334 * RETURNS: | |
335 * Returns NULL if the function succeeds. | |
336 * Returns a HttpCertStore Error if the function fails in a non-fatal way. | |
337 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
338 */ | |
339 PKIX_Error * | |
340 pkix_pl_HttpCertStore_ProcessCertResponse( | |
341 PRUint16 responseCode, | |
342 const char *responseContentType, | |
343 const char *responseData, | |
344 PRUint32 responseDataLen, | |
345 PKIX_List **pCertList, | |
346 void *plContext) | |
347 { | |
348 callbackContext cbContext; | |
349 | |
350 PKIX_ENTER(HTTPCERTSTORECONTEXT, | |
351 "pkix_pl_HttpCertStore_ProcessCertResponse"); | |
352 | |
353 cbContext.error = NULL; | |
354 cbContext.plContext = plContext; | |
355 cbContext.pkixCertList = NULL; | |
356 | |
357 PKIX_NULLCHECK_ONE(pCertList); | |
358 | |
359 if (responseCode != 200) { | |
360 PKIX_ERROR(PKIX_BADHTTPRESPONSE); | |
361 } | |
362 | |
363 /* check that response type is application/pkcs7-mime */ | |
364 if (responseContentType == NULL) { | |
365 PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE); | |
366 } | |
367 | |
368 if (responseData == NULL) { | |
369 PKIX_ERROR(PKIX_NORESPONSEDATAINHTTPRESPONSE); | |
370 } | |
371 | |
372 PKIX_CHECK( | |
373 PKIX_List_Create(&cbContext.pkixCertList, plContext), | |
374 PKIX_LISTCREATEFAILED); | |
375 | |
376 PKIX_CHECK_ONLY_FATAL( | |
377 pkix_pl_HttpCertStore_DecodeCertPackage(responseData, | |
378 responseDataLen, | |
379 certCallback, | |
380 &cbContext, | |
381 plContext), | |
382 PKIX_HTTPCERTSTOREDECODECERTPACKAGEFAILED); | |
383 if (cbContext.error) { | |
384 /* Aborting on a fatal error(See certCallback fn) */ | |
385 pkixErrorResult = cbContext.error; | |
386 goto cleanup; | |
387 } | |
388 | |
389 *pCertList = cbContext.pkixCertList; | |
390 cbContext.pkixCertList = NULL; | |
391 | |
392 cleanup: | |
393 | |
394 PKIX_DECREF(cbContext.pkixCertList); | |
395 | |
396 PKIX_RETURN(HTTPCERTSTORECONTEXT); | |
397 } | |
398 | |
399 /* | |
400 * FUNCTION: pkix_pl_HttpCertStore_ProcessCrlResponse | |
401 * DESCRIPTION: | |
402 * | |
403 * This function verifies that the response code pointed to by "responseCode" | |
404 * and the content type pointed to by "responseContentType" are as expected, | |
405 * and then decodes the data pointed to by "responseData", of length | |
406 * "responseDataLen", into a List of Crls, possibly empty, which is returned | |
407 * at "pCrlList". | |
408 * | |
409 * PARAMETERS: | |
410 * "responseCode" | |
411 * The value of the HTTP response code. | |
412 * "responseContentType" | |
413 * The address of the Content-type string. Must be non-NULL. | |
414 * "responseData" | |
415 * The address of the message data. Must be non-NULL. | |
416 * "responseDataLen" | |
417 * The length of the message data. | |
418 * "pCrlList" | |
419 * The address of the List that is created. Must be non-NULL. | |
420 * "plContext" | |
421 * Platform-specific context pointer. | |
422 * THREAD SAFETY: | |
423 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
424 * RETURNS: | |
425 * Returns NULL if the function succeeds. | |
426 * Returns a HttpCertStore Error if the function fails in a non-fatal way. | |
427 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
428 */ | |
429 PKIX_Error * | |
430 pkix_pl_HttpCertStore_ProcessCrlResponse( | |
431 PRUint16 responseCode, | |
432 const char *responseContentType, | |
433 const char *responseData, | |
434 PRUint32 responseDataLen, | |
435 PKIX_List **pCrlList, | |
436 void *plContext) | |
437 { | |
438 SECItem encodedResponse; | |
439 PRInt16 compareVal = 0; | |
440 PKIX_List *crls = NULL; | |
441 SECItem *derCrlCopy = NULL; | |
442 CERTSignedCrl *nssCrl = NULL; | |
443 PKIX_PL_CRL *crl = NULL; | |
444 | |
445 PKIX_ENTER(HTTPCERTSTORECONTEXT, | |
446 "pkix_pl_HttpCertStore_ProcessCrlResponse"); | |
447 PKIX_NULLCHECK_ONE(pCrlList); | |
448 | |
449 if (responseCode != 200) { | |
450 PKIX_ERROR(PKIX_BADHTTPRESPONSE); | |
451 } | |
452 | |
453 /* check that response type is application/pkix-crl */ | |
454 if (responseContentType == NULL) { | |
455 PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE); | |
456 } | |
457 | |
458 compareVal = PORT_Strcasecmp(responseContentType, | |
459 "application/pkix-crl"); | |
460 if (compareVal != 0) { | |
461 PKIX_ERROR(PKIX_CONTENTTYPENOTPKIXCRL); | |
462 } | |
463 encodedResponse.type = siBuffer; | |
464 encodedResponse.data = (void*)responseData; | |
465 encodedResponse.len = responseDataLen; | |
466 | |
467 derCrlCopy = SECITEM_DupItem(&encodedResponse); | |
468 if (!derCrlCopy) { | |
469 PKIX_ERROR(PKIX_ALLOCERROR); | |
470 } | |
471 /* crl will be based on derCrlCopy, but will not own the der. */ | |
472 nssCrl = | |
473 CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, SEC_CRL_TYPE, | |
474 CRL_DECODE_DONT_COPY_DER | | |
475 CRL_DECODE_SKIP_ENTRIES); | |
476 if (!nssCrl) { | |
477 PKIX_ERROR(PKIX_FAILEDTODECODECRL); | |
478 } | |
479 /* pkix crls own the der. */ | |
480 PKIX_CHECK( | |
481 pkix_pl_CRL_CreateWithSignedCRL(nssCrl, derCrlCopy, NULL, | |
482 &crl, plContext), | |
483 PKIX_CRLCREATEWITHSIGNEDCRLFAILED); | |
484 /* Left control over memory pointed by derCrlCopy and | |
485 * nssCrl to pkix crl. */ | |
486 derCrlCopy = NULL; | |
487 nssCrl = NULL; | |
488 PKIX_CHECK(PKIX_List_Create(&crls, plContext), | |
489 PKIX_LISTCREATEFAILED); | |
490 PKIX_CHECK(PKIX_List_AppendItem | |
491 (crls, (PKIX_PL_Object *) crl, plContext), | |
492 PKIX_LISTAPPENDITEMFAILED); | |
493 *pCrlList = crls; | |
494 crls = NULL; | |
495 cleanup: | |
496 if (derCrlCopy) { | |
497 SECITEM_FreeItem(derCrlCopy, PR_TRUE); | |
498 } | |
499 if (nssCrl) { | |
500 SEC_DestroyCrl(nssCrl); | |
501 } | |
502 PKIX_DECREF(crl); | |
503 PKIX_DECREF(crls); | |
504 | |
505 PKIX_RETURN(HTTPCERTSTORECONTEXT); | |
506 } | |
507 | |
508 /* | |
509 * FUNCTION: pkix_pl_HttpCertStore_CreateRequestSession | |
510 * DESCRIPTION: | |
511 * | |
512 * This function takes elements from the HttpCertStoreContext pointed to by | |
513 * "context" (path, client, and serverSession) and creates a RequestSession. | |
514 * See the HTTPClient API described in ocspt.h for further details. | |
515 * | |
516 * PARAMETERS: | |
517 * "context" | |
518 * The address of the HttpCertStoreContext. Must be non-NULL. | |
519 * "plContext" | |
520 * Platform-specific context pointer. | |
521 * THREAD SAFETY: | |
522 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
523 * RETURNS: | |
524 * Returns NULL if the function succeeds. | |
525 * Returns a HttpCertStore Error if the function fails in a non-fatal way. | |
526 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
527 */ | |
528 PKIX_Error * | |
529 pkix_pl_HttpCertStore_CreateRequestSession( | |
530 PKIX_PL_HttpCertStoreContext *context, | |
531 void *plContext) | |
532 { | |
533 const SEC_HttpClientFcnV1 *hcv1 = NULL; | |
534 SECStatus rv = SECFailure; | |
535 | |
536 PKIX_ENTER | |
537 (HTTPCERTSTORECONTEXT, | |
538 "pkix_pl_HttpCertStore_CreateRequestSession"); | |
539 PKIX_NULLCHECK_TWO(context, context->serverSession); | |
540 | |
541 if (context->client->version != 1) { | |
542 PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); | |
543 } | |
544 | |
545 hcv1 = &(context->client->fcnTable.ftable1); | |
546 if (context->requestSession != NULL) { | |
547 (*hcv1->freeFcn)(context->requestSession); | |
548 context->requestSession = 0; | |
549 } | |
550 | |
551 rv = (*hcv1->createFcn)(context->serverSession, "http", | |
552 context->path, "GET", | |
553 PR_SecondsToInterval( | |
554 ((PKIX_PL_NssContext*)plContext)->timeoutSeconds), | |
555 &(context->requestSession)); | |
556 | |
557 if (rv != SECSuccess) { | |
558 PKIX_ERROR(PKIX_HTTPSERVERERROR); | |
559 } | |
560 cleanup: | |
561 | |
562 PKIX_RETURN(HTTPCERTSTORECONTEXT); | |
563 | |
564 } | |
565 | |
566 /* | |
567 * FUNCTION: pkix_pl_HttpCertStore_GetCert | |
568 * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) | |
569 */ | |
570 PKIX_Error * | |
571 pkix_pl_HttpCertStore_GetCert( | |
572 PKIX_CertStore *store, | |
573 PKIX_CertSelector *selector, | |
574 PKIX_VerifyNode *verifyNode, | |
575 void **pNBIOContext, | |
576 PKIX_List **pCertList, | |
577 void *plContext) | |
578 { | |
579 const SEC_HttpClientFcnV1 *hcv1 = NULL; | |
580 PKIX_PL_HttpCertStoreContext *context = NULL; | |
581 void *nbioContext = NULL; | |
582 SECStatus rv = SECFailure; | |
583 PRUint16 responseCode = 0; | |
584 const char *responseContentType = NULL; | |
585 const char *responseData = NULL; | |
586 PRUint32 responseDataLen = 0; | |
587 PKIX_List *certList = NULL; | |
588 | |
589 PKIX_ENTER(HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStore_GetCert"); | |
590 PKIX_NULLCHECK_THREE(store, selector, pCertList); | |
591 | |
592 nbioContext = *pNBIOContext; | |
593 *pNBIOContext = NULL; | |
594 | |
595 PKIX_CHECK(PKIX_CertStore_GetCertStoreContext | |
596 (store, (PKIX_PL_Object **)&context, plContext), | |
597 PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); | |
598 | |
599 if (context->client->version != 1) { | |
600 PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); | |
601 } | |
602 | |
603 hcv1 = &(context->client->fcnTable.ftable1); | |
604 | |
605 PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession | |
606 (context, plContext), | |
607 PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED); | |
608 | |
609 responseDataLen = | |
610 ((PKIX_PL_NssContext*)plContext)->maxResponseLength; | |
611 | |
612 rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession, | |
613 (PRPollDesc **)&nbioContext, | |
614 &responseCode, | |
615 (const char **)&responseContentType, | |
616 NULL, /* &responseHeaders */ | |
617 (const char **)&responseData, | |
618 &responseDataLen); | |
619 if (rv != SECSuccess) { | |
620 PKIX_ERROR(PKIX_HTTPSERVERERROR); | |
621 } | |
622 | |
623 if (nbioContext != 0) { | |
624 *pNBIOContext = nbioContext; | |
625 goto cleanup; | |
626 } | |
627 | |
628 PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse | |
629 (responseCode, | |
630 responseContentType, | |
631 responseData, | |
632 responseDataLen, | |
633 &certList, | |
634 plContext), | |
635 PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED); | |
636 | |
637 *pCertList = certList; | |
638 | |
639 cleanup: | |
640 PKIX_DECREF(context); | |
641 | |
642 PKIX_RETURN(CERTSTORE); | |
643 } | |
644 | |
645 /* | |
646 * FUNCTION: pkix_pl_HttpCertStore_GetCertContinue | |
647 * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) | |
648 */ | |
649 PKIX_Error * | |
650 pkix_pl_HttpCertStore_GetCertContinue( | |
651 PKIX_CertStore *store, | |
652 PKIX_CertSelector *selector, | |
653 PKIX_VerifyNode *verifyNode, | |
654 void **pNBIOContext, | |
655 PKIX_List **pCertList, | |
656 void *plContext) | |
657 { | |
658 const SEC_HttpClientFcnV1 *hcv1 = NULL; | |
659 PKIX_PL_HttpCertStoreContext *context = NULL; | |
660 void *nbioContext = NULL; | |
661 SECStatus rv = SECFailure; | |
662 PRUint16 responseCode = 0; | |
663 const char *responseContentType = NULL; | |
664 const char *responseData = NULL; | |
665 PRUint32 responseDataLen = 0; | |
666 PKIX_List *certList = NULL; | |
667 | |
668 PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCertContinue"); | |
669 PKIX_NULLCHECK_THREE(store, selector, pCertList); | |
670 | |
671 nbioContext = *pNBIOContext; | |
672 *pNBIOContext = NULL; | |
673 | |
674 PKIX_CHECK(PKIX_CertStore_GetCertStoreContext | |
675 (store, (PKIX_PL_Object **)&context, plContext), | |
676 PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); | |
677 | |
678 if (context->client->version != 1) { | |
679 PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); | |
680 } | |
681 | |
682 hcv1 = &(context->client->fcnTable.ftable1); | |
683 PKIX_NULLCHECK_ONE(context->requestSession); | |
684 | |
685 responseDataLen = | |
686 ((PKIX_PL_NssContext*)plContext)->maxResponseLength; | |
687 | |
688 rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession, | |
689 (PRPollDesc **)&nbioContext, | |
690 &responseCode, | |
691 (const char **)&responseContentType, | |
692 NULL, /* &responseHeaders */ | |
693 (const char **)&responseData, | |
694 &responseDataLen); | |
695 | |
696 if (rv != SECSuccess) { | |
697 PKIX_ERROR(PKIX_HTTPSERVERERROR); | |
698 } | |
699 | |
700 if (nbioContext != 0) { | |
701 *pNBIOContext = nbioContext; | |
702 goto cleanup; | |
703 } | |
704 | |
705 PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse | |
706 (responseCode, | |
707 responseContentType, | |
708 responseData, | |
709 responseDataLen, | |
710 &certList, | |
711 plContext), | |
712 PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED); | |
713 | |
714 *pCertList = certList; | |
715 | |
716 cleanup: | |
717 PKIX_DECREF(context); | |
718 | |
719 PKIX_RETURN(CERTSTORE); | |
720 } | |
721 | |
722 /* | |
723 * FUNCTION: pkix_pl_HttpCertStore_GetCRL | |
724 * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h) | |
725 */ | |
726 PKIX_Error * | |
727 pkix_pl_HttpCertStore_GetCRL( | |
728 PKIX_CertStore *store, | |
729 PKIX_CRLSelector *selector, | |
730 void **pNBIOContext, | |
731 PKIX_List **pCrlList, | |
732 void *plContext) | |
733 { | |
734 | |
735 const SEC_HttpClientFcnV1 *hcv1 = NULL; | |
736 PKIX_PL_HttpCertStoreContext *context = NULL; | |
737 void *nbioContext = NULL; | |
738 SECStatus rv = SECFailure; | |
739 PRUint16 responseCode = 0; | |
740 const char *responseContentType = NULL; | |
741 const char *responseData = NULL; | |
742 PRUint32 responseDataLen = 0; | |
743 PKIX_List *crlList = NULL; | |
744 | |
745 PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCRL"); | |
746 PKIX_NULLCHECK_THREE(store, selector, pCrlList); | |
747 | |
748 nbioContext = *pNBIOContext; | |
749 *pNBIOContext = NULL; | |
750 | |
751 PKIX_CHECK(PKIX_CertStore_GetCertStoreContext | |
752 (store, (PKIX_PL_Object **)&context, plContext), | |
753 PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); | |
754 | |
755 if (context->client->version != 1) { | |
756 PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); | |
757 } | |
758 | |
759 hcv1 = &(context->client->fcnTable.ftable1); | |
760 PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession | |
761 (context, plContext), | |
762 PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED); | |
763 | |
764 responseDataLen = | |
765 ((PKIX_PL_NssContext*)plContext)->maxResponseLength; | |
766 | |
767 rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession, | |
768 (PRPollDesc **)&nbioContext, | |
769 &responseCode, | |
770 (const char **)&responseContentType, | |
771 NULL, /* &responseHeaders */ | |
772 (const char **)&responseData, | |
773 &responseDataLen); | |
774 | |
775 if (rv != SECSuccess) { | |
776 PKIX_ERROR(PKIX_HTTPSERVERERROR); | |
777 } | |
778 | |
779 if (nbioContext != 0) { | |
780 *pNBIOContext = nbioContext; | |
781 goto cleanup; | |
782 } | |
783 | |
784 PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCrlResponse | |
785 (responseCode, | |
786 responseContentType, | |
787 responseData, | |
788 responseDataLen, | |
789 &crlList, | |
790 plContext), | |
791 PKIX_HTTPCERTSTOREPROCESSCRLRESPONSEFAILED); | |
792 | |
793 *pCrlList = crlList; | |
794 | |
795 cleanup: | |
796 PKIX_DECREF(context); | |
797 | |
798 PKIX_RETURN(CERTSTORE); | |
799 } | |
800 | |
801 /* | |
802 * FUNCTION: pkix_pl_HttpCertStore_GetCRLContinue | |
803 * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h) | |
804 */ | |
805 PKIX_Error * | |
806 pkix_pl_HttpCertStore_GetCRLContinue( | |
807 PKIX_CertStore *store, | |
808 PKIX_CRLSelector *selector, | |
809 void **pNBIOContext, | |
810 PKIX_List **pCrlList, | |
811 void *plContext) | |
812 { | |
813 const SEC_HttpClientFcnV1 *hcv1 = NULL; | |
814 PKIX_PL_HttpCertStoreContext *context = NULL; | |
815 void *nbioContext = NULL; | |
816 SECStatus rv = SECFailure; | |
817 PRUint16 responseCode = 0; | |
818 const char *responseContentType = NULL; | |
819 const char *responseData = NULL; | |
820 PRUint32 responseDataLen = 0; | |
821 PKIX_List *crlList = NULL; | |
822 | |
823 PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCRLContinue"); | |
824 PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList); | |
825 | |
826 nbioContext = *pNBIOContext; | |
827 *pNBIOContext = NULL; | |
828 | |
829 PKIX_CHECK(PKIX_CertStore_GetCertStoreContext | |
830 (store, (PKIX_PL_Object **)&context, plContext), | |
831 PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); | |
832 | |
833 if (context->client->version != 1) { | |
834 PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); | |
835 } | |
836 hcv1 = &(context->client->fcnTable.ftable1); | |
837 | |
838 PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession | |
839 (context, plContext), | |
840 PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED); | |
841 | |
842 responseDataLen = | |
843 ((PKIX_PL_NssContext*)plContext)->maxResponseLength; | |
844 | |
845 rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession, | |
846 (PRPollDesc **)&nbioContext, | |
847 &responseCode, | |
848 (const char **)&responseContentType, | |
849 NULL, /* &responseHeaders */ | |
850 (const char **)&responseData, | |
851 &responseDataLen); | |
852 | |
853 if (rv != SECSuccess) { | |
854 PKIX_ERROR(PKIX_HTTPSERVERERROR); | |
855 } | |
856 | |
857 if (nbioContext != 0) { | |
858 *pNBIOContext = nbioContext; | |
859 goto cleanup; | |
860 } | |
861 | |
862 PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCrlResponse | |
863 (responseCode, | |
864 responseContentType, | |
865 responseData, | |
866 responseDataLen, | |
867 &crlList, | |
868 plContext), | |
869 PKIX_HTTPCERTSTOREPROCESSCRLRESPONSEFAILED); | |
870 | |
871 *pCrlList = crlList; | |
872 | |
873 cleanup: | |
874 PKIX_DECREF(context); | |
875 | |
876 PKIX_RETURN(CERTSTORE); | |
877 } | |
878 | |
879 /* --Public-HttpCertStore-Functions----------------------------------- */ | |
880 | |
881 /* | |
882 * FUNCTION: pkix_pl_HttpCertStore_CreateWithAsciiName | |
883 * DESCRIPTION: | |
884 * | |
885 * This function uses the HttpClient pointed to by "client" and the string | |
886 * (hostname:portnum/path, with portnum optional) pointed to by "locationAscii" | |
887 * to create an HttpCertStore connected to the desired location, storing the | |
888 * created CertStore at "pCertStore". | |
889 * | |
890 * PARAMETERS: | |
891 * "client" | |
892 * The address of the HttpClient. Must be non-NULL. | |
893 * "locationAscii" | |
894 * The address of the character string indicating the hostname, port, and | |
895 * path to be queried for Certs or Crls. Must be non-NULL. | |
896 * "pCertStore" | |
897 * The address in which the object is stored. Must be non-NULL. | |
898 * "plContext" | |
899 * Platform-specific context pointer. | |
900 * THREAD SAFETY: | |
901 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
902 * RETURNS: | |
903 * Returns NULL if the function succeeds. | |
904 * Returns a HttpCertStore Error if the function fails in a non-fatal way. | |
905 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
906 */ | |
907 PKIX_Error * | |
908 pkix_pl_HttpCertStore_CreateWithAsciiName( | |
909 PKIX_PL_HttpClient *client, | |
910 char *locationAscii, | |
911 PKIX_CertStore **pCertStore, | |
912 void *plContext) | |
913 { | |
914 const SEC_HttpClientFcn *clientFcn = NULL; | |
915 const SEC_HttpClientFcnV1 *hcv1 = NULL; | |
916 PKIX_PL_HttpCertStoreContext *httpCertStore = NULL; | |
917 PKIX_CertStore *certStore = NULL; | |
918 char *hostname = NULL; | |
919 char *path = NULL; | |
920 PRUint16 port = 0; | |
921 SECStatus rv = SECFailure; | |
922 | |
923 PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_CreateWithAsciiName"); | |
924 PKIX_NULLCHECK_TWO(locationAscii, pCertStore); | |
925 | |
926 if (client == NULL) { | |
927 clientFcn = SEC_GetRegisteredHttpClient(); | |
928 if (clientFcn == NULL) { | |
929 PKIX_ERROR(PKIX_NOREGISTEREDHTTPCLIENT); | |
930 } | |
931 } else { | |
932 clientFcn = (const SEC_HttpClientFcn *)client; | |
933 } | |
934 | |
935 if (clientFcn->version != 1) { | |
936 PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); | |
937 } | |
938 | |
939 /* create a PKIX_PL_HttpCertStore object */ | |
940 PKIX_CHECK(PKIX_PL_Object_Alloc | |
941 (PKIX_HTTPCERTSTORECONTEXT_TYPE, | |
942 sizeof (PKIX_PL_HttpCertStoreContext), | |
943 (PKIX_PL_Object **)&httpCertStore, | |
944 plContext), | |
945 PKIX_COULDNOTCREATEOBJECT); | |
946 | |
947 /* Initialize fields */ | |
948 httpCertStore->client = clientFcn; /* not a PKIX object! */ | |
949 | |
950 /* parse location -> hostname, port, path */ | |
951 rv = CERT_ParseURL(locationAscii, &hostname, &port, &path); | |
952 if (rv == SECFailure || hostname == NULL || path == NULL) { | |
953 PKIX_ERROR(PKIX_URLPARSINGFAILED); | |
954 } | |
955 | |
956 httpCertStore->path = path; | |
957 path = NULL; | |
958 | |
959 hcv1 = &(clientFcn->fcnTable.ftable1); | |
960 rv = (*hcv1->createSessionFcn)(hostname, port, | |
961 &(httpCertStore->serverSession)); | |
962 if (rv != SECSuccess) { | |
963 PKIX_ERROR(PKIX_HTTPCLIENTCREATESESSIONFAILED); | |
964 } | |
965 | |
966 httpCertStore->requestSession = NULL; | |
967 | |
968 PKIX_CHECK(PKIX_CertStore_Create | |
969 (pkix_pl_HttpCertStore_GetCert, | |
970 pkix_pl_HttpCertStore_GetCRL, | |
971 pkix_pl_HttpCertStore_GetCertContinue, | |
972 pkix_pl_HttpCertStore_GetCRLContinue, | |
973 NULL, /* don't support trust */ | |
974 NULL, /* can not store crls */ | |
975 NULL, /* can not do revocation check */ | |
976 (PKIX_PL_Object *)httpCertStore, | |
977 PKIX_TRUE, /* cache flag */ | |
978 PKIX_FALSE, /* not local */ | |
979 &certStore, | |
980 plContext), | |
981 PKIX_CERTSTORECREATEFAILED); | |
982 | |
983 *pCertStore = certStore; | |
984 certStore = NULL; | |
985 | |
986 cleanup: | |
987 PKIX_DECREF(httpCertStore); | |
988 if (hostname) { | |
989 PORT_Free(hostname); | |
990 } | |
991 if (path) { | |
992 PORT_Free(path); | |
993 } | |
994 | |
995 PKIX_RETURN(CERTSTORE); | |
996 } | |
997 | |
998 /* | |
999 * FUNCTION: PKIX_PL_HttpCertStore_Create | |
1000 * (see comments in pkix_samples_modules.h) | |
1001 */ | |
1002 PKIX_Error * | |
1003 PKIX_PL_HttpCertStore_Create( | |
1004 PKIX_PL_HttpClient *client, | |
1005 PKIX_PL_GeneralName *location, | |
1006 PKIX_CertStore **pCertStore, | |
1007 void *plContext) | |
1008 { | |
1009 PKIX_PL_String *locationString = NULL; | |
1010 char *locationAscii = NULL; | |
1011 PKIX_UInt32 len = 0; | |
1012 | |
1013 PKIX_ENTER(CERTSTORE, "PKIX_PL_HttpCertStore_Create"); | |
1014 PKIX_NULLCHECK_TWO(location, pCertStore); | |
1015 | |
1016 PKIX_TOSTRING(location, &locationString, plContext, | |
1017 PKIX_GENERALNAMETOSTRINGFAILED); | |
1018 | |
1019 PKIX_CHECK(PKIX_PL_String_GetEncoded | |
1020 (locationString, | |
1021 PKIX_ESCASCII, | |
1022 (void **)&locationAscii, | |
1023 &len, | |
1024 plContext), | |
1025 PKIX_STRINGGETENCODEDFAILED); | |
1026 | |
1027 PKIX_CHECK(pkix_pl_HttpCertStore_CreateWithAsciiName | |
1028 (client, locationAscii, pCertStore, plContext), | |
1029 PKIX_HTTPCERTSTORECREATEWITHASCIINAMEFAILED); | |
1030 | |
1031 cleanup: | |
1032 | |
1033 PKIX_DECREF(locationString); | |
1034 | |
1035 PKIX_RETURN(CERTSTORE); | |
1036 } | |
1037 | |
1038 /* | |
1039 * FUNCTION: pkix_HttpCertStore_FindSocketConnection | |
1040 * DESCRIPTION: | |
1041 * | |
1042 PRIntervalTime timeout, | |
1043 char *hostname, | |
1044 PRUint16 portnum, | |
1045 PRErrorCode *pStatus, | |
1046 PKIX_PL_Socket **pSocket, | |
1047 | |
1048 * This function checks for an existing socket, creating a new one if unable | |
1049 * to find an existing one, for the host pointed to by "hostname" and the port | |
1050 * pointed to by "portnum". If a new socket is created the PRIntervalTime in | |
1051 * "timeout" will be used for the timeout value and a creation status is | |
1052 * returned at "pStatus". The address of the socket is stored at "pSocket". | |
1053 * | |
1054 * PARAMETERS: | |
1055 * "timeout" | |
1056 * The PRIntervalTime of the timeout value. | |
1057 * "hostname" | |
1058 * The address of the string containing the hostname. Must be non-NULL. | |
1059 * "portnum" | |
1060 * The port number for the desired socket. | |
1061 * "pStatus" | |
1062 * The address at which the status is stored. Must be non-NULL. | |
1063 * "pSocket" | |
1064 * The address at which the socket is stored. Must be non-NULL. | |
1065 * "plContext" | |
1066 * Platform-specific context pointer. | |
1067 * THREAD SAFETY: | |
1068 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1069 * RETURNS: | |
1070 * Returns NULL if the function succeeds. | |
1071 * Returns a HttpCertStore Error if the function fails in a non-fatal way. | |
1072 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1073 */ | |
1074 PKIX_Error * | |
1075 pkix_HttpCertStore_FindSocketConnection( | |
1076 PRIntervalTime timeout, | |
1077 char *hostname, | |
1078 PRUint16 portnum, | |
1079 PRErrorCode *pStatus, | |
1080 PKIX_PL_Socket **pSocket, | |
1081 void *plContext) | |
1082 { | |
1083 PKIX_PL_String *formatString = NULL; | |
1084 PKIX_PL_String *hostString = NULL; | |
1085 PKIX_PL_String *domainString = NULL; | |
1086 PKIX_PL_Socket *socket = NULL; | |
1087 | |
1088 PKIX_ENTER(CERTSTORE, "pkix_HttpCertStore_FindSocketConnection"); | |
1089 PKIX_NULLCHECK_THREE(hostname, pStatus, pSocket); | |
1090 | |
1091 *pStatus = 0; | |
1092 | |
1093 /* create PKIX_PL_String from hostname and port */ | |
1094 PKIX_CHECK(PKIX_PL_String_Create | |
1095 (PKIX_ESCASCII, "%s:%d", 0, &formatString, plContext), | |
1096 PKIX_STRINGCREATEFAILED); | |
1097 | |
1098 #if 0 | |
1099 hostname = "variation.red.iplanet.com"; | |
1100 portnum = 2001; | |
1101 #endif | |
1102 | |
1103 PKIX_CHECK(PKIX_PL_String_Create | |
1104 (PKIX_ESCASCII, hostname, 0, &hostString, plContext), | |
1105 PKIX_STRINGCREATEFAILED); | |
1106 | |
1107 PKIX_CHECK(PKIX_PL_Sprintf | |
1108 (&domainString, plContext, formatString, hostString, portnum), | |
1109 PKIX_STRINGCREATEFAILED); | |
1110 | |
1111 #ifdef PKIX_SOCKETCACHE | |
1112 /* Is this domainName already in cache? */ | |
1113 PKIX_CHECK(PKIX_PL_HashTable_Lookup | |
1114 (httpSocketCache, | |
1115 (PKIX_PL_Object *)domainString, | |
1116 (PKIX_PL_Object **)&socket, | |
1117 plContext), | |
1118 PKIX_HASHTABLELOOKUPFAILED); | |
1119 #endif | |
1120 if (socket == NULL) { | |
1121 | |
1122 /* No, create a connection (and cache it) */ | |
1123 PKIX_CHECK(pkix_pl_Socket_CreateByHostAndPort | |
1124 (PKIX_FALSE, /* create a client, not a server */ | |
1125 timeout, | |
1126 hostname, | |
1127 portnum, | |
1128 pStatus, | |
1129 &socket, | |
1130 plContext), | |
1131 PKIX_SOCKETCREATEBYHOSTANDPORTFAILED); | |
1132 | |
1133 #ifdef PKIX_SOCKETCACHE | |
1134 PKIX_CHECK(PKIX_PL_HashTable_Add | |
1135 (httpSocketCache, | |
1136 (PKIX_PL_Object *)domainString, | |
1137 (PKIX_PL_Object *)socket, | |
1138 plContext), | |
1139 PKIX_HASHTABLEADDFAILED); | |
1140 #endif | |
1141 } | |
1142 | |
1143 *pSocket = socket; | |
1144 socket = NULL; | |
1145 | |
1146 cleanup: | |
1147 | |
1148 PKIX_DECREF(formatString); | |
1149 PKIX_DECREF(hostString); | |
1150 PKIX_DECREF(domainString); | |
1151 PKIX_DECREF(socket); | |
1152 | |
1153 PKIX_RETURN(CERTSTORE); | |
1154 } | |
1155 | |
OLD | NEW |