~ubuntu-branches/ubuntu/precise/nss/precise-security

« back to all changes in this revision

Viewing changes to nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2013-11-14 14:58:07 UTC
  • mfrom: (1.1.19)
  • Revision ID: package-import@ubuntu.com-20131114145807-ay302kimn72ovt88
Tags: 3.15.3-0ubuntu0.12.04.1
* SECURITY UPDATE: New upstream release to fix multiple security issues
  and add TLSv1.2 support.
  - CVE-2013-1739
  - CVE-2013-1741
  - CVE-2013-5605
  - CVE-2013-5606
* Adjusted packaging for 3.15.3:
  - debian/patches/*: refreshed.
  - debian/patches/lower-dhe-priority.patch: removed, no longer needed,
    was a workaround for an old version of firefox.
  - debian/libnss3.symbols: added new symbols.
  - debian/rules: updated for new source layout.

Show diffs side-by-side

added added

removed removed

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