Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(335)

Side by Side Diff: nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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_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 CERTCRLEntryReasonCode *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. When a response is received it is decoded and the
204 * results provided to the caller.
205 *
206 * During the most recent enhancement of this function, it has been found that
207 * it doesn't correctly implement non-blocking I/O.
208 *
209 * The nbioContext is used in two places, for "response-obtaining" and
210 * for "response-verification".
211 *
212 * However, if this function gets called to resume, it always
213 * repeats the "request creation" and "response fetching" steps!
214 * As a result, the earlier operation is never resumed.
215 */
216 PKIX_Error *
217 pkix_OcspChecker_CheckExternal(
218 PKIX_PL_Cert *cert,
219 PKIX_PL_Cert *issuer,
220 PKIX_PL_Date *date,
221 pkix_RevocationMethod *checkerObject,
222 PKIX_ProcessingParams *procParams,
223 PKIX_UInt32 methodFlags,
224 PKIX_RevocationStatus *pRevStatus,
225 CERTCRLEntryReasonCode *pReasonCode,
226 void **pNBIOContext,
227 void *plContext)
228 {
229 SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
230 PKIX_Boolean uriFound = PKIX_FALSE;
231 PKIX_Boolean passed = PKIX_TRUE;
232 pkix_OcspChecker *checker = NULL;
233 PKIX_PL_OcspCertID *cid = NULL;
234 PKIX_PL_OcspRequest *request = NULL;
235 PKIX_PL_OcspResponse *response = NULL;
236 PKIX_PL_Date *validity = NULL;
237 PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
238 void *nbioContext = NULL;
239 enum { stageGET, stagePOST } currentStage;
240 PRBool retry = PR_FALSE;
241
242 PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckExternal");
243
244 PKIX_CHECK(
245 pkix_CheckType((PKIX_PL_Object*)checkerObject,
246 PKIX_OCSPCHECKER_TYPE, plContext),
247 PKIX_OBJECTNOTOCSPCHECKER);
248
249 checker = (pkix_OcspChecker *)checkerObject;
250
251 PKIX_CHECK(
252 PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
253 plContext),
254 PKIX_OCSPCERTIDCREATEFAILED);
255
256 /* create request */
257 PKIX_CHECK(
258 pkix_pl_OcspRequest_Create(cert, cid, validity, NULL,
259 methodFlags, &uriFound, &request,
260 plContext),
261 PKIX_OCSPREQUESTCREATEFAILED);
262
263 if (uriFound == PKIX_FALSE) {
264 /* no caching for certs lacking URI */
265 resultCode = 0;
266 goto cleanup;
267 }
268
269 if (methodFlags & CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP) {
270 /* Do not try HTTP GET, only HTTP POST */
271 currentStage = stagePOST;
272 } else {
273 /* Try HTTP GET first, falling back to POST */
274 currentStage = stageGET;
275 }
276
277 do {
278 const char *method;
279 passed = PKIX_TRUE;
280
281 retry = PR_FALSE;
282 if (currentStage == stageGET) {
283 method = "GET";
284 } else {
285 PORT_Assert(currentStage == stagePOST);
286 method = "POST";
287 }
288
289 /* send request and create a response object */
290 PKIX_CHECK_NO_GOTO(
291 pkix_pl_OcspResponse_Create(request, method, NULL,
292 checker->certVerifyFcn,
293 &nbioContext,
294 &response,
295 plContext),
296 PKIX_OCSPRESPONSECREATEFAILED);
297
298 if (pkixErrorResult) {
299 passed = PKIX_FALSE;
300 }
301
302 if (passed && nbioContext != 0) {
303 *pNBIOContext = nbioContext;
304 goto cleanup;
305 }
306
307 if (passed){
308 PKIX_CHECK_NO_GOTO(
309 pkix_pl_OcspResponse_Decode(response, &passed,
310 &resultCode, plContext),
311 PKIX_OCSPRESPONSEDECODEFAILED);
312 if (pkixErrorResult) {
313 passed = PKIX_FALSE;
314 }
315 }
316
317 if (passed){
318 PKIX_CHECK_NO_GOTO(
319 pkix_pl_OcspResponse_GetStatus(response, &passed,
320 &resultCode, plContex t),
321 PKIX_OCSPRESPONSEGETSTATUSRETURNEDANERROR);
322 if (pkixErrorResult) {
323 passed = PKIX_FALSE;
324 }
325 }
326
327 if (passed){
328 PKIX_CHECK_NO_GOTO(
329 pkix_pl_OcspResponse_VerifySignature(response, cert,
330 procParams, &pa ssed,
331 &nbioContext, p lContext),
332 PKIX_OCSPRESPONSEVERIFYSIGNATUREFAILED);
333 if (pkixErrorResult) {
334 passed = PKIX_FALSE;
335 } else {
336 if (nbioContext != 0) {
337 *pNBIOContext = nbioContext;
338 goto cleanup;
339 }
340 }
341 }
342
343 if (!passed && currentStage == stagePOST) {
344 /* We won't retry a POST failure, so it's final.
345 * Because the following block with its call to
346 * pkix_pl_OcspResponse_GetStatusForCert
347 * will take care of caching good or bad state,
348 * but we only execute that next block if there hasn't
349 * been a failure yet, we must cache the POST
350 * failure now.
351 */
352
353 if (cid && cid->certID) {
354 /* Caching MIGHT consume the cid. */
355 PKIX_Error *err;
356 err = PKIX_PL_OcspCertID_RememberOCSPProcessingF ailure(
357 cid, plContext);
358 if (err) {
359 PKIX_PL_Object_DecRef((PKIX_PL_Object*)e rr, plContext);
360 }
361 }
362 }
363
364 if (passed){
365 PKIX_Boolean allowCachingOfFailures =
366 (currentStage == stagePOST) ? PKIX_TRUE : PKIX_F ALSE;
367
368 PKIX_CHECK_NO_GOTO(
369 pkix_pl_OcspResponse_GetStatusForCert(cid, response,
370 allowCachingOf Failures,
371 date,
372 &passed, &resu ltCode,
373 plContext),
374 PKIX_OCSPRESPONSEGETSTATUSFORCERTFAILED);
375 if (pkixErrorResult) {
376 passed = PKIX_FALSE;
377 } else if (passed == PKIX_FALSE) {
378 revStatus = pkix_OcspChecker_MapResultCodeToRevS tatus(resultCode);
379 } else {
380 revStatus = PKIX_RevStatus_Success;
381 }
382 }
383
384 if (currentStage == stageGET && revStatus != PKIX_RevStatus_Succ ess &&
385 revStatus != PKIX_RevStatus_Revo ked) {
386 /* we'll retry */
387 PKIX_DECREF(response);
388 retry = PR_TRUE;
389 currentStage = stagePOST;
390 revStatus = PKIX_RevStatus_NoInfo;
391 if (pkixErrorResult) {
392 PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixError Result,
393 plContext);
394 pkixErrorResult = NULL;
395 }
396 }
397 } while (retry);
398
399 cleanup:
400 if (revStatus == PKIX_RevStatus_NoInfo && (uriFound ||
401 methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
402 methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
403 revStatus = PKIX_RevStatus_Revoked;
404 }
405 *pRevStatus = revStatus;
406
407 /* ocsp carries only three statuses: good, bad, and unknown.
408 * revStatus is used to pass them. reasonCode is always set
409 * to be unknown. */
410 *pReasonCode = crlEntryReasonUnspecified;
411
412 PKIX_DECREF(cid);
413 PKIX_DECREF(request);
414 PKIX_DECREF(response);
415
416 PKIX_RETURN(OCSPCHECKER);
417 }
418
419
OLDNEW
« no previous file with comments | « nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h ('k') | nss/lib/libpkix/pkix/checker/pkix_policychecker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698