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

« back to all changes in this revision

Viewing changes to nss/lib/libpkix/pkix/checker/pkix_ocspchecker.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_ocspchecker.c
 
6
 *
 
7
 * OcspChecker Object Functions
 
8
 *
 
9
 */
 
10
 
 
11
#include "pkix_ocspchecker.h"
 
12
#include "pkix_pl_ocspcertid.h"
 
13
#include "pkix_error.h"
 
14
 
 
15
 
 
16
/* --Private-Data-and-Types--------------------------------------- */
 
17
 
 
18
typedef struct pkix_OcspCheckerStruct {
 
19
    /* RevocationMethod is the super class of OcspChecker. */
 
20
    pkix_RevocationMethod method;
 
21
    PKIX_PL_VerifyCallback certVerifyFcn;
 
22
} pkix_OcspChecker;
 
23
 
 
24
/* --Private-Functions-------------------------------------------- */
 
25
 
 
26
/*
 
27
 * FUNCTION: pkix_OcspChecker_Destroy
 
28
 *      (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
 
29
 */
 
30
static PKIX_Error *
 
31
pkix_OcspChecker_Destroy(
 
32
        PKIX_PL_Object *object,
 
33
        void *plContext)
 
34
{
 
35
    return NULL;
 
36
}
 
37
 
 
38
/*
 
39
 * FUNCTION: pkix_OcspChecker_RegisterSelf
 
40
 * DESCRIPTION:
 
41
 *  Registers PKIX_OCSPCHECKER_TYPE and its related functions with
 
42
 *  systemClasses[]
 
43
 * THREAD SAFETY:
 
44
 *  Not Thread Safe - for performance and complexity reasons
 
45
 *
 
46
 *  Since this function is only called by PKIX_PL_Initialize, which should
 
47
 *  only be called once, it is acceptable that this function is not
 
48
 *  thread-safe.
 
49
 */
 
50
PKIX_Error *
 
51
pkix_OcspChecker_RegisterSelf(void *plContext)
 
52
{
 
53
        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
 
54
        pkix_ClassTable_Entry* entry = &systemClasses[PKIX_OCSPCHECKER_TYPE];
 
55
 
 
56
        PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_RegisterSelf");
 
57
 
 
58
        entry->description = "OcspChecker";
 
59
        entry->typeObjectSize = sizeof(pkix_OcspChecker);
 
60
        entry->destructor = pkix_OcspChecker_Destroy;
 
61
 
 
62
        PKIX_RETURN(OCSPCHECKER);
 
63
}
 
64
 
 
65
 
 
66
/*
 
67
 * FUNCTION: pkix_OcspChecker_Create
 
68
 */
 
69
PKIX_Error *
 
70
pkix_OcspChecker_Create(PKIX_RevocationMethodType methodType,
 
71
                        PKIX_UInt32 flags,
 
72
                        PKIX_UInt32 priority,
 
73
                        pkix_LocalRevocationCheckFn localRevChecker,
 
74
                        pkix_ExternalRevocationCheckFn externalRevChecker,
 
75
                        PKIX_PL_VerifyCallback verifyFn,
 
76
                        pkix_RevocationMethod **pChecker,
 
77
                        void *plContext)
 
78
{
 
79
        pkix_OcspChecker *method = NULL;
 
80
 
 
81
        PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_Create");
 
82
        PKIX_NULLCHECK_ONE(pChecker);
 
83
 
 
84
        PKIX_CHECK(PKIX_PL_Object_Alloc
 
85
                    (PKIX_OCSPCHECKER_TYPE,
 
86
                    sizeof (pkix_OcspChecker),
 
87
                    (PKIX_PL_Object **)&method,
 
88
                    plContext),
 
89
                    PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
 
90
 
 
91
        pkixErrorResult = pkix_RevocationMethod_Init(
 
92
            (pkix_RevocationMethod*)method, methodType, flags,  priority,
 
93
            localRevChecker, externalRevChecker, plContext);
 
94
        if (pkixErrorResult) {
 
95
            goto cleanup;
 
96
        }
 
97
        method->certVerifyFcn = (PKIX_PL_VerifyCallback)verifyFn;
 
98
 
 
99
        *pChecker = (pkix_RevocationMethod*)method;
 
100
        method = NULL;
 
101
 
 
102
cleanup:
 
103
        PKIX_DECREF(method);
 
104
 
 
105
        PKIX_RETURN(OCSPCHECKER);
 
106
}
 
107
 
 
108
/*
 
109
 * FUNCTION: pkix_OcspChecker_MapResultCodeToRevStatus
 
110
 */
 
111
PKIX_RevocationStatus
 
112
pkix_OcspChecker_MapResultCodeToRevStatus(SECErrorCodes resultCode)
 
113
{
 
114
        switch (resultCode) {
 
115
            case SEC_ERROR_REVOKED_CERTIFICATE:
 
116
                return PKIX_RevStatus_Revoked;
 
117
            default:
 
118
                return PKIX_RevStatus_NoInfo;
 
119
        }
 
120
}
 
121
 
 
122
/* --Public-Functions--------------------------------------------- */
 
123
 
 
124
/*
 
125
 * FUNCTION: pkix_OcspChecker_Check (see comments in pkix_checker.h)
 
126
 */
 
127
 
 
128
/*
 
129
 * The OCSPChecker is created in an idle state, and remains in this state until
 
130
 * either (a) the default Responder has been set and enabled, and a Check
 
131
 * request is received with no responder specified, or (b) a Check request is
 
132
 * received with a specified responder. A request message is constructed and
 
133
 * given to the HttpClient. If non-blocking I/O is used the client may return
 
134
 * with WOULDBLOCK, in which case the OCSPChecker returns the WOULDBLOCK
 
135
 * condition to its caller in turn. On a subsequent call the I/O is resumed.
 
136
 * When a response is received it is decoded and the results provided to the
 
137
 * caller.
 
138
 *
 
139
 */
 
140
PKIX_Error *
 
141
pkix_OcspChecker_CheckLocal(
 
142
        PKIX_PL_Cert *cert,
 
143
        PKIX_PL_Cert *issuer,
 
144
        PKIX_PL_Date *date,
 
145
        pkix_RevocationMethod *checkerObject,
 
146
        PKIX_ProcessingParams *procParams,
 
147
        PKIX_UInt32 methodFlags,
 
148
        PKIX_Boolean chainVerificationState,
 
149
        PKIX_RevocationStatus *pRevStatus,
 
150
        PKIX_UInt32 *pReasonCode,
 
151
        void *plContext)
 
152
{
 
153
        PKIX_PL_OcspCertID    *cid = NULL;
 
154
        PKIX_Boolean           hasFreshStatus = PKIX_FALSE;
 
155
        PKIX_Boolean           statusIsGood = PKIX_FALSE;
 
156
        SECErrorCodes          resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
 
157
        PKIX_RevocationStatus  revStatus = PKIX_RevStatus_NoInfo;
 
158
 
 
159
        PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckLocal");
 
160
 
 
161
        PKIX_CHECK(
 
162
            PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
 
163
                                      plContext),
 
164
            PKIX_OCSPCERTIDCREATEFAILED);
 
165
        if (!cid) {
 
166
            goto cleanup;
 
167
        }
 
168
 
 
169
        PKIX_CHECK(
 
170
            PKIX_PL_OcspCertID_GetFreshCacheStatus(cid, date,
 
171
                                                   &hasFreshStatus,
 
172
                                                   &statusIsGood,
 
173
                                                   &resultCode,
 
174
                                                   plContext),
 
175
            PKIX_OCSPCERTIDGETFRESHCACHESTATUSFAILED);
 
176
        if (hasFreshStatus) {
 
177
            if (statusIsGood) {
 
178
                revStatus = PKIX_RevStatus_Success;
 
179
                resultCode = 0;
 
180
            } else {
 
181
                revStatus = pkix_OcspChecker_MapResultCodeToRevStatus(resultCode);
 
182
            }
 
183
        }
 
184
 
 
185
cleanup:
 
186
        *pRevStatus = revStatus;
 
187
 
 
188
        /* ocsp carries only tree statuses: good, bad, and unknown.
 
189
         * revStatus is used to pass them. reasonCode is always set
 
190
         * to be unknown. */
 
191
        *pReasonCode = crlEntryReasonUnspecified;
 
192
        PKIX_DECREF(cid);
 
193
 
 
194
        PKIX_RETURN(OCSPCHECKER);
 
195
}
 
196
 
 
197
 
 
198
/*
 
199
 * The OCSPChecker is created in an idle state, and remains in this state until
 
200
 * either (a) the default Responder has been set and enabled, and a Check
 
201
 * request is received with no responder specified, or (b) a Check request is
 
202
 * received with a specified responder. A request message is constructed and
 
203
 * given to the HttpClient. If non-blocking I/O is used the client may return
 
204
 * with WOULDBLOCK, in which case the OCSPChecker returns the WOULDBLOCK
 
205
 * condition to its caller in turn. On a subsequent call the I/O is resumed.
 
206
 * When a response is received it is decoded and the results provided to the
 
207
 * caller.
 
208
 *
 
209
 */
 
210
PKIX_Error *
 
211
pkix_OcspChecker_CheckExternal(
 
212
        PKIX_PL_Cert *cert,
 
213
        PKIX_PL_Cert *issuer,
 
214
        PKIX_PL_Date *date,
 
215
        pkix_RevocationMethod *checkerObject,
 
216
        PKIX_ProcessingParams *procParams,
 
217
        PKIX_UInt32 methodFlags,
 
218
        PKIX_RevocationStatus *pRevStatus,
 
219
        PKIX_UInt32 *pReasonCode,
 
220
        void **pNBIOContext,
 
221
        void *plContext)
 
222
{
 
223
        SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
 
224
        PKIX_Boolean uriFound = PKIX_FALSE;
 
225
        PKIX_Boolean passed = PKIX_TRUE;
 
226
        pkix_OcspChecker *checker = NULL;
 
227
        PKIX_PL_OcspCertID *cid = NULL;
 
228
        PKIX_PL_OcspRequest *request = NULL;
 
229
        PKIX_PL_OcspResponse *response = NULL;
 
230
        PKIX_PL_Date *validity = NULL;
 
231
        PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
 
232
        void *nbioContext = NULL;
 
233
 
 
234
        PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckExternal");
 
235
 
 
236
        PKIX_CHECK(
 
237
            pkix_CheckType((PKIX_PL_Object*)checkerObject,
 
238
                           PKIX_OCSPCHECKER_TYPE, plContext),
 
239
                PKIX_OBJECTNOTOCSPCHECKER);
 
240
 
 
241
        checker = (pkix_OcspChecker *)checkerObject;
 
242
 
 
243
        PKIX_CHECK(
 
244
            PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
 
245
                                      plContext),
 
246
            PKIX_OCSPCERTIDCREATEFAILED);
 
247
        
 
248
        /* create request */
 
249
        PKIX_CHECK(
 
250
            pkix_pl_OcspRequest_Create(cert, cid, validity, NULL, 
 
251
                                       methodFlags, &uriFound, &request,
 
252
                                       plContext),
 
253
            PKIX_OCSPREQUESTCREATEFAILED);
 
254
        
 
255
        if (uriFound == PKIX_FALSE) {
 
256
            /* no caching for certs lacking URI */
 
257
            resultCode = 0;
 
258
            goto cleanup;
 
259
        }
 
260
 
 
261
        /* send request and create a response object */
 
262
        PKIX_CHECK(
 
263
            pkix_pl_OcspResponse_Create(request, NULL,
 
264
                                        checker->certVerifyFcn,
 
265
                                        &nbioContext,
 
266
                                        &response,
 
267
                                        plContext),
 
268
            PKIX_OCSPRESPONSECREATEFAILED);
 
269
        if (nbioContext != 0) {
 
270
            *pNBIOContext = nbioContext;
 
271
            goto cleanup;
 
272
        }
 
273
        
 
274
        PKIX_CHECK(
 
275
            pkix_pl_OcspResponse_Decode(response, &passed,
 
276
                                        &resultCode, plContext),
 
277
            PKIX_OCSPRESPONSEDECODEFAILED);
 
278
        if (passed == PKIX_FALSE) {
 
279
            goto cleanup;
 
280
        }
 
281
        
 
282
        PKIX_CHECK(
 
283
            pkix_pl_OcspResponse_GetStatus(response, &passed,
 
284
                                           &resultCode, plContext),
 
285
            PKIX_OCSPRESPONSEGETSTATUSRETURNEDANERROR);
 
286
        if (passed == PKIX_FALSE) {
 
287
            goto cleanup;
 
288
        }
 
289
 
 
290
        PKIX_CHECK(
 
291
            pkix_pl_OcspResponse_VerifySignature(response, cert,
 
292
                                                 procParams, &passed, 
 
293
                                                 &nbioContext, plContext),
 
294
            PKIX_OCSPRESPONSEVERIFYSIGNATUREFAILED);
 
295
        if (nbioContext != 0) {
 
296
                *pNBIOContext = nbioContext;
 
297
                goto cleanup;
 
298
        }
 
299
        if (passed == PKIX_FALSE) {
 
300
                goto cleanup;
 
301
        }
 
302
 
 
303
        PKIX_CHECK(
 
304
            pkix_pl_OcspResponse_GetStatusForCert(cid, response, date,
 
305
                                                  &passed, &resultCode,
 
306
                                                  plContext),
 
307
            PKIX_OCSPRESPONSEGETSTATUSFORCERTFAILED);
 
308
        if (passed == PKIX_FALSE) {
 
309
            revStatus = pkix_OcspChecker_MapResultCodeToRevStatus(resultCode);
 
310
        } else {
 
311
            revStatus = PKIX_RevStatus_Success;
 
312
        }
 
313
 
 
314
cleanup:
 
315
        if (revStatus == PKIX_RevStatus_NoInfo && (uriFound || 
 
316
            methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
 
317
            methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
 
318
            revStatus = PKIX_RevStatus_Revoked;
 
319
        }
 
320
        *pRevStatus = revStatus;
 
321
 
 
322
        /* ocsp carries only tree statuses: good, bad, and unknown.
 
323
         * revStatus is used to pass them. reasonCode is always set
 
324
         * to be unknown. */
 
325
        *pReasonCode = crlEntryReasonUnspecified;
 
326
 
 
327
        if (!passed && cid && cid->certID) {
 
328
                /* We still own the certID object, which means that 
 
329
                 * it did not get consumed to create a cache entry.
 
330
                 * Let's make sure there is one.
 
331
                 */
 
332
                PKIX_Error *err;
 
333
                err = PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
 
334
                        cid, plContext);
 
335
                if (err) {
 
336
                        PKIX_PL_Object_DecRef((PKIX_PL_Object*)err, plContext);
 
337
                }
 
338
        }
 
339
        PKIX_DECREF(cid);
 
340
        PKIX_DECREF(request);
 
341
        PKIX_DECREF(response);
 
342
 
 
343
        PKIX_RETURN(OCSPCHECKER);
 
344
}
 
345
 
 
346