OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 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 | 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/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | 4 |
5 /* | 5 /* |
6 * Implementation of OCSP services, for both client and server. | 6 * Implementation of OCSP services, for both client and server. |
7 * (XXX, really, mostly just for client right now, but intended to do both.) | 7 * (XXX, really, mostly just for client right now, but intended to do both.) |
8 */ | 8 */ |
9 | 9 |
10 #include "prerror.h" | 10 #include "prerror.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "sechash.h" | 26 #include "sechash.h" |
27 #include "secasn1.h" | 27 #include "secasn1.h" |
28 #include "plbase64.h" | 28 #include "plbase64.h" |
29 #include "keyhi.h" | 29 #include "keyhi.h" |
30 #include "cryptohi.h" | 30 #include "cryptohi.h" |
31 #include "ocsp.h" | 31 #include "ocsp.h" |
32 #include "ocspti.h" | 32 #include "ocspti.h" |
33 #include "ocspi.h" | 33 #include "ocspi.h" |
34 #include "genname.h" | 34 #include "genname.h" |
35 #include "certxutl.h" | 35 #include "certxutl.h" |
36 #include "pk11func.h"» /* for PK11_HashBuf */ | 36 #include "pk11func.h" /* for PK11_HashBuf */ |
37 #include <stdarg.h> | 37 #include <stdarg.h> |
38 #include <plhash.h> | 38 #include <plhash.h> |
39 | 39 |
40 #define DEFAULT_OCSP_CACHE_SIZE 1000 | 40 #define DEFAULT_OCSP_CACHE_SIZE 1000 |
41 #define DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 1*60*60L | 41 #define DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 1 * 60 * 60L |
42 #define DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 24*60*60L | 42 #define DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 24 * 60 * 60L |
43 #define DEFAULT_OSCP_TIMEOUT_SECONDS 60 | 43 #define DEFAULT_OSCP_TIMEOUT_SECONDS 60 |
44 #define MICROSECONDS_PER_SECOND 1000000L | 44 #define MICROSECONDS_PER_SECOND 1000000L |
45 | 45 |
46 typedef struct OCSPCacheItemStr OCSPCacheItem; | 46 typedef struct OCSPCacheItemStr OCSPCacheItem; |
47 typedef struct OCSPCacheDataStr OCSPCacheData; | 47 typedef struct OCSPCacheDataStr OCSPCacheData; |
48 | 48 |
49 struct OCSPCacheItemStr { | 49 struct OCSPCacheItemStr { |
50 /* LRU linking */ | 50 /* LRU linking */ |
51 OCSPCacheItem *moreRecent; | 51 OCSPCacheItem *moreRecent; |
52 OCSPCacheItem *lessRecent; | 52 OCSPCacheItem *lessRecent; |
(...skipping 29 matching lines...) Expand all Loading... |
82 PRMonitor *monitor; | 82 PRMonitor *monitor; |
83 const SEC_HttpClientFcn *defaultHttpClientFcn; | 83 const SEC_HttpClientFcn *defaultHttpClientFcn; |
84 PRInt32 maxCacheEntries; | 84 PRInt32 maxCacheEntries; |
85 PRUint32 minimumSecondsToNextFetchAttempt; | 85 PRUint32 minimumSecondsToNextFetchAttempt; |
86 PRUint32 maximumSecondsToNextFetchAttempt; | 86 PRUint32 maximumSecondsToNextFetchAttempt; |
87 PRUint32 timeoutSeconds; | 87 PRUint32 timeoutSeconds; |
88 OCSPCacheData cache; | 88 OCSPCacheData cache; |
89 SEC_OcspFailureMode ocspFailureMode; | 89 SEC_OcspFailureMode ocspFailureMode; |
90 CERT_StringFromCertFcn alternateOCSPAIAFcn; | 90 CERT_StringFromCertFcn alternateOCSPAIAFcn; |
91 PRBool forcePost; | 91 PRBool forcePost; |
92 } OCSP_Global = { NULL, | 92 } OCSP_Global = { NULL, |
93 NULL, | 93 NULL, |
94 DEFAULT_OCSP_CACHE_SIZE, | 94 DEFAULT_OCSP_CACHE_SIZE, |
95 DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT, | 95 DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT, |
96 DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT, | 96 DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT, |
97 DEFAULT_OSCP_TIMEOUT_SECONDS, | 97 DEFAULT_OSCP_TIMEOUT_SECONDS, |
98 {NULL, 0, NULL, NULL}, | 98 { NULL, 0, NULL, NULL }, |
99 ocspMode_FailureIsVerificationFailure, | 99 ocspMode_FailureIsVerificationFailure, |
100 NULL, | 100 NULL, |
101 PR_FALSE | 101 PR_FALSE }; |
102 }; | |
103 | |
104 | |
105 | 102 |
106 /* Forward declarations */ | 103 /* Forward declarations */ |
107 static SECItem * | 104 static SECItem * |
108 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena, | 105 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena, |
109 CERTOCSPRequest *request, | 106 CERTOCSPRequest *request, |
110 const char *location, | 107 const char *location, |
111 » » » » const char *method, | 108 const char *method, |
112 » » » » PRTime time, | 109 PRTime time, |
113 PRBool addServiceLocator, | 110 PRBool addServiceLocator, |
114 void *pwArg, | 111 void *pwArg, |
115 CERTOCSPRequest **pRequest); | 112 CERTOCSPRequest **pRequest); |
116 static SECStatus | 113 static SECStatus |
117 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, | 114 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, |
118 CERTOCSPCertID *certID, | 115 CERTOCSPCertID *certID, |
119 CERTCertificate *cert, | 116 CERTCertificate *cert, |
120 PRTime time, | 117 PRTime time, |
121 void *pwArg, | 118 void *pwArg, |
122 PRBool *certIDWasConsumed, | 119 PRBool *certIDWasConsumed, |
123 SECStatus *rv_ocsp); | 120 SECStatus *rv_ocsp); |
124 | 121 |
125 static SECStatus | 122 static SECStatus |
126 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle, | 123 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle, |
127 » » » » » CERTOCSPCertID *certID, | 124 CERTOCSPCertID *certID, |
128 » » » » » CERTCertificate *cert, | 125 CERTCertificate *cert, |
129 » » » » » PRTime time, | 126 PRTime time, |
130 » » » » » void *pwArg, | 127 void *pwArg, |
131 » » » » » const SECItem *encodedResponse, | 128 const SECItem *encodedResponse, |
132 » » » » » CERTOCSPResponse **pDecodedResponse, | 129 CERTOCSPResponse **pDecodedResponse, |
133 » » » » » CERTOCSPSingleResponse **pSingle); | 130 CERTOCSPSingleResponse **pSingle); |
134 | 131 |
135 static SECStatus | 132 static SECStatus |
136 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time); | 133 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time); |
137 | 134 |
138 static CERTOCSPCertID * | 135 static CERTOCSPCertID * |
139 cert_DupOCSPCertID(const CERTOCSPCertID *src); | 136 cert_DupOCSPCertID(const CERTOCSPCertID *src); |
140 | 137 |
141 #ifndef DEBUG | 138 #ifndef DEBUG |
142 #define OCSP_TRACE(msg) | 139 #define OCSP_TRACE(msg) |
143 #define OCSP_TRACE_TIME(msg, time) | 140 #define OCSP_TRACE_TIME(msg, time) |
144 #define OCSP_TRACE_CERT(cert) | 141 #define OCSP_TRACE_CERT(cert) |
145 #define OCSP_TRACE_CERTID(certid) | 142 #define OCSP_TRACE_CERTID(certid) |
146 #else | 143 #else |
147 #define OCSP_TRACE(msg) ocsp_Trace msg | 144 #define OCSP_TRACE(msg) ocsp_Trace msg |
148 #define OCSP_TRACE_TIME(msg, time) ocsp_dumpStringWithTime(msg, time) | 145 #define OCSP_TRACE_TIME(msg, time) ocsp_dumpStringWithTime(msg, time) |
149 #define OCSP_TRACE_CERT(cert) dumpCertificate(cert) | 146 #define OCSP_TRACE_CERT(cert) dumpCertificate(cert) |
150 #define OCSP_TRACE_CERTID(certid) dumpCertID(certid) | 147 #define OCSP_TRACE_CERTID(certid) dumpCertID(certid) |
151 | 148 |
152 #if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS) \ | 149 #if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS) || \ |
153 || defined(XP_MACOSX) | 150 defined(XP_MACOSX) |
154 #define NSS_HAVE_GETENV 1 | 151 #define NSS_HAVE_GETENV 1 |
155 #endif | 152 #endif |
156 | 153 |
157 static PRBool wantOcspTrace(void) | 154 static PRBool |
| 155 wantOcspTrace(void) |
158 { | 156 { |
159 static PRBool firstTime = PR_TRUE; | 157 static PRBool firstTime = PR_TRUE; |
160 static PRBool wantTrace = PR_FALSE; | 158 static PRBool wantTrace = PR_FALSE; |
161 | 159 |
162 #ifdef NSS_HAVE_GETENV | 160 #ifdef NSS_HAVE_GETENV |
163 if (firstTime) { | 161 if (firstTime) { |
164 char *ev = getenv("NSS_TRACE_OCSP"); | 162 char *ev = PR_GetEnvSecure("NSS_TRACE_OCSP"); |
165 if (ev && ev[0]) { | 163 if (ev && ev[0]) { |
166 wantTrace = PR_TRUE; | 164 wantTrace = PR_TRUE; |
167 } | 165 } |
168 firstTime = PR_FALSE; | 166 firstTime = PR_FALSE; |
169 } | 167 } |
170 #endif | 168 #endif |
171 return wantTrace; | 169 return wantTrace; |
172 } | 170 } |
173 | 171 |
174 static void | 172 static void |
175 ocsp_Trace(const char *format, ...) | 173 ocsp_Trace(const char *format, ...) |
176 { | 174 { |
177 char buf[2000]; | 175 char buf[2000]; |
178 va_list args; | 176 va_list args; |
179 | 177 |
180 if (!wantOcspTrace()) | 178 if (!wantOcspTrace()) |
181 return; | 179 return; |
182 va_start(args, format); | 180 va_start(args, format); |
183 PR_vsnprintf(buf, sizeof(buf), format, args); | 181 PR_vsnprintf(buf, sizeof(buf), format, args); |
184 va_end(args); | 182 va_end(args); |
185 PR_LogPrint("%s", buf); | 183 PR_LogPrint("%s", buf); |
186 } | 184 } |
187 | 185 |
188 static void | 186 static void |
189 ocsp_dumpStringWithTime(const char *str, PRTime time) | 187 ocsp_dumpStringWithTime(const char *str, PRTime time) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 ocsp_Trace("OCSP ## SUBJECT: %s\n", cert->subjectName); | 226 ocsp_Trace("OCSP ## SUBJECT: %s\n", cert->subjectName); |
229 { | 227 { |
230 PRTime timeBefore, timeAfter; | 228 PRTime timeBefore, timeAfter; |
231 PRExplodedTime beforePrintable, afterPrintable; | 229 PRExplodedTime beforePrintable, afterPrintable; |
232 char beforestr[256], afterstr[256]; | 230 char beforestr[256], afterstr[256]; |
233 PRStatus rv1, rv2; | 231 PRStatus rv1, rv2; |
234 DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore); | 232 DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore); |
235 DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter); | 233 DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter); |
236 PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable); | 234 PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable); |
237 PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable); | 235 PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable); |
238 rv1 = PR_FormatTime(beforestr, 256, "%a %b %d %H:%M:%S %Y", | 236 rv1 = PR_FormatTime(beforestr, 256, "%a %b %d %H:%M:%S %Y", |
239 &beforePrintable); | 237 &beforePrintable); |
240 rv2 = PR_FormatTime(afterstr, 256, "%a %b %d %H:%M:%S %Y", | 238 rv2 = PR_FormatTime(afterstr, 256, "%a %b %d %H:%M:%S %Y", |
241 &afterPrintable); | 239 &afterPrintable); |
242 ocsp_Trace("OCSP ## VALIDITY: %s to %s\n", rv1 ? beforestr : "", | 240 ocsp_Trace("OCSP ## VALIDITY: %s to %s\n", rv1 ? beforestr : "", |
243 rv2 ? afterstr : ""); | 241 rv2 ? afterstr : ""); |
244 } | 242 } |
245 ocsp_Trace("OCSP ## ISSUER: %s\n", cert->issuerName); | 243 ocsp_Trace("OCSP ## ISSUER: %s\n", cert->issuerName); |
246 printHexString("OCSP ## SERIAL NUMBER:", &cert->serialNumber); | 244 printHexString("OCSP ## SERIAL NUMBER:", &cert->serialNumber); |
247 } | 245 } |
248 | 246 |
249 static void | 247 static void |
250 dumpCertID(CERTOCSPCertID *certID) | 248 dumpCertID(CERTOCSPCertID *certID) |
251 { | 249 { |
252 if (!wantOcspTrace()) | 250 if (!wantOcspTrace()) |
253 return; | 251 return; |
254 | 252 |
255 printHexString("OCSP certID issuer", &certID->issuerNameHash); | 253 printHexString("OCSP certID issuer", &certID->issuerNameHash); |
256 printHexString("OCSP certID serial", &certID->serialNumber); | 254 printHexString("OCSP certID serial", &certID->serialNumber); |
257 } | 255 } |
258 #endif | 256 #endif |
259 | 257 |
260 SECStatus | 258 SECStatus |
261 SEC_RegisterDefaultHttpClient(const SEC_HttpClientFcn *fcnTable) | 259 SEC_RegisterDefaultHttpClient(const SEC_HttpClientFcn *fcnTable) |
262 { | 260 { |
263 if (!OCSP_Global.monitor) { | 261 if (!OCSP_Global.monitor) { |
264 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); | 262 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); |
265 return SECFailure; | 263 return SECFailure; |
266 } | 264 } |
267 | 265 |
268 PR_EnterMonitor(OCSP_Global.monitor); | 266 PR_EnterMonitor(OCSP_Global.monitor); |
269 OCSP_Global.defaultHttpClientFcn = fcnTable; | 267 OCSP_Global.defaultHttpClientFcn = fcnTable; |
270 PR_ExitMonitor(OCSP_Global.monitor); | 268 PR_ExitMonitor(OCSP_Global.monitor); |
271 | 269 |
272 return SECSuccess; | 270 return SECSuccess; |
273 } | 271 } |
274 | 272 |
275 SECStatus | 273 SECStatus |
276 CERT_RegisterAlternateOCSPAIAInfoCallBack( | 274 CERT_RegisterAlternateOCSPAIAInfoCallBack( |
277 » » » CERT_StringFromCertFcn newCallback, | 275 CERT_StringFromCertFcn newCallback, |
278 » » » CERT_StringFromCertFcn * oldCallback) | 276 CERT_StringFromCertFcn *oldCallback) |
279 { | 277 { |
280 CERT_StringFromCertFcn old; | 278 CERT_StringFromCertFcn old; |
281 | 279 |
282 if (!OCSP_Global.monitor) { | 280 if (!OCSP_Global.monitor) { |
283 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); | 281 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); |
284 return SECFailure; | 282 return SECFailure; |
285 } | 283 } |
286 | 284 |
287 PR_EnterMonitor(OCSP_Global.monitor); | 285 PR_EnterMonitor(OCSP_Global.monitor); |
288 old = OCSP_Global.alternateOCSPAIAFcn; | 286 old = OCSP_Global.alternateOCSPAIAFcn; |
289 OCSP_Global.alternateOCSPAIAFcn = newCallback; | 287 OCSP_Global.alternateOCSPAIAFcn = newCallback; |
290 PR_ExitMonitor(OCSP_Global.monitor); | 288 PR_ExitMonitor(OCSP_Global.monitor); |
291 if (oldCallback) | 289 if (oldCallback) |
292 » *oldCallback = old; | 290 *oldCallback = old; |
293 return SECSuccess; | 291 return SECSuccess; |
294 } | 292 } |
295 | 293 |
296 static PLHashNumber PR_CALLBACK | 294 static PLHashNumber PR_CALLBACK |
297 ocsp_CacheKeyHashFunction(const void *key) | 295 ocsp_CacheKeyHashFunction(const void *key) |
298 { | 296 { |
299 CERTOCSPCertID *cid = (CERTOCSPCertID *)key; | 297 CERTOCSPCertID *cid = (CERTOCSPCertID *)key; |
300 PLHashNumber hash = 0; | 298 PLHashNumber hash = 0; |
301 unsigned int i; | 299 unsigned int i; |
302 unsigned char *walk; | 300 unsigned char *walk; |
303 | 301 |
304 /* a very simple hash calculation for the initial coding phase */ | 302 /* a very simple hash calculation for the initial coding phase */ |
305 walk = (unsigned char*)cid->issuerNameHash.data; | 303 walk = (unsigned char *)cid->issuerNameHash.data; |
306 for (i=0; i < cid->issuerNameHash.len; ++i, ++walk) { | 304 for (i = 0; i < cid->issuerNameHash.len; ++i, ++walk) { |
307 hash += *walk; | 305 hash += *walk; |
308 } | 306 } |
309 walk = (unsigned char*)cid->issuerKeyHash.data; | 307 walk = (unsigned char *)cid->issuerKeyHash.data; |
310 for (i=0; i < cid->issuerKeyHash.len; ++i, ++walk) { | 308 for (i = 0; i < cid->issuerKeyHash.len; ++i, ++walk) { |
311 hash += *walk; | 309 hash += *walk; |
312 } | 310 } |
313 walk = (unsigned char*)cid->serialNumber.data; | 311 walk = (unsigned char *)cid->serialNumber.data; |
314 for (i=0; i < cid->serialNumber.len; ++i, ++walk) { | 312 for (i = 0; i < cid->serialNumber.len; ++i, ++walk) { |
315 hash += *walk; | 313 hash += *walk; |
316 } | 314 } |
317 return hash; | 315 return hash; |
318 } | 316 } |
319 | 317 |
320 static PRIntn PR_CALLBACK | 318 static PRIntn PR_CALLBACK |
321 ocsp_CacheKeyCompareFunction(const void *v1, const void *v2) | 319 ocsp_CacheKeyCompareFunction(const void *v1, const void *v2) |
322 { | 320 { |
323 CERTOCSPCertID *cid1 = (CERTOCSPCertID *)v1; | 321 CERTOCSPCertID *cid1 = (CERTOCSPCertID *)v1; |
324 CERTOCSPCertID *cid2 = (CERTOCSPCertID *)v2; | 322 CERTOCSPCertID *cid2 = (CERTOCSPCertID *)v2; |
325 | 323 |
326 return (SECEqual == SECITEM_CompareItem(&cid1->issuerNameHash, | 324 return (SECEqual == SECITEM_CompareItem(&cid1->issuerNameHash, |
327 &cid2->issuerNameHash) | 325 &cid2->issuerNameHash) && |
328 && SECEqual == SECITEM_CompareItem(&cid1->issuerKeyHash, | 326 SECEqual == SECITEM_CompareItem(&cid1->issuerKeyHash, |
329 &cid2->issuerKeyHash) | 327 &cid2->issuerKeyHash) && |
330 && SECEqual == SECITEM_CompareItem(&cid1->serialNumber, | 328 SECEqual == SECITEM_CompareItem(&cid1->serialNumber, |
331 &cid2->serialNumber)); | 329 &cid2->serialNumber)); |
332 } | 330 } |
333 | 331 |
334 static SECStatus | 332 static SECStatus |
335 ocsp_CopyRevokedInfo(PLArenaPool *arena, ocspCertStatus *dest, | 333 ocsp_CopyRevokedInfo(PLArenaPool *arena, ocspCertStatus *dest, |
336 ocspRevokedInfo *src) | 334 ocspRevokedInfo *src) |
337 { | 335 { |
338 SECStatus rv = SECFailure; | 336 SECStatus rv = SECFailure; |
339 void *mark; | 337 void *mark; |
340 | 338 |
341 mark = PORT_ArenaMark(arena); | 339 mark = PORT_ArenaMark(arena); |
342 | 340 |
343 dest->certStatusInfo.revokedInfo = | 341 dest->certStatusInfo.revokedInfo = |
344 (ocspRevokedInfo *) PORT_ArenaZAlloc(arena, sizeof(ocspRevokedInfo)); | 342 (ocspRevokedInfo *)PORT_ArenaZAlloc(arena, sizeof(ocspRevokedInfo)); |
345 if (!dest->certStatusInfo.revokedInfo) { | 343 if (!dest->certStatusInfo.revokedInfo) { |
346 goto loser; | 344 goto loser; |
347 } | 345 } |
348 | 346 |
349 rv = SECITEM_CopyItem(arena, | 347 rv = SECITEM_CopyItem(arena, |
350 &dest->certStatusInfo.revokedInfo->revocationTime, | 348 &dest->certStatusInfo.revokedInfo->revocationTime, |
351 &src->revocationTime); | 349 &src->revocationTime); |
352 if (rv != SECSuccess) { | 350 if (rv != SECSuccess) { |
353 goto loser; | 351 goto loser; |
354 } | 352 } |
355 | 353 |
356 if (src->revocationReason) { | 354 if (src->revocationReason) { |
357 dest->certStatusInfo.revokedInfo->revocationReason = | 355 dest->certStatusInfo.revokedInfo->revocationReason = |
358 SECITEM_ArenaDupItem(arena, src->revocationReason); | 356 SECITEM_ArenaDupItem(arena, src->revocationReason); |
359 if (!dest->certStatusInfo.revokedInfo->revocationReason) { | 357 if (!dest->certStatusInfo.revokedInfo->revocationReason) { |
360 goto loser; | 358 goto loser; |
361 } | 359 } |
362 } else { | 360 } else { |
363 dest->certStatusInfo.revokedInfo->revocationReason = NULL; | 361 dest->certStatusInfo.revokedInfo->revocationReason = NULL; |
364 } | 362 } |
365 | 363 |
366 PORT_ArenaUnmark(arena, mark); | 364 PORT_ArenaUnmark(arena, mark); |
367 return SECSuccess; | 365 return SECSuccess; |
368 | 366 |
369 loser: | 367 loser: |
370 PORT_ArenaRelease(arena, mark); | 368 PORT_ArenaRelease(arena, mark); |
371 return SECFailure; | 369 return SECFailure; |
372 } | 370 } |
373 | 371 |
374 static SECStatus | 372 static SECStatus |
375 ocsp_CopyCertStatus(PLArenaPool *arena, ocspCertStatus *dest, | 373 ocsp_CopyCertStatus(PLArenaPool *arena, ocspCertStatus *dest, |
376 ocspCertStatus*src) | 374 ocspCertStatus *src) |
377 { | 375 { |
378 SECStatus rv = SECFailure; | 376 SECStatus rv = SECFailure; |
379 dest->certStatusType = src->certStatusType; | 377 dest->certStatusType = src->certStatusType; |
380 | 378 |
381 switch (src->certStatusType) { | 379 switch (src->certStatusType) { |
382 case ocspCertStatus_good: | 380 case ocspCertStatus_good: |
383 dest->certStatusInfo.goodInfo = | 381 dest->certStatusInfo.goodInfo = |
384 SECITEM_ArenaDupItem(arena, src->certStatusInfo.goodInfo); | 382 SECITEM_ArenaDupItem(arena, src->certStatusInfo.goodInfo); |
385 if (dest->certStatusInfo.goodInfo != NULL) { | 383 if (dest->certStatusInfo.goodInfo != NULL) { |
386 rv = SECSuccess; | 384 rv = SECSuccess; |
387 } | 385 } |
388 break; | 386 break; |
389 case ocspCertStatus_revoked: | 387 case ocspCertStatus_revoked: |
390 rv = ocsp_CopyRevokedInfo(arena, dest, | 388 rv = ocsp_CopyRevokedInfo(arena, dest, |
391 src->certStatusInfo.revokedInfo); | 389 src->certStatusInfo.revokedInfo); |
392 break; | 390 break; |
393 case ocspCertStatus_unknown: | 391 case ocspCertStatus_unknown: |
394 dest->certStatusInfo.unknownInfo = | 392 dest->certStatusInfo.unknownInfo = |
395 SECITEM_ArenaDupItem(arena, src->certStatusInfo.unknownInfo); | 393 SECITEM_ArenaDupItem(arena, src->certStatusInfo.unknownInfo); |
396 if (dest->certStatusInfo.unknownInfo != NULL) { | 394 if (dest->certStatusInfo.unknownInfo != NULL) { |
397 rv = SECSuccess; | 395 rv = SECSuccess; |
398 } | 396 } |
399 break; | 397 break; |
400 case ocspCertStatus_other: | 398 case ocspCertStatus_other: |
401 default: | 399 default: |
402 PORT_Assert(src->certStatusType == ocspCertStatus_other); | 400 PORT_Assert(src->certStatusType == ocspCertStatus_other); |
403 dest->certStatusInfo.otherInfo = | 401 dest->certStatusInfo.otherInfo = |
404 SECITEM_ArenaDupItem(arena, src->certStatusInfo.otherInfo); | 402 SECITEM_ArenaDupItem(arena, src->certStatusInfo.otherInfo); |
405 if (dest->certStatusInfo.otherInfo != NULL) { | 403 if (dest->certStatusInfo.otherInfo != NULL) { |
406 rv = SECSuccess; | 404 rv = SECSuccess; |
407 } | 405 } |
408 break; | 406 break; |
409 } | 407 } |
410 return rv; | 408 return rv; |
411 } | 409 } |
412 | 410 |
413 static void | 411 static void |
414 ocsp_AddCacheItemToLinkedList(OCSPCacheData *cache, OCSPCacheItem *new_most_rece
nt) | 412 ocsp_AddCacheItemToLinkedList(OCSPCacheData *cache, OCSPCacheItem *new_most_rece
nt) |
415 { | 413 { |
416 PR_EnterMonitor(OCSP_Global.monitor); | 414 PR_EnterMonitor(OCSP_Global.monitor); |
417 | 415 |
418 if (!cache->LRUitem) { | 416 if (!cache->LRUitem) { |
(...skipping 27 matching lines...) Expand all Loading... |
446 PORT_Assert(cache->numberOfEntries == 1); | 444 PORT_Assert(cache->numberOfEntries == 1); |
447 PORT_Assert(item->moreRecent == NULL); | 445 PORT_Assert(item->moreRecent == NULL); |
448 cache->MRUitem = NULL; | 446 cache->MRUitem = NULL; |
449 cache->LRUitem = NULL; | 447 cache->LRUitem = NULL; |
450 } | 448 } |
451 PR_ExitMonitor(OCSP_Global.monitor); | 449 PR_ExitMonitor(OCSP_Global.monitor); |
452 return; | 450 return; |
453 } | 451 } |
454 | 452 |
455 PORT_Assert(cache->numberOfEntries > 1); | 453 PORT_Assert(cache->numberOfEntries > 1); |
456 | 454 |
457 if (item == cache->LRUitem) { | 455 if (item == cache->LRUitem) { |
458 PORT_Assert(item != cache->MRUitem); | 456 PORT_Assert(item != cache->MRUitem); |
459 PORT_Assert(item->lessRecent == NULL); | 457 PORT_Assert(item->lessRecent == NULL); |
460 PORT_Assert(item->moreRecent != NULL); | 458 PORT_Assert(item->moreRecent != NULL); |
461 PORT_Assert(item->moreRecent->lessRecent == item); | 459 PORT_Assert(item->moreRecent->lessRecent == item); |
462 cache->LRUitem = item->moreRecent; | 460 cache->LRUitem = item->moreRecent; |
463 cache->LRUitem->lessRecent = NULL; | 461 cache->LRUitem->lessRecent = NULL; |
464 } | 462 } else if (item == cache->MRUitem) { |
465 else if (item == cache->MRUitem) { | |
466 PORT_Assert(item->moreRecent == NULL); | 463 PORT_Assert(item->moreRecent == NULL); |
467 PORT_Assert(item->lessRecent != NULL); | 464 PORT_Assert(item->lessRecent != NULL); |
468 PORT_Assert(item->lessRecent->moreRecent == item); | 465 PORT_Assert(item->lessRecent->moreRecent == item); |
469 cache->MRUitem = item->lessRecent; | 466 cache->MRUitem = item->lessRecent; |
470 cache->MRUitem->moreRecent = NULL; | 467 cache->MRUitem->moreRecent = NULL; |
471 } else { | 468 } else { |
472 /* remove an entry in the middle of the list */ | 469 /* remove an entry in the middle of the list */ |
473 PORT_Assert(item->moreRecent != NULL); | 470 PORT_Assert(item->moreRecent != NULL); |
474 PORT_Assert(item->lessRecent != NULL); | 471 PORT_Assert(item->lessRecent != NULL); |
475 PORT_Assert(item->lessRecent->moreRecent == item); | 472 PORT_Assert(item->lessRecent->moreRecent == item); |
476 PORT_Assert(item->moreRecent->lessRecent == item); | 473 PORT_Assert(item->moreRecent->lessRecent == item); |
477 item->moreRecent->lessRecent = item->lessRecent; | 474 item->moreRecent->lessRecent = item->lessRecent; |
478 item->lessRecent->moreRecent = item->moreRecent; | 475 item->lessRecent->moreRecent = item->moreRecent; |
479 } | 476 } |
480 | 477 |
481 item->lessRecent = NULL; | 478 item->lessRecent = NULL; |
482 item->moreRecent = NULL; | 479 item->moreRecent = NULL; |
483 | 480 |
484 PR_ExitMonitor(OCSP_Global.monitor); | 481 PR_ExitMonitor(OCSP_Global.monitor); |
485 } | 482 } |
486 | 483 |
487 static void | 484 static void |
488 ocsp_MakeCacheEntryMostRecent(OCSPCacheData *cache, OCSPCacheItem *new_most_rece
nt) | 485 ocsp_MakeCacheEntryMostRecent(OCSPCacheData *cache, OCSPCacheItem *new_most_rece
nt) |
489 { | 486 { |
490 OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent THREADID %p\n", | 487 OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent THREADID %p\n", |
491 PR_GetCurrentThread())); | 488 PR_GetCurrentThread())); |
492 PR_EnterMonitor(OCSP_Global.monitor); | 489 PR_EnterMonitor(OCSP_Global.monitor); |
493 if (cache->MRUitem == new_most_recent) { | 490 if (cache->MRUitem == new_most_recent) { |
494 OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent ALREADY MOST\n")); | 491 OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent ALREADY MOST\n")); |
495 PR_ExitMonitor(OCSP_Global.monitor); | 492 PR_ExitMonitor(OCSP_Global.monitor); |
496 return; | 493 return; |
497 } | 494 } |
498 OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent NEW entry\n")); | 495 OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent NEW entry\n")); |
499 ocsp_RemoveCacheItemFromLinkedList(cache, new_most_recent); | 496 ocsp_RemoveCacheItemFromLinkedList(cache, new_most_recent); |
500 ocsp_AddCacheItemToLinkedList(cache, new_most_recent); | 497 ocsp_AddCacheItemToLinkedList(cache, new_most_recent); |
501 PR_ExitMonitor(OCSP_Global.monitor); | 498 PR_ExitMonitor(OCSP_Global.monitor); |
502 } | 499 } |
503 | 500 |
504 static PRBool | 501 static PRBool |
505 ocsp_IsCacheDisabled(void) | 502 ocsp_IsCacheDisabled(void) |
506 { | 503 { |
507 /* | 504 /* |
508 * maxCacheEntries == 0 means unlimited cache entries | 505 * maxCacheEntries == 0 means unlimited cache entries |
509 * maxCacheEntries < 0 means cache is disabled | 506 * maxCacheEntries < 0 means cache is disabled |
510 */ | 507 */ |
511 PRBool retval; | 508 PRBool retval; |
512 PR_EnterMonitor(OCSP_Global.monitor); | 509 PR_EnterMonitor(OCSP_Global.monitor); |
513 retval = (OCSP_Global.maxCacheEntries < 0); | 510 retval = (OCSP_Global.maxCacheEntries < 0); |
514 PR_ExitMonitor(OCSP_Global.monitor); | 511 PR_ExitMonitor(OCSP_Global.monitor); |
515 return retval; | 512 return retval; |
516 } | 513 } |
517 | 514 |
518 static OCSPCacheItem * | 515 static OCSPCacheItem * |
519 ocsp_FindCacheEntry(OCSPCacheData *cache, CERTOCSPCertID *certID) | 516 ocsp_FindCacheEntry(OCSPCacheData *cache, CERTOCSPCertID *certID) |
520 { | 517 { |
521 OCSPCacheItem *found_ocsp_item = NULL; | 518 OCSPCacheItem *found_ocsp_item = NULL; |
522 OCSP_TRACE(("OCSP ocsp_FindCacheEntry\n")); | 519 OCSP_TRACE(("OCSP ocsp_FindCacheEntry\n")); |
523 OCSP_TRACE_CERTID(certID); | 520 OCSP_TRACE_CERTID(certID); |
524 PR_EnterMonitor(OCSP_Global.monitor); | 521 PR_EnterMonitor(OCSP_Global.monitor); |
525 if (ocsp_IsCacheDisabled()) | 522 if (ocsp_IsCacheDisabled()) |
526 goto loser; | 523 goto loser; |
527 | 524 |
528 found_ocsp_item = (OCSPCacheItem *)PL_HashTableLookup( | 525 found_ocsp_item = (OCSPCacheItem *)PL_HashTableLookup( |
529 cache->entries, certID); | 526 cache->entries, certID); |
530 if (!found_ocsp_item) | 527 if (!found_ocsp_item) |
531 goto loser; | 528 goto loser; |
532 | 529 |
533 OCSP_TRACE(("OCSP ocsp_FindCacheEntry FOUND!\n")); | 530 OCSP_TRACE(("OCSP ocsp_FindCacheEntry FOUND!\n")); |
534 ocsp_MakeCacheEntryMostRecent(cache, found_ocsp_item); | 531 ocsp_MakeCacheEntryMostRecent(cache, found_ocsp_item); |
535 | 532 |
536 loser: | 533 loser: |
537 PR_ExitMonitor(OCSP_Global.monitor); | 534 PR_ExitMonitor(OCSP_Global.monitor); |
538 return found_ocsp_item; | 535 return found_ocsp_item; |
539 } | 536 } |
540 | 537 |
541 static void | 538 static void |
542 ocsp_FreeCacheItem(OCSPCacheItem *item) | 539 ocsp_FreeCacheItem(OCSPCacheItem *item) |
543 { | 540 { |
544 OCSP_TRACE(("OCSP ocsp_FreeCacheItem\n")); | 541 OCSP_TRACE(("OCSP ocsp_FreeCacheItem\n")); |
545 if (item->certStatusArena) { | 542 if (item->certStatusArena) { |
546 PORT_FreeArena(item->certStatusArena, PR_FALSE); | 543 PORT_FreeArena(item->certStatusArena, PR_FALSE); |
547 } | 544 } |
548 if (item->certID->poolp) { | 545 if (item->certID->poolp) { |
549 /* freeing this poolp arena will also free item */ | 546 /* freeing this poolp arena will also free item */ |
550 PORT_FreeArena(item->certID->poolp, PR_FALSE); | 547 PORT_FreeArena(item->certID->poolp, PR_FALSE); |
551 } | 548 } |
552 } | 549 } |
553 | 550 |
554 static void | 551 static void |
555 ocsp_RemoveCacheItem(OCSPCacheData *cache, OCSPCacheItem *item) | 552 ocsp_RemoveCacheItem(OCSPCacheData *cache, OCSPCacheItem *item) |
556 { | 553 { |
557 /* The item we're removing could be either the least recently used item, | 554 /* The item we're removing could be either the least recently used item, |
558 * or it could be an item that couldn't get updated with newer status info | 555 * or it could be an item that couldn't get updated with newer status info |
559 * because of an allocation failure, or it could get removed because we're | 556 * because of an allocation failure, or it could get removed because we're |
560 * cleaning up. | 557 * cleaning up. |
561 */ | 558 */ |
562 OCSP_TRACE(("OCSP ocsp_RemoveCacheItem, THREADID %p\n", PR_GetCurrentThread(
))); | 559 OCSP_TRACE(("OCSP ocsp_RemoveCacheItem, THREADID %p\n", PR_GetCurrentThread(
))); |
563 PR_EnterMonitor(OCSP_Global.monitor); | 560 PR_EnterMonitor(OCSP_Global.monitor); |
564 | 561 |
565 ocsp_RemoveCacheItemFromLinkedList(cache, item); | 562 ocsp_RemoveCacheItemFromLinkedList(cache, item); |
566 #ifdef DEBUG | 563 #ifdef DEBUG |
567 { | 564 { |
568 PRBool couldRemoveFromHashTable = PL_HashTableRemove(cache->entries, | 565 PRBool couldRemoveFromHashTable = PL_HashTableRemove(cache->entries, |
569 item->certID); | 566 item->certID); |
570 PORT_Assert(couldRemoveFromHashTable); | 567 PORT_Assert(couldRemoveFromHashTable); |
571 } | 568 } |
572 #else | 569 #else |
573 PL_HashTableRemove(cache->entries, item->certID); | 570 PL_HashTableRemove(cache->entries, item->certID); |
574 #endif | 571 #endif |
575 --cache->numberOfEntries; | 572 --cache->numberOfEntries; |
576 ocsp_FreeCacheItem(item); | 573 ocsp_FreeCacheItem(item); |
577 PR_ExitMonitor(OCSP_Global.monitor); | 574 PR_ExitMonitor(OCSP_Global.monitor); |
578 } | 575 } |
579 | 576 |
580 static void | 577 static void |
581 ocsp_CheckCacheSize(OCSPCacheData *cache) | 578 ocsp_CheckCacheSize(OCSPCacheData *cache) |
582 { | 579 { |
583 OCSP_TRACE(("OCSP ocsp_CheckCacheSize\n")); | 580 OCSP_TRACE(("OCSP ocsp_CheckCacheSize\n")); |
584 PR_EnterMonitor(OCSP_Global.monitor); | 581 PR_EnterMonitor(OCSP_Global.monitor); |
585 if (OCSP_Global.maxCacheEntries > 0) { | 582 if (OCSP_Global.maxCacheEntries > 0) { |
586 /* Cache is not disabled. Number of cache entries is limited. | 583 /* Cache is not disabled. Number of cache entries is limited. |
587 * The monitor ensures that maxCacheEntries remains positive. | 584 * The monitor ensures that maxCacheEntries remains positive. |
588 */ | 585 */ |
589 while (cache->numberOfEntries > | 586 while (cache->numberOfEntries > |
590 (PRUint32)OCSP_Global.maxCacheEntries) { | 587 (PRUint32)OCSP_Global.maxCacheEntries) { |
591 ocsp_RemoveCacheItem(cache, cache->LRUitem); | 588 ocsp_RemoveCacheItem(cache, cache->LRUitem); |
592 } | 589 } |
593 } | 590 } |
594 PR_ExitMonitor(OCSP_Global.monitor); | 591 PR_ExitMonitor(OCSP_Global.monitor); |
595 } | 592 } |
596 | 593 |
597 SECStatus | 594 SECStatus |
598 CERT_ClearOCSPCache(void) | 595 CERT_ClearOCSPCache(void) |
599 { | 596 { |
600 OCSP_TRACE(("OCSP CERT_ClearOCSPCache\n")); | 597 OCSP_TRACE(("OCSP CERT_ClearOCSPCache\n")); |
601 PR_EnterMonitor(OCSP_Global.monitor); | 598 PR_EnterMonitor(OCSP_Global.monitor); |
602 while (OCSP_Global.cache.numberOfEntries > 0) { | 599 while (OCSP_Global.cache.numberOfEntries > 0) { |
603 ocsp_RemoveCacheItem(&OCSP_Global.cache, | 600 ocsp_RemoveCacheItem(&OCSP_Global.cache, |
604 OCSP_Global.cache.LRUitem); | 601 OCSP_Global.cache.LRUitem); |
605 } | 602 } |
606 PR_ExitMonitor(OCSP_Global.monitor); | 603 PR_ExitMonitor(OCSP_Global.monitor); |
607 return SECSuccess; | 604 return SECSuccess; |
608 } | 605 } |
609 | 606 |
610 static SECStatus | 607 static SECStatus |
611 ocsp_CreateCacheItemAndConsumeCertID(OCSPCacheData *cache, | 608 ocsp_CreateCacheItemAndConsumeCertID(OCSPCacheData *cache, |
612 CERTOCSPCertID *certID, | 609 CERTOCSPCertID *certID, |
613 OCSPCacheItem **pCacheItem) | 610 OCSPCacheItem **pCacheItem) |
614 { | 611 { |
615 PLArenaPool *arena; | 612 PLArenaPool *arena; |
616 void *mark; | 613 void *mark; |
617 PLHashEntry *new_hash_entry; | 614 PLHashEntry *new_hash_entry; |
618 OCSPCacheItem *item; | 615 OCSPCacheItem *item; |
619 | 616 |
620 PORT_Assert(pCacheItem != NULL); | 617 PORT_Assert(pCacheItem != NULL); |
621 *pCacheItem = NULL; | 618 *pCacheItem = NULL; |
622 | 619 |
623 PR_EnterMonitor(OCSP_Global.monitor); | 620 PR_EnterMonitor(OCSP_Global.monitor); |
624 arena = certID->poolp; | 621 arena = certID->poolp; |
625 mark = PORT_ArenaMark(arena); | 622 mark = PORT_ArenaMark(arena); |
626 | 623 |
627 /* ZAlloc will init all Bools to False and all Pointers to NULL | 624 /* ZAlloc will init all Bools to False and all Pointers to NULL |
628 and all error codes to zero/good. */ | 625 and all error codes to zero/good. */ |
629 item = (OCSPCacheItem *)PORT_ArenaZAlloc(certID->poolp, | 626 item = (OCSPCacheItem *)PORT_ArenaZAlloc(certID->poolp, |
630 sizeof(OCSPCacheItem)); | 627 sizeof(OCSPCacheItem)); |
631 if (!item) { | 628 if (!item) { |
632 goto loser; | 629 goto loser; |
633 } | 630 } |
634 item->certID = certID; | 631 item->certID = certID; |
635 new_hash_entry = PL_HashTableAdd(cache->entries, item->certID, | 632 new_hash_entry = PL_HashTableAdd(cache->entries, item->certID, |
636 item); | 633 item); |
637 if (!new_hash_entry) { | 634 if (!new_hash_entry) { |
638 goto loser; | 635 goto loser; |
639 } | 636 } |
640 ++cache->numberOfEntries; | 637 ++cache->numberOfEntries; |
641 PORT_ArenaUnmark(arena, mark); | 638 PORT_ArenaUnmark(arena, mark); |
642 ocsp_AddCacheItemToLinkedList(cache, item); | 639 ocsp_AddCacheItemToLinkedList(cache, item); |
643 *pCacheItem = item; | 640 *pCacheItem = item; |
644 | 641 |
645 PR_ExitMonitor(OCSP_Global.monitor); | 642 PR_ExitMonitor(OCSP_Global.monitor); |
646 return SECSuccess; | 643 return SECSuccess; |
647 | 644 |
648 loser: | 645 loser: |
649 PORT_ArenaRelease(arena, mark); | 646 PORT_ArenaRelease(arena, mark); |
650 PR_ExitMonitor(OCSP_Global.monitor); | 647 PR_ExitMonitor(OCSP_Global.monitor); |
651 return SECFailure; | 648 return SECFailure; |
652 } | 649 } |
653 | 650 |
654 static SECStatus | 651 static SECStatus |
655 ocsp_SetCacheItemResponse(OCSPCacheItem *item, | 652 ocsp_SetCacheItemResponse(OCSPCacheItem *item, |
656 const CERTOCSPSingleResponse *response) | 653 const CERTOCSPSingleResponse *response) |
657 { | 654 { |
658 if (item->certStatusArena) { | 655 if (item->certStatusArena) { |
659 PORT_FreeArena(item->certStatusArena, PR_FALSE); | 656 PORT_FreeArena(item->certStatusArena, PR_FALSE); |
660 item->certStatusArena = NULL; | 657 item->certStatusArena = NULL; |
661 } | 658 } |
662 item->haveThisUpdate = item->haveNextUpdate = PR_FALSE; | 659 item->haveThisUpdate = item->haveNextUpdate = PR_FALSE; |
663 if (response) { | 660 if (response) { |
664 SECStatus rv; | 661 SECStatus rv; |
665 item->certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 662 item->certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
666 if (item->certStatusArena == NULL) { | 663 if (item->certStatusArena == NULL) { |
667 return SECFailure; | 664 return SECFailure; |
668 } | 665 } |
669 rv = ocsp_CopyCertStatus(item->certStatusArena, &item->certStatus, | 666 rv = ocsp_CopyCertStatus(item->certStatusArena, &item->certStatus, |
670 response->certStatus); | 667 response->certStatus); |
671 if (rv != SECSuccess) { | 668 if (rv != SECSuccess) { |
672 PORT_FreeArena(item->certStatusArena, PR_FALSE); | 669 PORT_FreeArena(item->certStatusArena, PR_FALSE); |
673 item->certStatusArena = NULL; | 670 item->certStatusArena = NULL; |
674 return rv; | 671 return rv; |
675 } | 672 } |
676 item->missingResponseError = 0; | 673 item->missingResponseError = 0; |
677 rv = DER_GeneralizedTimeToTime(&item->thisUpdate, | 674 rv = DER_GeneralizedTimeToTime(&item->thisUpdate, |
678 &response->thisUpdate); | 675 &response->thisUpdate); |
679 item->haveThisUpdate = (rv == SECSuccess); | 676 item->haveThisUpdate = (rv == SECSuccess); |
680 if (response->nextUpdate) { | 677 if (response->nextUpdate) { |
681 rv = DER_GeneralizedTimeToTime(&item->nextUpdate, | 678 rv = DER_GeneralizedTimeToTime(&item->nextUpdate, |
682 response->nextUpdate); | 679 response->nextUpdate); |
683 item->haveNextUpdate = (rv == SECSuccess); | 680 item->haveNextUpdate = (rv == SECSuccess); |
684 } else { | 681 } else { |
685 item->haveNextUpdate = PR_FALSE; | 682 item->haveNextUpdate = PR_FALSE; |
686 } | 683 } |
687 } | 684 } |
688 return SECSuccess; | 685 return SECSuccess; |
689 } | 686 } |
690 | 687 |
691 static void | 688 static void |
692 ocsp_FreshenCacheItemNextFetchAttemptTime(OCSPCacheItem *cacheItem) | 689 ocsp_FreshenCacheItemNextFetchAttemptTime(OCSPCacheItem *cacheItem) |
693 { | 690 { |
694 PRTime now; | 691 PRTime now; |
695 PRTime earliestAllowedNextFetchAttemptTime; | 692 PRTime earliestAllowedNextFetchAttemptTime; |
696 PRTime latestTimeWhenResponseIsConsideredFresh; | 693 PRTime latestTimeWhenResponseIsConsideredFresh; |
697 | 694 |
698 OCSP_TRACE(("OCSP ocsp_FreshenCacheItemNextFetchAttemptTime\n")); | 695 OCSP_TRACE(("OCSP ocsp_FreshenCacheItemNextFetchAttemptTime\n")); |
699 | 696 |
700 PR_EnterMonitor(OCSP_Global.monitor); | 697 PR_EnterMonitor(OCSP_Global.monitor); |
701 | 698 |
702 now = PR_Now(); | 699 now = PR_Now(); |
703 OCSP_TRACE_TIME("now:", now); | 700 OCSP_TRACE_TIME("now:", now); |
704 | 701 |
705 if (cacheItem->haveThisUpdate) { | 702 if (cacheItem->haveThisUpdate) { |
706 OCSP_TRACE_TIME("thisUpdate:", cacheItem->thisUpdate); | 703 OCSP_TRACE_TIME("thisUpdate:", cacheItem->thisUpdate); |
707 latestTimeWhenResponseIsConsideredFresh = cacheItem->thisUpdate + | 704 latestTimeWhenResponseIsConsideredFresh = cacheItem->thisUpdate + |
708 OCSP_Global.maximumSecondsToNextFetchAttempt * | 705 OCSP_Global.maximumSecondsToNe
xtFetchAttempt * |
709 MICROSECONDS_PER_SECOND; | 706 MICROSECONDS_PER_SECOND; |
710 OCSP_TRACE_TIME("latestTimeWhenResponseIsConsideredFresh:", | 707 OCSP_TRACE_TIME("latestTimeWhenResponseIsConsideredFresh:", |
711 latestTimeWhenResponseIsConsideredFresh); | 708 latestTimeWhenResponseIsConsideredFresh); |
712 } else { | 709 } else { |
713 latestTimeWhenResponseIsConsideredFresh = now + | 710 latestTimeWhenResponseIsConsideredFresh = now + |
714 OCSP_Global.minimumSecondsToNextFetchAttempt * | 711 OCSP_Global.minimumSecondsToNe
xtFetchAttempt * |
715 MICROSECONDS_PER_SECOND; | 712 MICROSECONDS_PER_SECOND; |
716 OCSP_TRACE_TIME("no thisUpdate, " | 713 OCSP_TRACE_TIME("no thisUpdate, " |
717 "latestTimeWhenResponseIsConsideredFresh:", | 714 "latestTimeWhenResponseIsConsideredFresh:", |
718 latestTimeWhenResponseIsConsideredFresh); | 715 latestTimeWhenResponseIsConsideredFresh); |
719 } | 716 } |
720 | 717 |
721 if (cacheItem->haveNextUpdate) { | 718 if (cacheItem->haveNextUpdate) { |
722 OCSP_TRACE_TIME("have nextUpdate:", cacheItem->nextUpdate); | 719 OCSP_TRACE_TIME("have nextUpdate:", cacheItem->nextUpdate); |
723 } | 720 } |
724 | 721 |
725 if (cacheItem->haveNextUpdate && | 722 if (cacheItem->haveNextUpdate && |
726 cacheItem->nextUpdate < latestTimeWhenResponseIsConsideredFresh) { | 723 cacheItem->nextUpdate < latestTimeWhenResponseIsConsideredFresh) { |
727 latestTimeWhenResponseIsConsideredFresh = cacheItem->nextUpdate; | 724 latestTimeWhenResponseIsConsideredFresh = cacheItem->nextUpdate; |
728 OCSP_TRACE_TIME("nextUpdate is smaller than latestFresh, setting " | 725 OCSP_TRACE_TIME("nextUpdate is smaller than latestFresh, setting " |
729 "latestTimeWhenResponseIsConsideredFresh:", | 726 "latestTimeWhenResponseIsConsideredFresh:", |
730 latestTimeWhenResponseIsConsideredFresh); | 727 latestTimeWhenResponseIsConsideredFresh); |
731 } | 728 } |
732 | 729 |
733 earliestAllowedNextFetchAttemptTime = now + | 730 earliestAllowedNextFetchAttemptTime = now + |
734 OCSP_Global.minimumSecondsToNextFetchAttempt * | 731 OCSP_Global.minimumSecondsToNextFetchA
ttempt * |
735 MICROSECONDS_PER_SECOND; | 732 MICROSECONDS_PER_SECOND; |
736 OCSP_TRACE_TIME("earliestAllowedNextFetchAttemptTime:", | 733 OCSP_TRACE_TIME("earliestAllowedNextFetchAttemptTime:", |
737 earliestAllowedNextFetchAttemptTime); | 734 earliestAllowedNextFetchAttemptTime); |
738 | 735 |
739 if (latestTimeWhenResponseIsConsideredFresh < | 736 if (latestTimeWhenResponseIsConsideredFresh < |
740 earliestAllowedNextFetchAttemptTime) { | 737 earliestAllowedNextFetchAttemptTime) { |
741 latestTimeWhenResponseIsConsideredFresh = | 738 latestTimeWhenResponseIsConsideredFresh = |
742 earliestAllowedNextFetchAttemptTime; | 739 earliestAllowedNextFetchAttemptTime; |
743 OCSP_TRACE_TIME("latest < earliest, setting latest to:", | 740 OCSP_TRACE_TIME("latest < earliest, setting latest to:", |
744 latestTimeWhenResponseIsConsideredFresh); | 741 latestTimeWhenResponseIsConsideredFresh); |
745 } | 742 } |
746 | 743 |
747 cacheItem->nextFetchAttemptTime = | 744 cacheItem->nextFetchAttemptTime = |
748 latestTimeWhenResponseIsConsideredFresh; | 745 latestTimeWhenResponseIsConsideredFresh; |
749 OCSP_TRACE_TIME("nextFetchAttemptTime", | 746 OCSP_TRACE_TIME("nextFetchAttemptTime", |
750 latestTimeWhenResponseIsConsideredFresh); | 747 latestTimeWhenResponseIsConsideredFresh); |
751 | 748 |
752 PR_ExitMonitor(OCSP_Global.monitor); | 749 PR_ExitMonitor(OCSP_Global.monitor); |
753 } | 750 } |
754 | 751 |
755 static PRBool | 752 static PRBool |
756 ocsp_IsCacheItemFresh(OCSPCacheItem *cacheItem) | 753 ocsp_IsCacheItemFresh(OCSPCacheItem *cacheItem) |
757 { | 754 { |
758 PRTime now; | 755 PRTime now; |
759 PRBool fresh; | 756 PRBool fresh; |
760 | 757 |
761 now = PR_Now(); | 758 now = PR_Now(); |
762 | 759 |
763 fresh = cacheItem->nextFetchAttemptTime > now; | 760 fresh = cacheItem->nextFetchAttemptTime > now; |
764 | 761 |
765 /* Work around broken OCSP responders that return unknown responses for | 762 /* Work around broken OCSP responders that return unknown responses for |
766 * certificates, especially certificates that were just recently issued. | 763 * certificates, especially certificates that were just recently issued. |
767 */ | 764 */ |
768 if (fresh && cacheItem->certStatusArena && | 765 if (fresh && cacheItem->certStatusArena && |
769 cacheItem->certStatus.certStatusType == ocspCertStatus_unknown) { | 766 cacheItem->certStatus.certStatusType == ocspCertStatus_unknown) { |
770 fresh = PR_FALSE; | 767 fresh = PR_FALSE; |
771 } | 768 } |
772 | 769 |
773 OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", fresh)); | 770 OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", fresh)); |
774 | 771 |
775 return fresh; | 772 return fresh; |
776 } | 773 } |
777 | 774 |
778 /* | 775 /* |
779 * Status in *certIDWasConsumed will always be correct, regardless of | 776 * Status in *certIDWasConsumed will always be correct, regardless of |
780 * return value. | 777 * return value. |
781 * If the caller is unable to transfer ownership of certID, | 778 * If the caller is unable to transfer ownership of certID, |
782 * then the caller must set certIDWasConsumed to NULL, | 779 * then the caller must set certIDWasConsumed to NULL, |
783 * and this function will potentially duplicate the certID object. | 780 * and this function will potentially duplicate the certID object. |
784 */ | 781 */ |
785 static SECStatus | 782 static SECStatus |
786 ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache, | 783 ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache, |
787 CERTOCSPCertID *certID, | 784 CERTOCSPCertID *certID, |
788 CERTOCSPSingleResponse *single, | 785 CERTOCSPSingleResponse *single, |
789 PRBool *certIDWasConsumed) | 786 PRBool *certIDWasConsumed) |
790 { | 787 { |
791 SECStatus rv; | 788 SECStatus rv; |
792 OCSPCacheItem *cacheItem; | 789 OCSPCacheItem *cacheItem; |
793 OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n")); | 790 OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n")); |
794 | 791 |
795 if (certIDWasConsumed) | 792 if (certIDWasConsumed) |
796 *certIDWasConsumed = PR_FALSE; | 793 *certIDWasConsumed = PR_FALSE; |
797 | 794 |
798 PR_EnterMonitor(OCSP_Global.monitor); | 795 PR_EnterMonitor(OCSP_Global.monitor); |
799 PORT_Assert(OCSP_Global.maxCacheEntries >= 0); | 796 PORT_Assert(OCSP_Global.maxCacheEntries >= 0); |
800 | 797 |
801 cacheItem = ocsp_FindCacheEntry(cache, certID); | 798 cacheItem = ocsp_FindCacheEntry(cache, certID); |
802 | 799 |
803 /* Don't replace an unknown or revoked entry with an error entry, even if | 800 /* Don't replace an unknown or revoked entry with an error entry, even if |
804 * the existing entry is expired. Instead, we'll continue to use the | 801 * the existing entry is expired. Instead, we'll continue to use the |
805 * existing (possibly expired) cache entry until we receive a valid signed | 802 * existing (possibly expired) cache entry until we receive a valid signed |
806 * response to replace it. | 803 * response to replace it. |
807 */ | 804 */ |
808 if (!single && cacheItem && cacheItem->certStatusArena && | 805 if (!single && cacheItem && cacheItem->certStatusArena && |
809 (cacheItem->certStatus.certStatusType == ocspCertStatus_revoked || | 806 (cacheItem->certStatus.certStatusType == ocspCertStatus_revoked || |
810 cacheItem->certStatus.certStatusType == ocspCertStatus_unknown)) { | 807 cacheItem->certStatus.certStatusType == ocspCertStatus_unknown)) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 ocsp_CheckCacheSize(cache); | 857 ocsp_CheckCacheSize(cache); |
861 | 858 |
862 PR_ExitMonitor(OCSP_Global.monitor); | 859 PR_ExitMonitor(OCSP_Global.monitor); |
863 return SECSuccess; | 860 return SECSuccess; |
864 } | 861 } |
865 | 862 |
866 extern SECStatus | 863 extern SECStatus |
867 CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode) | 864 CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode) |
868 { | 865 { |
869 switch (ocspFailureMode) { | 866 switch (ocspFailureMode) { |
870 case ocspMode_FailureIsVerificationFailure: | 867 case ocspMode_FailureIsVerificationFailure: |
871 case ocspMode_FailureIsNotAVerificationFailure: | 868 case ocspMode_FailureIsNotAVerificationFailure: |
872 break; | 869 break; |
873 default: | 870 default: |
874 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 871 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
875 return SECFailure; | 872 return SECFailure; |
876 } | 873 } |
877 | 874 |
878 PR_EnterMonitor(OCSP_Global.monitor); | 875 PR_EnterMonitor(OCSP_Global.monitor); |
879 OCSP_Global.ocspFailureMode = ocspFailureMode; | 876 OCSP_Global.ocspFailureMode = ocspFailureMode; |
880 PR_ExitMonitor(OCSP_Global.monitor); | 877 PR_ExitMonitor(OCSP_Global.monitor); |
881 return SECSuccess; | 878 return SECSuccess; |
882 } | 879 } |
883 | 880 |
884 SECStatus | 881 SECStatus |
885 CERT_OCSPCacheSettings(PRInt32 maxCacheEntries, | 882 CERT_OCSPCacheSettings(PRInt32 maxCacheEntries, |
886 PRUint32 minimumSecondsToNextFetchAttempt, | 883 PRUint32 minimumSecondsToNextFetchAttempt, |
887 PRUint32 maximumSecondsToNextFetchAttempt) | 884 PRUint32 maximumSecondsToNextFetchAttempt) |
888 { | 885 { |
889 if (minimumSecondsToNextFetchAttempt > maximumSecondsToNextFetchAttempt | 886 if (minimumSecondsToNextFetchAttempt > maximumSecondsToNextFetchAttempt || |
890 || maxCacheEntries < -1) { | 887 maxCacheEntries < -1) { |
891 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 888 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
892 return SECFailure; | 889 return SECFailure; |
893 } | 890 } |
894 | 891 |
895 PR_EnterMonitor(OCSP_Global.monitor); | 892 PR_EnterMonitor(OCSP_Global.monitor); |
896 | 893 |
897 if (maxCacheEntries < 0) { | 894 if (maxCacheEntries < 0) { |
898 OCSP_Global.maxCacheEntries = -1; /* disable cache */ | 895 OCSP_Global.maxCacheEntries = -1; /* disable cache */ |
899 } else if (maxCacheEntries == 0) { | 896 } else if (maxCacheEntries == 0) { |
900 OCSP_Global.maxCacheEntries = 0; /* unlimited cache entries */ | 897 OCSP_Global.maxCacheEntries = 0; /* unlimited cache entries */ |
901 } else { | 898 } else { |
902 OCSP_Global.maxCacheEntries = maxCacheEntries; | 899 OCSP_Global.maxCacheEntries = maxCacheEntries; |
903 } | 900 } |
904 | 901 |
905 if (minimumSecondsToNextFetchAttempt < | 902 if (minimumSecondsToNextFetchAttempt < |
906 OCSP_Global.minimumSecondsToNextFetchAttempt | 903 OCSP_Global.minimumSecondsToNextFetchAttempt || |
907 || maximumSecondsToNextFetchAttempt < | 904 maximumSecondsToNextFetchAttempt < |
908 OCSP_Global.maximumSecondsToNextFetchAttempt) { | 905 OCSP_Global.maximumSecondsToNextFetchAttempt) { |
909 /* | 906 /* |
910 * Ensure our existing cache entries are not used longer than the | 907 * Ensure our existing cache entries are not used longer than the |
911 * new settings allow, we're lazy and just clear the cache | 908 * new settings allow, we're lazy and just clear the cache |
912 */ | 909 */ |
913 CERT_ClearOCSPCache(); | 910 CERT_ClearOCSPCache(); |
914 } | 911 } |
915 | 912 |
916 OCSP_Global.minimumSecondsToNextFetchAttempt = | 913 OCSP_Global.minimumSecondsToNextFetchAttempt = |
917 minimumSecondsToNextFetchAttempt; | 914 minimumSecondsToNextFetchAttempt; |
918 OCSP_Global.maximumSecondsToNextFetchAttempt = | 915 OCSP_Global.maximumSecondsToNextFetchAttempt = |
919 maximumSecondsToNextFetchAttempt; | 916 maximumSecondsToNextFetchAttempt; |
920 ocsp_CheckCacheSize(&OCSP_Global.cache); | 917 ocsp_CheckCacheSize(&OCSP_Global.cache); |
921 | 918 |
922 PR_ExitMonitor(OCSP_Global.monitor); | 919 PR_ExitMonitor(OCSP_Global.monitor); |
923 return SECSuccess; | 920 return SECSuccess; |
924 } | 921 } |
925 | 922 |
926 SECStatus | 923 SECStatus |
927 CERT_SetOCSPTimeout(PRUint32 seconds) | 924 CERT_SetOCSPTimeout(PRUint32 seconds) |
928 { | 925 { |
929 /* no locking, see bug 406120 */ | 926 /* no locking, see bug 406120 */ |
930 OCSP_Global.timeoutSeconds = seconds; | 927 OCSP_Global.timeoutSeconds = seconds; |
931 return SECSuccess; | 928 return SECSuccess; |
932 } | 929 } |
933 | 930 |
934 /* this function is called at NSS initialization time */ | 931 /* this function is called at NSS initialization time */ |
935 SECStatus OCSP_InitGlobal(void) | 932 SECStatus |
| 933 OCSP_InitGlobal(void) |
936 { | 934 { |
937 SECStatus rv = SECFailure; | 935 SECStatus rv = SECFailure; |
938 | 936 |
939 if (OCSP_Global.monitor == NULL) { | 937 if (OCSP_Global.monitor == NULL) { |
940 OCSP_Global.monitor = PR_NewMonitor(); | 938 OCSP_Global.monitor = PR_NewMonitor(); |
941 } | 939 } |
942 if (!OCSP_Global.monitor) | 940 if (!OCSP_Global.monitor) |
943 return SECFailure; | 941 return SECFailure; |
944 | 942 |
945 PR_EnterMonitor(OCSP_Global.monitor); | 943 PR_EnterMonitor(OCSP_Global.monitor); |
946 if (!OCSP_Global.cache.entries) { | 944 if (!OCSP_Global.cache.entries) { |
947 OCSP_Global.cache.entries = | 945 OCSP_Global.cache.entries = |
948 PL_NewHashTable(0, | 946 PL_NewHashTable(0, |
949 ocsp_CacheKeyHashFunction, | 947 ocsp_CacheKeyHashFunction, |
950 ocsp_CacheKeyCompareFunction, | 948 ocsp_CacheKeyCompareFunction, |
951 PL_CompareValues, | 949 PL_CompareValues, |
952 NULL, | 950 NULL, |
953 NULL); | 951 NULL); |
954 OCSP_Global.ocspFailureMode = ocspMode_FailureIsVerificationFailure; | 952 OCSP_Global.ocspFailureMode = ocspMode_FailureIsVerificationFailure; |
955 OCSP_Global.cache.numberOfEntries = 0; | 953 OCSP_Global.cache.numberOfEntries = 0; |
956 OCSP_Global.cache.MRUitem = NULL; | 954 OCSP_Global.cache.MRUitem = NULL; |
957 OCSP_Global.cache.LRUitem = NULL; | 955 OCSP_Global.cache.LRUitem = NULL; |
958 } else { | 956 } else { |
959 /* | 957 /* |
960 * NSS might call this function twice while attempting to init. | 958 * NSS might call this function twice while attempting to init. |
961 * But it's not allowed to call this again after any activity. | 959 * But it's not allowed to call this again after any activity. |
962 */ | 960 */ |
963 PORT_Assert(OCSP_Global.cache.numberOfEntries == 0); | 961 PORT_Assert(OCSP_Global.cache.numberOfEntries == 0); |
964 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 962 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
965 } | 963 } |
966 if (OCSP_Global.cache.entries) | 964 if (OCSP_Global.cache.entries) |
967 rv = SECSuccess; | 965 rv = SECSuccess; |
968 PR_ExitMonitor(OCSP_Global.monitor); | 966 PR_ExitMonitor(OCSP_Global.monitor); |
969 return rv; | 967 return rv; |
970 } | 968 } |
971 | 969 |
972 SECStatus OCSP_ShutdownGlobal(void) | 970 SECStatus |
| 971 OCSP_ShutdownGlobal(void) |
973 { | 972 { |
974 if (!OCSP_Global.monitor) | 973 if (!OCSP_Global.monitor) |
975 return SECSuccess; | 974 return SECSuccess; |
976 | 975 |
977 PR_EnterMonitor(OCSP_Global.monitor); | 976 PR_EnterMonitor(OCSP_Global.monitor); |
978 if (OCSP_Global.cache.entries) { | 977 if (OCSP_Global.cache.entries) { |
979 CERT_ClearOCSPCache(); | 978 CERT_ClearOCSPCache(); |
980 PL_HashTableDestroy(OCSP_Global.cache.entries); | 979 PL_HashTableDestroy(OCSP_Global.cache.entries); |
981 OCSP_Global.cache.entries = NULL; | 980 OCSP_Global.cache.entries = NULL; |
982 } | 981 } |
983 PORT_Assert(OCSP_Global.cache.numberOfEntries == 0); | 982 PORT_Assert(OCSP_Global.cache.numberOfEntries == 0); |
984 OCSP_Global.cache.MRUitem = NULL; | 983 OCSP_Global.cache.MRUitem = NULL; |
985 OCSP_Global.cache.LRUitem = NULL; | 984 OCSP_Global.cache.LRUitem = NULL; |
986 | 985 |
987 OCSP_Global.defaultHttpClientFcn = NULL; | 986 OCSP_Global.defaultHttpClientFcn = NULL; |
988 OCSP_Global.maxCacheEntries = DEFAULT_OCSP_CACHE_SIZE; | 987 OCSP_Global.maxCacheEntries = DEFAULT_OCSP_CACHE_SIZE; |
989 OCSP_Global.minimumSecondsToNextFetchAttempt = | 988 OCSP_Global.minimumSecondsToNextFetchAttempt = |
990 DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT; | 989 DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT; |
991 OCSP_Global.maximumSecondsToNextFetchAttempt = | 990 OCSP_Global.maximumSecondsToNextFetchAttempt = |
992 DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT; | 991 DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT; |
993 OCSP_Global.ocspFailureMode = | 992 OCSP_Global.ocspFailureMode = |
994 ocspMode_FailureIsVerificationFailure; | 993 ocspMode_FailureIsVerificationFailure; |
995 PR_ExitMonitor(OCSP_Global.monitor); | 994 PR_ExitMonitor(OCSP_Global.monitor); |
996 | 995 |
997 PR_DestroyMonitor(OCSP_Global.monitor); | 996 PR_DestroyMonitor(OCSP_Global.monitor); |
998 OCSP_Global.monitor = NULL; | 997 OCSP_Global.monitor = NULL; |
999 return SECSuccess; | 998 return SECSuccess; |
1000 } | 999 } |
1001 | 1000 |
1002 /* | 1001 /* |
1003 * A return value of NULL means: | 1002 * A return value of NULL means: |
1004 * The application did not register it's own HTTP client. | 1003 * The application did not register it's own HTTP client. |
1005 */ | 1004 */ |
1006 const SEC_HttpClientFcn *SEC_GetRegisteredHttpClient(void) | 1005 const SEC_HttpClientFcn * |
| 1006 SEC_GetRegisteredHttpClient(void) |
1007 { | 1007 { |
1008 const SEC_HttpClientFcn *retval; | 1008 const SEC_HttpClientFcn *retval; |
1009 | 1009 |
1010 if (!OCSP_Global.monitor) { | 1010 if (!OCSP_Global.monitor) { |
1011 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); | 1011 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); |
1012 return NULL; | 1012 return NULL; |
1013 } | 1013 } |
1014 | 1014 |
1015 PR_EnterMonitor(OCSP_Global.monitor); | 1015 PR_EnterMonitor(OCSP_Global.monitor); |
1016 retval = OCSP_Global.defaultHttpClientFcn; | 1016 retval = OCSP_Global.defaultHttpClientFcn; |
1017 PR_ExitMonitor(OCSP_Global.monitor); | 1017 PR_ExitMonitor(OCSP_Global.monitor); |
1018 | 1018 |
1019 return retval; | 1019 return retval; |
1020 } | 1020 } |
1021 | 1021 |
1022 /* | 1022 /* |
1023 * The following structure is only used internally. It is allocated when | 1023 * The following structure is only used internally. It is allocated when |
1024 * someone turns on OCSP checking, and hangs off of the status-configuration | 1024 * someone turns on OCSP checking, and hangs off of the status-configuration |
1025 * structure in the certdb structure. We use it to keep configuration | 1025 * structure in the certdb structure. We use it to keep configuration |
1026 * information specific to OCSP checking. | 1026 * information specific to OCSP checking. |
1027 */ | 1027 */ |
1028 typedef struct ocspCheckingContextStr { | 1028 typedef struct ocspCheckingContextStr { |
(...skipping 21 matching lines...) Expand all Loading... |
1050 */ | 1050 */ |
1051 extern const SEC_ASN1Template ocsp_CertIDTemplate[]; | 1051 extern const SEC_ASN1Template ocsp_CertIDTemplate[]; |
1052 extern const SEC_ASN1Template ocsp_PointerToSignatureTemplate[]; | 1052 extern const SEC_ASN1Template ocsp_PointerToSignatureTemplate[]; |
1053 extern const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[]; | 1053 extern const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[]; |
1054 extern const SEC_ASN1Template ocsp_ResponseDataTemplate[]; | 1054 extern const SEC_ASN1Template ocsp_ResponseDataTemplate[]; |
1055 extern const SEC_ASN1Template ocsp_RevokedInfoTemplate[]; | 1055 extern const SEC_ASN1Template ocsp_RevokedInfoTemplate[]; |
1056 extern const SEC_ASN1Template ocsp_SingleRequestTemplate[]; | 1056 extern const SEC_ASN1Template ocsp_SingleRequestTemplate[]; |
1057 extern const SEC_ASN1Template ocsp_SingleResponseTemplate[]; | 1057 extern const SEC_ASN1Template ocsp_SingleResponseTemplate[]; |
1058 extern const SEC_ASN1Template ocsp_TBSRequestTemplate[]; | 1058 extern const SEC_ASN1Template ocsp_TBSRequestTemplate[]; |
1059 | 1059 |
1060 | |
1061 /* | 1060 /* |
1062 * Request-related templates... | 1061 * Request-related templates... |
1063 */ | 1062 */ |
1064 | 1063 |
1065 /* | 1064 /* |
1066 * OCSPRequest ::= SEQUENCE { | 1065 * OCSPRequest ::= SEQUENCE { |
1067 * tbsRequest TBSRequest, | 1066 * tbsRequest TBSRequest, |
1068 * optionalSignature [0] EXPLICIT Signature OPTIONAL } | 1067 * optionalSignature [0] EXPLICIT Signature OPTIONAL } |
1069 */ | 1068 */ |
1070 static const SEC_ASN1Template ocsp_OCSPRequestTemplate[] = { | 1069 static const SEC_ASN1Template ocsp_OCSPRequestTemplate[] = { |
1071 { SEC_ASN1_SEQUENCE, | 1070 { SEC_ASN1_SEQUENCE, |
1072 » 0, NULL, sizeof(CERTOCSPRequest) }, | 1071 0, NULL, sizeof(CERTOCSPRequest) }, |
1073 { SEC_ASN1_POINTER, | 1072 { SEC_ASN1_POINTER, |
1074 » offsetof(CERTOCSPRequest, tbsRequest), | 1073 offsetof(CERTOCSPRequest, tbsRequest), |
1075 » ocsp_TBSRequestTemplate }, | 1074 ocsp_TBSRequestTemplate }, |
1076 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1075 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1077 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | 1076 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, |
1078 » offsetof(CERTOCSPRequest, optionalSignature), | 1077 offsetof(CERTOCSPRequest, optionalSignature), |
1079 » ocsp_PointerToSignatureTemplate }, | 1078 ocsp_PointerToSignatureTemplate }, |
1080 { 0 } | 1079 { 0 } |
1081 }; | 1080 }; |
1082 | 1081 |
1083 /* | 1082 /* |
1084 * TBSRequest ::= SEQUENCE { | 1083 * TBSRequest ::= SEQUENCE { |
1085 * version [0] EXPLICIT Version DEFAULT v1, | 1084 * version [0] EXPLICIT Version DEFAULT v1, |
1086 * requestorName [1] EXPLICIT GeneralName OPTIONAL, | 1085 * requestorName [1] EXPLICIT GeneralName OPTIONAL, |
1087 * requestList SEQUENCE OF Request, | 1086 * requestList SEQUENCE OF Request, |
1088 * requestExtensions [2] EXPLICIT Extensions OPTIONAL } | 1087 * requestExtensions [2] EXPLICIT Extensions OPTIONAL } |
1089 * | 1088 * |
1090 * Version ::= INTEGER { v1(0) } | 1089 * Version ::= INTEGER { v1(0) } |
1091 * | 1090 * |
1092 * Note: this should be static but the AIX compiler doesn't like it (because it | 1091 * Note: this should be static but the AIX compiler doesn't like it (because it |
1093 * was forward-declared above); it is not meant to be exported, but this | 1092 * was forward-declared above); it is not meant to be exported, but this |
1094 * is the only way it will compile. | 1093 * is the only way it will compile. |
1095 */ | 1094 */ |
1096 const SEC_ASN1Template ocsp_TBSRequestTemplate[] = { | 1095 const SEC_ASN1Template ocsp_TBSRequestTemplate[] = { |
1097 { SEC_ASN1_SEQUENCE, | 1096 { SEC_ASN1_SEQUENCE, |
1098 » 0, NULL, sizeof(ocspTBSRequest) }, | 1097 0, NULL, sizeof(ocspTBSRequest) }, |
1099 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |» » /* XXX DER_DEFAULT */ | 1098 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */ |
1100 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | 1099 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
1101 » offsetof(ocspTBSRequest, version), | 1100 offsetof(ocspTBSRequest, version), |
1102 » SEC_ASN1_SUB(SEC_IntegerTemplate) }, | 1101 SEC_ASN1_SUB(SEC_IntegerTemplate) }, |
1103 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1102 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1104 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, | 1103 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, |
1105 » offsetof(ocspTBSRequest, derRequestorName), | 1104 offsetof(ocspTBSRequest, derRequestorName), |
1106 » SEC_ASN1_SUB(SEC_PointerToAnyTemplate) }, | 1105 SEC_ASN1_SUB(SEC_PointerToAnyTemplate) }, |
1107 { SEC_ASN1_SEQUENCE_OF, | 1106 { SEC_ASN1_SEQUENCE_OF, |
1108 » offsetof(ocspTBSRequest, requestList), | 1107 offsetof(ocspTBSRequest, requestList), |
1109 » ocsp_SingleRequestTemplate }, | 1108 ocsp_SingleRequestTemplate }, |
1110 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1109 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1111 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2, | 1110 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2, |
1112 » offsetof(ocspTBSRequest, requestExtensions), | 1111 offsetof(ocspTBSRequest, requestExtensions), |
1113 » CERT_SequenceOfCertExtensionTemplate }, | 1112 CERT_SequenceOfCertExtensionTemplate }, |
1114 { 0 } | 1113 { 0 } |
1115 }; | 1114 }; |
1116 | 1115 |
1117 /* | 1116 /* |
1118 * Signature ::= SEQUENCE { | 1117 * Signature ::= SEQUENCE { |
1119 * signatureAlgorithm AlgorithmIdentifier, | 1118 * signatureAlgorithm AlgorithmIdentifier, |
1120 * signature BIT STRING, | 1119 * signature BIT STRING, |
1121 * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } | 1120 * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } |
1122 */ | 1121 */ |
1123 static const SEC_ASN1Template ocsp_SignatureTemplate[] = { | 1122 static const SEC_ASN1Template ocsp_SignatureTemplate[] = { |
1124 { SEC_ASN1_SEQUENCE, | 1123 { SEC_ASN1_SEQUENCE, |
1125 » 0, NULL, sizeof(ocspSignature) }, | 1124 0, NULL, sizeof(ocspSignature) }, |
1126 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | 1125 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
1127 » offsetof(ocspSignature, signatureAlgorithm), | 1126 offsetof(ocspSignature, signatureAlgorithm), |
1128 » SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | 1127 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
1129 { SEC_ASN1_BIT_STRING, | 1128 { SEC_ASN1_BIT_STRING, |
1130 » offsetof(ocspSignature, signature) }, | 1129 offsetof(ocspSignature, signature) }, |
1131 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1130 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1132 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | 1131 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
1133 » offsetof(ocspSignature, derCerts), | 1132 offsetof(ocspSignature, derCerts), |
1134 » SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) }, | 1133 SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) }, |
1135 { 0 } | 1134 { 0 } |
1136 }; | 1135 }; |
1137 | 1136 |
1138 /* | 1137 /* |
1139 * This template is just an extra level to use in an explicitly-tagged | 1138 * This template is just an extra level to use in an explicitly-tagged |
1140 * reference to a Signature. | 1139 * reference to a Signature. |
1141 * | 1140 * |
1142 * Note: this should be static but the AIX compiler doesn't like it (because it | 1141 * Note: this should be static but the AIX compiler doesn't like it (because it |
1143 * was forward-declared above); it is not meant to be exported, but this | 1142 * was forward-declared above); it is not meant to be exported, but this |
1144 * is the only way it will compile. | 1143 * is the only way it will compile. |
1145 */ | 1144 */ |
1146 const SEC_ASN1Template ocsp_PointerToSignatureTemplate[] = { | 1145 const SEC_ASN1Template ocsp_PointerToSignatureTemplate[] = { |
1147 { SEC_ASN1_POINTER, 0, ocsp_SignatureTemplate } | 1146 { SEC_ASN1_POINTER, 0, ocsp_SignatureTemplate } |
1148 }; | 1147 }; |
1149 | 1148 |
1150 /* | 1149 /* |
1151 * Request ::= SEQUENCE { | 1150 * Request ::= SEQUENCE { |
1152 * reqCert CertID, | 1151 * reqCert CertID, |
1153 * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } | 1152 * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } |
1154 * | 1153 * |
1155 * Note: this should be static but the AIX compiler doesn't like it (because it | 1154 * Note: this should be static but the AIX compiler doesn't like it (because it |
1156 * was forward-declared above); it is not meant to be exported, but this | 1155 * was forward-declared above); it is not meant to be exported, but this |
1157 * is the only way it will compile. | 1156 * is the only way it will compile. |
1158 */ | 1157 */ |
1159 const SEC_ASN1Template ocsp_SingleRequestTemplate[] = { | 1158 const SEC_ASN1Template ocsp_SingleRequestTemplate[] = { |
1160 { SEC_ASN1_SEQUENCE, | 1159 { SEC_ASN1_SEQUENCE, |
1161 » 0, NULL, sizeof(ocspSingleRequest) }, | 1160 0, NULL, sizeof(ocspSingleRequest) }, |
1162 { SEC_ASN1_POINTER, | 1161 { SEC_ASN1_POINTER, |
1163 » offsetof(ocspSingleRequest, reqCert), | 1162 offsetof(ocspSingleRequest, reqCert), |
1164 » ocsp_CertIDTemplate }, | 1163 ocsp_CertIDTemplate }, |
1165 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1164 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1166 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | 1165 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, |
1167 » offsetof(ocspSingleRequest, singleRequestExtensions), | 1166 offsetof(ocspSingleRequest, singleRequestExtensions), |
1168 » CERT_SequenceOfCertExtensionTemplate }, | 1167 CERT_SequenceOfCertExtensionTemplate }, |
1169 { 0 } | 1168 { 0 } |
1170 }; | 1169 }; |
1171 | 1170 |
1172 | |
1173 /* | 1171 /* |
1174 * This data structure and template (CertID) is used by both OCSP | 1172 * This data structure and template (CertID) is used by both OCSP |
1175 * requests and responses. It is the only one that is shared. | 1173 * requests and responses. It is the only one that is shared. |
1176 * | 1174 * |
1177 * CertID ::= SEQUENCE { | 1175 * CertID ::= SEQUENCE { |
1178 * hashAlgorithm AlgorithmIdentifier, | 1176 * hashAlgorithm AlgorithmIdentifier, |
1179 * issuerNameHash OCTET STRING, -- Hash of Issuer DN | 1177 * issuerNameHash OCTET STRING, -- Hash of Issuer DN |
1180 * issuerKeyHash OCTET STRING, -- Hash of Issuer public key | 1178 * issuerKeyHash OCTET STRING, -- Hash of Issuer public key |
1181 * serialNumber CertificateSerialNumber } | 1179 * serialNumber CertificateSerialNumber } |
1182 * | 1180 * |
1183 * CertificateSerialNumber ::= INTEGER | 1181 * CertificateSerialNumber ::= INTEGER |
1184 * | 1182 * |
1185 * Note: this should be static but the AIX compiler doesn't like it (because it | 1183 * Note: this should be static but the AIX compiler doesn't like it (because it |
1186 * was forward-declared above); it is not meant to be exported, but this | 1184 * was forward-declared above); it is not meant to be exported, but this |
1187 * is the only way it will compile. | 1185 * is the only way it will compile. |
1188 */ | 1186 */ |
1189 const SEC_ASN1Template ocsp_CertIDTemplate[] = { | 1187 const SEC_ASN1Template ocsp_CertIDTemplate[] = { |
1190 { SEC_ASN1_SEQUENCE, | 1188 { SEC_ASN1_SEQUENCE, |
1191 » 0, NULL, sizeof(CERTOCSPCertID) }, | 1189 0, NULL, sizeof(CERTOCSPCertID) }, |
1192 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | 1190 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
1193 » offsetof(CERTOCSPCertID, hashAlgorithm), | 1191 offsetof(CERTOCSPCertID, hashAlgorithm), |
1194 » SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | 1192 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
1195 { SEC_ASN1_OCTET_STRING, | 1193 { SEC_ASN1_OCTET_STRING, |
1196 » offsetof(CERTOCSPCertID, issuerNameHash) }, | 1194 offsetof(CERTOCSPCertID, issuerNameHash) }, |
1197 { SEC_ASN1_OCTET_STRING, | 1195 { SEC_ASN1_OCTET_STRING, |
1198 » offsetof(CERTOCSPCertID, issuerKeyHash) }, | 1196 offsetof(CERTOCSPCertID, issuerKeyHash) }, |
1199 { SEC_ASN1_INTEGER, | 1197 { SEC_ASN1_INTEGER, |
1200 » offsetof(CERTOCSPCertID, serialNumber) }, | 1198 offsetof(CERTOCSPCertID, serialNumber) }, |
1201 { 0 } | 1199 { 0 } |
1202 }; | 1200 }; |
1203 | 1201 |
1204 | |
1205 /* | 1202 /* |
1206 * Response-related templates... | 1203 * Response-related templates... |
1207 */ | 1204 */ |
1208 | 1205 |
1209 /* | 1206 /* |
1210 * OCSPResponse ::= SEQUENCE { | 1207 * OCSPResponse ::= SEQUENCE { |
1211 * responseStatus OCSPResponseStatus, | 1208 * responseStatus OCSPResponseStatus, |
1212 * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } | 1209 * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } |
1213 */ | 1210 */ |
1214 const SEC_ASN1Template ocsp_OCSPResponseTemplate[] = { | 1211 const SEC_ASN1Template ocsp_OCSPResponseTemplate[] = { |
1215 { SEC_ASN1_SEQUENCE, | 1212 { SEC_ASN1_SEQUENCE, |
1216 » 0, NULL, sizeof(CERTOCSPResponse) }, | 1213 0, NULL, sizeof(CERTOCSPResponse) }, |
1217 { SEC_ASN1_ENUMERATED, | 1214 { SEC_ASN1_ENUMERATED, |
1218 » offsetof(CERTOCSPResponse, responseStatus) }, | 1215 offsetof(CERTOCSPResponse, responseStatus) }, |
1219 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1216 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1220 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | 1217 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, |
1221 » offsetof(CERTOCSPResponse, responseBytes), | 1218 offsetof(CERTOCSPResponse, responseBytes), |
1222 » ocsp_PointerToResponseBytesTemplate }, | 1219 ocsp_PointerToResponseBytesTemplate }, |
1223 { 0 } | 1220 { 0 } |
1224 }; | 1221 }; |
1225 | 1222 |
1226 /* | 1223 /* |
1227 * ResponseBytes ::= SEQUENCE { | 1224 * ResponseBytes ::= SEQUENCE { |
1228 * responseType OBJECT IDENTIFIER, | 1225 * responseType OBJECT IDENTIFIER, |
1229 * response OCTET STRING } | 1226 * response OCTET STRING } |
1230 */ | 1227 */ |
1231 const SEC_ASN1Template ocsp_ResponseBytesTemplate[] = { | 1228 const SEC_ASN1Template ocsp_ResponseBytesTemplate[] = { |
1232 { SEC_ASN1_SEQUENCE, | 1229 { SEC_ASN1_SEQUENCE, |
1233 » 0, NULL, sizeof(ocspResponseBytes) }, | 1230 0, NULL, sizeof(ocspResponseBytes) }, |
1234 { SEC_ASN1_OBJECT_ID, | 1231 { SEC_ASN1_OBJECT_ID, |
1235 » offsetof(ocspResponseBytes, responseType) }, | 1232 offsetof(ocspResponseBytes, responseType) }, |
1236 { SEC_ASN1_OCTET_STRING, | 1233 { SEC_ASN1_OCTET_STRING, |
1237 » offsetof(ocspResponseBytes, response) }, | 1234 offsetof(ocspResponseBytes, response) }, |
1238 { 0 } | 1235 { 0 } |
1239 }; | 1236 }; |
1240 | 1237 |
1241 /* | 1238 /* |
1242 * This template is just an extra level to use in an explicitly-tagged | 1239 * This template is just an extra level to use in an explicitly-tagged |
1243 * reference to a ResponseBytes. | 1240 * reference to a ResponseBytes. |
1244 * | 1241 * |
1245 * Note: this should be static but the AIX compiler doesn't like it (because it | 1242 * Note: this should be static but the AIX compiler doesn't like it (because it |
1246 * was forward-declared above); it is not meant to be exported, but this | 1243 * was forward-declared above); it is not meant to be exported, but this |
1247 * is the only way it will compile. | 1244 * is the only way it will compile. |
1248 */ | 1245 */ |
1249 const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[] = { | 1246 const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[] = { |
1250 { SEC_ASN1_POINTER, 0, ocsp_ResponseBytesTemplate } | 1247 { SEC_ASN1_POINTER, 0, ocsp_ResponseBytesTemplate } |
1251 }; | 1248 }; |
1252 | 1249 |
1253 /* | 1250 /* |
1254 * BasicOCSPResponse ::= SEQUENCE { | 1251 * BasicOCSPResponse ::= SEQUENCE { |
1255 * tbsResponseData ResponseData, | 1252 * tbsResponseData ResponseData, |
1256 * signatureAlgorithm AlgorithmIdentifier, | 1253 * signatureAlgorithm AlgorithmIdentifier, |
1257 * signature BIT STRING, | 1254 * signature BIT STRING, |
1258 * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } | 1255 * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } |
1259 */ | 1256 */ |
1260 static const SEC_ASN1Template ocsp_BasicOCSPResponseTemplate[] = { | 1257 static const SEC_ASN1Template ocsp_BasicOCSPResponseTemplate[] = { |
1261 { SEC_ASN1_SEQUENCE, | 1258 { SEC_ASN1_SEQUENCE, |
1262 » 0, NULL, sizeof(ocspBasicOCSPResponse) }, | 1259 0, NULL, sizeof(ocspBasicOCSPResponse) }, |
1263 { SEC_ASN1_ANY | SEC_ASN1_SAVE, | 1260 { SEC_ASN1_ANY | SEC_ASN1_SAVE, |
1264 » offsetof(ocspBasicOCSPResponse, tbsResponseDataDER) }, | 1261 offsetof(ocspBasicOCSPResponse, tbsResponseDataDER) }, |
1265 { SEC_ASN1_POINTER, | 1262 { SEC_ASN1_POINTER, |
1266 » offsetof(ocspBasicOCSPResponse, tbsResponseData), | 1263 offsetof(ocspBasicOCSPResponse, tbsResponseData), |
1267 » ocsp_ResponseDataTemplate }, | 1264 ocsp_ResponseDataTemplate }, |
1268 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | 1265 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
1269 » offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm), | 1266 offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm), |
1270 » SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | 1267 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
1271 { SEC_ASN1_BIT_STRING, | 1268 { SEC_ASN1_BIT_STRING, |
1272 » offsetof(ocspBasicOCSPResponse, responseSignature.signature) }, | 1269 offsetof(ocspBasicOCSPResponse, responseSignature.signature) }, |
1273 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1270 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1274 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | 1271 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
1275 » offsetof(ocspBasicOCSPResponse, responseSignature.derCerts), | 1272 offsetof(ocspBasicOCSPResponse, responseSignature.derCerts), |
1276 » SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) }, | 1273 SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) }, |
1277 { 0 } | 1274 { 0 } |
1278 }; | 1275 }; |
1279 | 1276 |
1280 /* | 1277 /* |
1281 * ResponseData ::= SEQUENCE { | 1278 * ResponseData ::= SEQUENCE { |
1282 * version [0] EXPLICIT Version DEFAULT v1, | 1279 * version [0] EXPLICIT Version DEFAULT v1, |
1283 * responderID ResponderID, | 1280 * responderID ResponderID, |
1284 * producedAt GeneralizedTime, | 1281 * producedAt GeneralizedTime, |
1285 * responses SEQUENCE OF SingleResponse, | 1282 * responses SEQUENCE OF SingleResponse, |
1286 * responseExtensions [1] EXPLICIT Extensions OPTIONAL } | 1283 * responseExtensions [1] EXPLICIT Extensions OPTIONAL } |
1287 * | 1284 * |
1288 * Note: this should be static but the AIX compiler doesn't like it (because it | 1285 * Note: this should be static but the AIX compiler doesn't like it (because it |
1289 * was forward-declared above); it is not meant to be exported, but this | 1286 * was forward-declared above); it is not meant to be exported, but this |
1290 * is the only way it will compile. | 1287 * is the only way it will compile. |
1291 */ | 1288 */ |
1292 const SEC_ASN1Template ocsp_ResponseDataTemplate[] = { | 1289 const SEC_ASN1Template ocsp_ResponseDataTemplate[] = { |
1293 { SEC_ASN1_SEQUENCE, | 1290 { SEC_ASN1_SEQUENCE, |
1294 » 0, NULL, sizeof(ocspResponseData) }, | 1291 0, NULL, sizeof(ocspResponseData) }, |
1295 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |» » /* XXX DER_DEFAULT */ | 1292 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */ |
1296 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | 1293 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
1297 » offsetof(ocspResponseData, version), | 1294 offsetof(ocspResponseData, version), |
1298 » SEC_ASN1_SUB(SEC_IntegerTemplate) }, | 1295 SEC_ASN1_SUB(SEC_IntegerTemplate) }, |
1299 { SEC_ASN1_ANY, | 1296 { SEC_ASN1_ANY, |
1300 » offsetof(ocspResponseData, derResponderID) }, | 1297 offsetof(ocspResponseData, derResponderID) }, |
1301 { SEC_ASN1_GENERALIZED_TIME, | 1298 { SEC_ASN1_GENERALIZED_TIME, |
1302 » offsetof(ocspResponseData, producedAt) }, | 1299 offsetof(ocspResponseData, producedAt) }, |
1303 { SEC_ASN1_SEQUENCE_OF, | 1300 { SEC_ASN1_SEQUENCE_OF, |
1304 » offsetof(ocspResponseData, responses), | 1301 offsetof(ocspResponseData, responses), |
1305 » ocsp_SingleResponseTemplate }, | 1302 ocsp_SingleResponseTemplate }, |
1306 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1303 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1307 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | 1304 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, |
1308 » offsetof(ocspResponseData, responseExtensions), | 1305 offsetof(ocspResponseData, responseExtensions), |
1309 » CERT_SequenceOfCertExtensionTemplate }, | 1306 CERT_SequenceOfCertExtensionTemplate }, |
1310 { 0 } | 1307 { 0 } |
1311 }; | 1308 }; |
1312 | 1309 |
1313 /* | 1310 /* |
1314 * ResponderID ::= CHOICE { | 1311 * ResponderID ::= CHOICE { |
1315 * byName [1] EXPLICIT Name, | 1312 * byName [1] EXPLICIT Name, |
1316 * byKey [2] EXPLICIT KeyHash } | 1313 * byKey [2] EXPLICIT KeyHash } |
1317 * | 1314 * |
1318 * KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key | 1315 * KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key |
1319 * (excluding the tag and length fields) | 1316 * (excluding the tag and length fields) |
1320 * | 1317 * |
1321 * XXX Because the ASN.1 encoder and decoder currently do not provide | 1318 * XXX Because the ASN.1 encoder and decoder currently do not provide |
1322 * a way to automatically handle a CHOICE, we need to do it in two | 1319 * a way to automatically handle a CHOICE, we need to do it in two |
1323 * steps, looking at the type tag and feeding the exact choice back | 1320 * steps, looking at the type tag and feeding the exact choice back |
1324 * to the ASN.1 code. Hopefully that will change someday and this | 1321 * to the ASN.1 code. Hopefully that will change someday and this |
1325 * can all be simplified down into a single template. Anyway, for | 1322 * can all be simplified down into a single template. Anyway, for |
1326 * now we list each choice as its own template: | 1323 * now we list each choice as its own template: |
1327 */ | 1324 */ |
1328 const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[] = { | 1325 const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[] = { |
1329 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | 1326 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, |
1330 » offsetof(ocspResponderID, responderIDValue.name), | 1327 offsetof(ocspResponderID, responderIDValue.name), |
1331 » CERT_NameTemplate } | 1328 CERT_NameTemplate } |
1332 }; | 1329 }; |
1333 const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[] = { | 1330 const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[] = { |
1334 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | | 1331 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | |
1335 SEC_ASN1_XTRN | 2, | 1332 SEC_ASN1_XTRN | 2, |
1336 » offsetof(ocspResponderID, responderIDValue.keyHash), | 1333 offsetof(ocspResponderID, responderIDValue.keyHash), |
1337 » SEC_ASN1_SUB(SEC_OctetStringTemplate) } | 1334 SEC_ASN1_SUB(SEC_OctetStringTemplate) } |
1338 }; | 1335 }; |
1339 static const SEC_ASN1Template ocsp_ResponderIDOtherTemplate[] = { | 1336 static const SEC_ASN1Template ocsp_ResponderIDOtherTemplate[] = { |
1340 { SEC_ASN1_ANY, | 1337 { SEC_ASN1_ANY, |
1341 » offsetof(ocspResponderID, responderIDValue.other) } | 1338 offsetof(ocspResponderID, responderIDValue.other) } |
1342 }; | 1339 }; |
1343 | 1340 |
1344 /* Decode choice container, but leave x509 name object encoded */ | 1341 /* Decode choice container, but leave x509 name object encoded */ |
1345 static const SEC_ASN1Template ocsp_ResponderIDDerNameTemplate[] = { | 1342 static const SEC_ASN1Template ocsp_ResponderIDDerNameTemplate[] = { |
1346 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | | 1343 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | |
1347 SEC_ASN1_XTRN | 1, 0, SEC_ASN1_SUB(SEC_AnyTemplate) } | 1344 SEC_ASN1_XTRN | 1, |
| 1345 0, SEC_ASN1_SUB(SEC_AnyTemplate) } |
1348 }; | 1346 }; |
1349 | 1347 |
1350 /* | 1348 /* |
1351 * SingleResponse ::= SEQUENCE { | 1349 * SingleResponse ::= SEQUENCE { |
1352 * certID CertID, | 1350 * certID CertID, |
1353 * certStatus CertStatus, | 1351 * certStatus CertStatus, |
1354 * thisUpdate GeneralizedTime, | 1352 * thisUpdate GeneralizedTime, |
1355 * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, | 1353 * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, |
1356 * singleExtensions [1] EXPLICIT Extensions OPTIONAL } | 1354 * singleExtensions [1] EXPLICIT Extensions OPTIONAL } |
1357 * | 1355 * |
1358 * Note: this should be static but the AIX compiler doesn't like it (because it | 1356 * Note: this should be static but the AIX compiler doesn't like it (because it |
1359 * was forward-declared above); it is not meant to be exported, but this | 1357 * was forward-declared above); it is not meant to be exported, but this |
1360 * is the only way it will compile. | 1358 * is the only way it will compile. |
1361 */ | 1359 */ |
1362 const SEC_ASN1Template ocsp_SingleResponseTemplate[] = { | 1360 const SEC_ASN1Template ocsp_SingleResponseTemplate[] = { |
1363 { SEC_ASN1_SEQUENCE, | 1361 { SEC_ASN1_SEQUENCE, |
1364 » 0, NULL, sizeof(CERTOCSPSingleResponse) }, | 1362 0, NULL, sizeof(CERTOCSPSingleResponse) }, |
1365 { SEC_ASN1_POINTER, | 1363 { SEC_ASN1_POINTER, |
1366 » offsetof(CERTOCSPSingleResponse, certID), | 1364 offsetof(CERTOCSPSingleResponse, certID), |
1367 » ocsp_CertIDTemplate }, | 1365 ocsp_CertIDTemplate }, |
1368 { SEC_ASN1_ANY, | 1366 { SEC_ASN1_ANY, |
1369 » offsetof(CERTOCSPSingleResponse, derCertStatus) }, | 1367 offsetof(CERTOCSPSingleResponse, derCertStatus) }, |
1370 { SEC_ASN1_GENERALIZED_TIME, | 1368 { SEC_ASN1_GENERALIZED_TIME, |
1371 » offsetof(CERTOCSPSingleResponse, thisUpdate) }, | 1369 offsetof(CERTOCSPSingleResponse, thisUpdate) }, |
1372 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1370 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1373 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | 1371 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
1374 » offsetof(CERTOCSPSingleResponse, nextUpdate), | 1372 offsetof(CERTOCSPSingleResponse, nextUpdate), |
1375 » SEC_ASN1_SUB(SEC_PointerToGeneralizedTimeTemplate) }, | 1373 SEC_ASN1_SUB(SEC_PointerToGeneralizedTimeTemplate) }, |
1376 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1374 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1377 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | 1375 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, |
1378 » offsetof(CERTOCSPSingleResponse, singleExtensions), | 1376 offsetof(CERTOCSPSingleResponse, singleExtensions), |
1379 » CERT_SequenceOfCertExtensionTemplate }, | 1377 CERT_SequenceOfCertExtensionTemplate }, |
1380 { 0 } | 1378 { 0 } |
1381 }; | 1379 }; |
1382 | 1380 |
1383 /* | 1381 /* |
1384 * CertStatus ::= CHOICE { | 1382 * CertStatus ::= CHOICE { |
1385 * good [0] IMPLICIT NULL, | 1383 * good [0] IMPLICIT NULL, |
1386 * revoked [1] IMPLICIT RevokedInfo, | 1384 * revoked [1] IMPLICIT RevokedInfo, |
1387 * unknown [2] IMPLICIT UnknownInfo } | 1385 * unknown [2] IMPLICIT UnknownInfo } |
1388 * | 1386 * |
1389 * Because the ASN.1 encoder and decoder currently do not provide | 1387 * Because the ASN.1 encoder and decoder currently do not provide |
1390 * a way to automatically handle a CHOICE, we need to do it in two | 1388 * a way to automatically handle a CHOICE, we need to do it in two |
1391 * steps, looking at the type tag and feeding the exact choice back | 1389 * steps, looking at the type tag and feeding the exact choice back |
1392 * to the ASN.1 code. Hopefully that will change someday and this | 1390 * to the ASN.1 code. Hopefully that will change someday and this |
1393 * can all be simplified down into a single template. Anyway, for | 1391 * can all be simplified down into a single template. Anyway, for |
1394 * now we list each choice as its own template: | 1392 * now we list each choice as its own template: |
1395 */ | 1393 */ |
1396 static const SEC_ASN1Template ocsp_CertStatusGoodTemplate[] = { | 1394 static const SEC_ASN1Template ocsp_CertStatusGoodTemplate[] = { |
1397 { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | 1395 { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
1398 » offsetof(ocspCertStatus, certStatusInfo.goodInfo), | 1396 offsetof(ocspCertStatus, certStatusInfo.goodInfo), |
1399 » SEC_ASN1_SUB(SEC_NullTemplate) } | 1397 SEC_ASN1_SUB(SEC_NullTemplate) } |
1400 }; | 1398 }; |
1401 static const SEC_ASN1Template ocsp_CertStatusRevokedTemplate[] = { | 1399 static const SEC_ASN1Template ocsp_CertStatusRevokedTemplate[] = { |
1402 { SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | 1400 { SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, |
1403 » offsetof(ocspCertStatus, certStatusInfo.revokedInfo), | 1401 offsetof(ocspCertStatus, certStatusInfo.revokedInfo), |
1404 » ocsp_RevokedInfoTemplate } | 1402 ocsp_RevokedInfoTemplate } |
1405 }; | 1403 }; |
1406 static const SEC_ASN1Template ocsp_CertStatusUnknownTemplate[] = { | 1404 static const SEC_ASN1Template ocsp_CertStatusUnknownTemplate[] = { |
1407 { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, | 1405 { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, |
1408 » offsetof(ocspCertStatus, certStatusInfo.unknownInfo), | 1406 offsetof(ocspCertStatus, certStatusInfo.unknownInfo), |
1409 » SEC_ASN1_SUB(SEC_NullTemplate) } | 1407 SEC_ASN1_SUB(SEC_NullTemplate) } |
1410 }; | 1408 }; |
1411 static const SEC_ASN1Template ocsp_CertStatusOtherTemplate[] = { | 1409 static const SEC_ASN1Template ocsp_CertStatusOtherTemplate[] = { |
1412 { SEC_ASN1_POINTER | SEC_ASN1_XTRN, | 1410 { SEC_ASN1_POINTER | SEC_ASN1_XTRN, |
1413 » offsetof(ocspCertStatus, certStatusInfo.otherInfo), | 1411 offsetof(ocspCertStatus, certStatusInfo.otherInfo), |
1414 » SEC_ASN1_SUB(SEC_AnyTemplate) } | 1412 SEC_ASN1_SUB(SEC_AnyTemplate) } |
1415 }; | 1413 }; |
1416 | 1414 |
1417 /* | 1415 /* |
1418 * RevokedInfo ::= SEQUENCE { | 1416 * RevokedInfo ::= SEQUENCE { |
1419 * revocationTime GeneralizedTime, | 1417 * revocationTime GeneralizedTime, |
1420 * revocationReason [0] EXPLICIT CRLReason OPTIONAL } | 1418 * revocationReason [0] EXPLICIT CRLReason OPTIONAL } |
1421 * | 1419 * |
1422 * Note: this should be static but the AIX compiler doesn't like it (because it | 1420 * Note: this should be static but the AIX compiler doesn't like it (because it |
1423 * was forward-declared above); it is not meant to be exported, but this | 1421 * was forward-declared above); it is not meant to be exported, but this |
1424 * is the only way it will compile. | 1422 * is the only way it will compile. |
1425 */ | 1423 */ |
1426 const SEC_ASN1Template ocsp_RevokedInfoTemplate[] = { | 1424 const SEC_ASN1Template ocsp_RevokedInfoTemplate[] = { |
1427 { SEC_ASN1_SEQUENCE, | 1425 { SEC_ASN1_SEQUENCE, |
1428 » 0, NULL, sizeof(ocspRevokedInfo) }, | 1426 0, NULL, sizeof(ocspRevokedInfo) }, |
1429 { SEC_ASN1_GENERALIZED_TIME, | 1427 { SEC_ASN1_GENERALIZED_TIME, |
1430 » offsetof(ocspRevokedInfo, revocationTime) }, | 1428 offsetof(ocspRevokedInfo, revocationTime) }, |
1431 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 1429 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | |
1432 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | | 1430 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | |
1433 SEC_ASN1_XTRN | 0, | 1431 SEC_ASN1_XTRN | 0, |
1434 » offsetof(ocspRevokedInfo, revocationReason), | 1432 offsetof(ocspRevokedInfo, revocationReason), |
1435 » SEC_ASN1_SUB(SEC_PointerToEnumeratedTemplate) }, | 1433 SEC_ASN1_SUB(SEC_PointerToEnumeratedTemplate) }, |
1436 { 0 } | 1434 { 0 } |
1437 }; | 1435 }; |
1438 | 1436 |
1439 | |
1440 /* | 1437 /* |
1441 * OCSP-specific extension templates: | 1438 * OCSP-specific extension templates: |
1442 */ | 1439 */ |
1443 | 1440 |
1444 /* | 1441 /* |
1445 * ServiceLocator ::= SEQUENCE { | 1442 * ServiceLocator ::= SEQUENCE { |
1446 * issuer Name, | 1443 * issuer Name, |
1447 * locator AuthorityInfoAccessSyntax OPTIONAL } | 1444 * locator AuthorityInfoAccessSyntax OPTIONAL } |
1448 */ | 1445 */ |
1449 static const SEC_ASN1Template ocsp_ServiceLocatorTemplate[] = { | 1446 static const SEC_ASN1Template ocsp_ServiceLocatorTemplate[] = { |
1450 { SEC_ASN1_SEQUENCE, | 1447 { SEC_ASN1_SEQUENCE, |
1451 » 0, NULL, sizeof(ocspServiceLocator) }, | 1448 0, NULL, sizeof(ocspServiceLocator) }, |
1452 { SEC_ASN1_POINTER, | 1449 { SEC_ASN1_POINTER, |
1453 » offsetof(ocspServiceLocator, issuer), | 1450 offsetof(ocspServiceLocator, issuer), |
1454 » CERT_NameTemplate }, | 1451 CERT_NameTemplate }, |
1455 { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, | 1452 { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, |
1456 » offsetof(ocspServiceLocator, locator) }, | 1453 offsetof(ocspServiceLocator, locator) }, |
1457 { 0 } | 1454 { 0 } |
1458 }; | 1455 }; |
1459 | 1456 |
1460 | |
1461 /* | 1457 /* |
1462 * REQUEST SUPPORT FUNCTIONS (encode/create/decode/destroy): | 1458 * REQUEST SUPPORT FUNCTIONS (encode/create/decode/destroy): |
1463 */ | 1459 */ |
1464 | 1460 |
1465 /* | 1461 /* |
1466 * FUNCTION: CERT_EncodeOCSPRequest | 1462 * FUNCTION: CERT_EncodeOCSPRequest |
1467 * DER encodes an OCSP Request, possibly adding a signature as well. | 1463 * DER encodes an OCSP Request, possibly adding a signature as well. |
1468 * XXX Signing is not yet supported, however; see comments in code. | 1464 * XXX Signing is not yet supported, however; see comments in code. |
1469 * INPUTS: | 1465 * INPUTS: |
1470 * PLArenaPool *arena | 1466 * PLArenaPool *arena |
1471 * The return value is allocated from here. | 1467 * The return value is allocated from here. |
1472 * If a NULL is passed in, allocation is done from the heap instead. | 1468 * If a NULL is passed in, allocation is done from the heap instead. |
1473 * CERTOCSPRequest *request | 1469 * CERTOCSPRequest *request |
1474 * The request to be encoded. | 1470 * The request to be encoded. |
1475 * void *pwArg | 1471 * void *pwArg |
1476 * Pointer to argument for password prompting, if needed. (Definitely | 1472 * Pointer to argument for password prompting, if needed. (Definitely |
1477 * not needed if not signing.) | 1473 * not needed if not signing.) |
1478 * RETURN: | 1474 * RETURN: |
1479 * Returns a NULL on error and a pointer to the SECItem with the | 1475 * Returns a NULL on error and a pointer to the SECItem with the |
1480 * encoded value otherwise. Any error is likely to be low-level | 1476 * encoded value otherwise. Any error is likely to be low-level |
1481 * (e.g. no memory). | 1477 * (e.g. no memory). |
1482 */ | 1478 */ |
1483 SECItem * | 1479 SECItem * |
1484 CERT_EncodeOCSPRequest(PLArenaPool *arena, CERTOCSPRequest *request, | 1480 CERT_EncodeOCSPRequest(PLArenaPool *arena, CERTOCSPRequest *request, |
1485 » » void *pwArg) | 1481 void *pwArg) |
1486 { | 1482 { |
1487 SECStatus rv; | 1483 SECStatus rv; |
1488 | 1484 |
1489 /* XXX All of these should generate errors if they fail. */ | 1485 /* XXX All of these should generate errors if they fail. */ |
1490 PORT_Assert(request); | 1486 PORT_Assert(request); |
1491 PORT_Assert(request->tbsRequest); | 1487 PORT_Assert(request->tbsRequest); |
1492 | 1488 |
1493 if (request->tbsRequest->extensionHandle != NULL) { | 1489 if (request->tbsRequest->extensionHandle != NULL) { |
1494 » rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle); | 1490 rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle); |
1495 » request->tbsRequest->extensionHandle = NULL; | 1491 request->tbsRequest->extensionHandle = NULL; |
1496 » if (rv != SECSuccess) | 1492 if (rv != SECSuccess) |
1497 » return NULL; | 1493 return NULL; |
1498 } | 1494 } |
1499 | 1495 |
1500 /* | 1496 /* |
1501 * XXX When signed requests are supported and request->optionalSignature | 1497 * XXX When signed requests are supported and request->optionalSignature |
1502 * is not NULL: | 1498 * is not NULL: |
1503 * - need to encode tbsRequest->requestorName | 1499 * - need to encode tbsRequest->requestorName |
1504 * - need to encode tbsRequest | 1500 * - need to encode tbsRequest |
1505 * - need to sign that encoded result (using cert in sig), filling in the | 1501 * - need to sign that encoded result (using cert in sig), filling in the |
1506 * request->optionalSignature structure with the result, the signing | 1502 * request->optionalSignature structure with the result, the signing |
1507 * algorithm and (perhaps?) the cert (and its chain?) in derCerts | 1503 * algorithm and (perhaps?) the cert (and its chain?) in derCerts |
1508 */ | 1504 */ |
1509 | 1505 |
1510 return SEC_ASN1EncodeItem(arena, NULL, request, ocsp_OCSPRequestTemplate); | 1506 return SEC_ASN1EncodeItem(arena, NULL, request, ocsp_OCSPRequestTemplate); |
1511 } | 1507 } |
1512 | 1508 |
1513 | |
1514 /* | 1509 /* |
1515 * FUNCTION: CERT_DecodeOCSPRequest | 1510 * FUNCTION: CERT_DecodeOCSPRequest |
1516 * Decode a DER encoded OCSP Request. | 1511 * Decode a DER encoded OCSP Request. |
1517 * INPUTS: | 1512 * INPUTS: |
1518 * SECItem *src | 1513 * SECItem *src |
1519 * Pointer to a SECItem holding DER encoded OCSP Request. | 1514 * Pointer to a SECItem holding DER encoded OCSP Request. |
1520 * RETURN: | 1515 * RETURN: |
1521 * Returns a pointer to a CERTOCSPRequest containing the decoded request. | 1516 * Returns a pointer to a CERTOCSPRequest containing the decoded request. |
1522 * On error, returns NULL. Most likely error is trouble decoding | 1517 * On error, returns NULL. Most likely error is trouble decoding |
1523 * (SEC_ERROR_OCSP_MALFORMED_REQUEST), or low-level problem (no memory). | 1518 * (SEC_ERROR_OCSP_MALFORMED_REQUEST), or low-level problem (no memory). |
1524 */ | 1519 */ |
1525 CERTOCSPRequest * | 1520 CERTOCSPRequest * |
1526 CERT_DecodeOCSPRequest(const SECItem *src) | 1521 CERT_DecodeOCSPRequest(const SECItem *src) |
1527 { | 1522 { |
1528 PLArenaPool *arena = NULL; | 1523 PLArenaPool *arena = NULL; |
1529 SECStatus rv = SECFailure; | 1524 SECStatus rv = SECFailure; |
1530 CERTOCSPRequest *dest = NULL; | 1525 CERTOCSPRequest *dest = NULL; |
1531 int i; | 1526 int i; |
1532 SECItem newSrc; | 1527 SECItem newSrc; |
1533 | 1528 |
1534 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 1529 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
1535 if (arena == NULL) { | 1530 if (arena == NULL) { |
1536 » goto loser; | 1531 goto loser; |
1537 } | 1532 } |
1538 dest = (CERTOCSPRequest *) PORT_ArenaZAlloc(arena, | 1533 dest = (CERTOCSPRequest *)PORT_ArenaZAlloc(arena, |
1539 » » » » » » sizeof(CERTOCSPRequest)); | 1534 sizeof(CERTOCSPRequest)); |
1540 if (dest == NULL) { | 1535 if (dest == NULL) { |
1541 » goto loser; | 1536 goto loser; |
1542 } | 1537 } |
1543 dest->arena = arena; | 1538 dest->arena = arena; |
1544 | 1539 |
1545 /* copy the DER into the arena, since Quick DER returns data that points | 1540 /* copy the DER into the arena, since Quick DER returns data that points |
1546 into the DER input, which may get freed by the caller */ | 1541 into the DER input, which may get freed by the caller */ |
1547 rv = SECITEM_CopyItem(arena, &newSrc, src); | 1542 rv = SECITEM_CopyItem(arena, &newSrc, src); |
1548 if ( rv != SECSuccess ) { | 1543 if (rv != SECSuccess) { |
1549 » goto loser; | 1544 goto loser; |
1550 } | 1545 } |
1551 | 1546 |
1552 rv = SEC_QuickDERDecodeItem(arena, dest, ocsp_OCSPRequestTemplate, &newSrc); | 1547 rv = SEC_QuickDERDecodeItem(arena, dest, ocsp_OCSPRequestTemplate, &newSrc); |
1553 if (rv != SECSuccess) { | 1548 if (rv != SECSuccess) { |
1554 » if (PORT_GetError() == SEC_ERROR_BAD_DER) | 1549 if (PORT_GetError() == SEC_ERROR_BAD_DER) |
1555 » PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST); | 1550 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST); |
1556 » goto loser; | 1551 goto loser; |
1557 } | 1552 } |
1558 | 1553 |
1559 /* | 1554 /* |
1560 * XXX I would like to find a way to get rid of the necessity | 1555 * XXX I would like to find a way to get rid of the necessity |
1561 * of doing this copying of the arena pointer. | 1556 * of doing this copying of the arena pointer. |
1562 */ | 1557 */ |
1563 for (i = 0; dest->tbsRequest->requestList[i] != NULL; i++) { | 1558 for (i = 0; dest->tbsRequest->requestList[i] != NULL; i++) { |
1564 » dest->tbsRequest->requestList[i]->arena = arena; | 1559 dest->tbsRequest->requestList[i]->arena = arena; |
1565 } | 1560 } |
1566 | 1561 |
1567 return dest; | 1562 return dest; |
1568 | 1563 |
1569 loser: | 1564 loser: |
1570 if (arena != NULL) { | 1565 if (arena != NULL) { |
1571 » PORT_FreeArena(arena, PR_FALSE); | 1566 PORT_FreeArena(arena, PR_FALSE); |
1572 } | 1567 } |
1573 return NULL; | 1568 return NULL; |
1574 } | 1569 } |
1575 | 1570 |
1576 SECStatus | 1571 SECStatus |
1577 CERT_DestroyOCSPCertID(CERTOCSPCertID* certID) | 1572 CERT_DestroyOCSPCertID(CERTOCSPCertID *certID) |
1578 { | 1573 { |
1579 if (certID && certID->poolp) { | 1574 if (certID && certID->poolp) { |
1580 » PORT_FreeArena(certID->poolp, PR_FALSE); | 1575 PORT_FreeArena(certID->poolp, PR_FALSE); |
1581 » return SECSuccess; | 1576 return SECSuccess; |
1582 } | 1577 } |
1583 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1578 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1584 return SECFailure; | 1579 return SECFailure; |
1585 } | 1580 } |
1586 | 1581 |
1587 /* | 1582 /* |
1588 * Digest data using the specified algorithm. | 1583 * Digest data using the specified algorithm. |
1589 * The necessary storage for the digest data is allocated. If "fill" is | 1584 * The necessary storage for the digest data is allocated. If "fill" is |
1590 * non-null, the data is put there, otherwise a SECItem is allocated. | 1585 * non-null, the data is put there, otherwise a SECItem is allocated. |
1591 * Allocation from "arena" if it is non-null, heap otherwise. Any problem | 1586 * Allocation from "arena" if it is non-null, heap otherwise. Any problem |
1592 * results in a NULL being returned (and an appropriate error set). | 1587 * results in a NULL being returned (and an appropriate error set). |
1593 */ | 1588 */ |
1594 | 1589 |
1595 SECItem * | 1590 SECItem * |
1596 ocsp_DigestValue(PLArenaPool *arena, SECOidTag digestAlg, | 1591 ocsp_DigestValue(PLArenaPool *arena, SECOidTag digestAlg, |
1597 SECItem *fill, const SECItem *src) | 1592 SECItem *fill, const SECItem *src) |
1598 { | 1593 { |
1599 const SECHashObject *digestObject; | 1594 const SECHashObject *digestObject; |
1600 SECItem *result = NULL; | 1595 SECItem *result = NULL; |
1601 void *mark = NULL; | 1596 void *mark = NULL; |
1602 void *digestBuff = NULL; | 1597 void *digestBuff = NULL; |
1603 | 1598 |
1604 if ( arena != NULL ) { | 1599 if (arena != NULL) { |
1605 mark = PORT_ArenaMark(arena); | 1600 mark = PORT_ArenaMark(arena); |
1606 } | 1601 } |
1607 | 1602 |
1608 digestObject = HASH_GetHashObjectByOidTag(digestAlg); | 1603 digestObject = HASH_GetHashObjectByOidTag(digestAlg); |
1609 if ( digestObject == NULL ) { | 1604 if (digestObject == NULL) { |
1610 goto loser; | 1605 goto loser; |
1611 } | 1606 } |
1612 | 1607 |
1613 if (fill == NULL || fill->data == NULL) { | 1608 if (fill == NULL || fill->data == NULL) { |
1614 » result = SECITEM_AllocItem(arena, fill, digestObject->length); | 1609 result = SECITEM_AllocItem(arena, fill, digestObject->length); |
1615 » if ( result == NULL ) { | 1610 if (result == NULL) { |
1616 » goto loser; | 1611 goto loser; |
1617 » } | 1612 } |
1618 » digestBuff = result->data; | 1613 digestBuff = result->data; |
1619 } else { | 1614 } else { |
1620 » if (fill->len < digestObject->length) { | 1615 if (fill->len < digestObject->length) { |
1621 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1616 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1622 » goto loser; | 1617 goto loser; |
1623 » } | 1618 } |
1624 » digestBuff = fill->data; | 1619 digestBuff = fill->data; |
1625 } | 1620 } |
1626 | 1621 |
1627 if (PK11_HashBuf(digestAlg, digestBuff, | 1622 if (PK11_HashBuf(digestAlg, digestBuff, |
1628 src->data, src->len) != SECSuccess) { | 1623 src->data, src->len) != SECSuccess) { |
1629 goto loser; | 1624 goto loser; |
1630 } | 1625 } |
1631 | 1626 |
1632 if ( arena != NULL ) { | 1627 if (arena != NULL) { |
1633 PORT_ArenaUnmark(arena, mark); | 1628 PORT_ArenaUnmark(arena, mark); |
1634 } | 1629 } |
1635 | 1630 |
1636 if (result == NULL) { | 1631 if (result == NULL) { |
1637 result = fill; | 1632 result = fill; |
1638 } | 1633 } |
1639 return result; | 1634 return result; |
1640 | 1635 |
1641 loser: | 1636 loser: |
1642 if (arena != NULL) { | 1637 if (arena != NULL) { |
1643 PORT_ArenaRelease(arena, mark); | 1638 PORT_ArenaRelease(arena, mark); |
1644 } else { | 1639 } else { |
1645 if (result != NULL) { | 1640 if (result != NULL) { |
1646 SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE); | 1641 SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE); |
1647 } | 1642 } |
1648 } | 1643 } |
1649 return(NULL); | 1644 return (NULL); |
1650 } | 1645 } |
1651 | 1646 |
1652 /* | 1647 /* |
1653 * Digest the cert's subject public key using the specified algorithm. | 1648 * Digest the cert's subject public key using the specified algorithm. |
1654 * The necessary storage for the digest data is allocated. If "fill" is | 1649 * The necessary storage for the digest data is allocated. If "fill" is |
1655 * non-null, the data is put there, otherwise a SECItem is allocated. | 1650 * non-null, the data is put there, otherwise a SECItem is allocated. |
1656 * Allocation from "arena" if it is non-null, heap otherwise. Any problem | 1651 * Allocation from "arena" if it is non-null, heap otherwise. Any problem |
1657 * results in a NULL being returned (and an appropriate error set). | 1652 * results in a NULL being returned (and an appropriate error set). |
1658 */ | 1653 */ |
1659 SECItem * | 1654 SECItem * |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1706 { | 1701 { |
1707 CERTOCSPCertID *certID; | 1702 CERTOCSPCertID *certID; |
1708 CERTCertificate *issuerCert = NULL; | 1703 CERTCertificate *issuerCert = NULL; |
1709 void *mark = PORT_ArenaMark(arena); | 1704 void *mark = PORT_ArenaMark(arena); |
1710 SECStatus rv; | 1705 SECStatus rv; |
1711 | 1706 |
1712 PORT_Assert(arena != NULL); | 1707 PORT_Assert(arena != NULL); |
1713 | 1708 |
1714 certID = PORT_ArenaZNew(arena, CERTOCSPCertID); | 1709 certID = PORT_ArenaZNew(arena, CERTOCSPCertID); |
1715 if (certID == NULL) { | 1710 if (certID == NULL) { |
1716 » goto loser; | 1711 goto loser; |
1717 } | 1712 } |
1718 | 1713 |
1719 rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1, | 1714 rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1, |
1720 » » » NULL); | 1715 NULL); |
1721 if (rv != SECSuccess) { | 1716 if (rv != SECSuccess) { |
1722 » goto loser; | 1717 goto loser; |
1723 } | 1718 } |
1724 | 1719 |
1725 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); | 1720 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); |
1726 if (issuerCert == NULL) { | 1721 if (issuerCert == NULL) { |
1727 » goto loser; | 1722 goto loser; |
1728 } | 1723 } |
1729 | 1724 |
1730 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_SHA1, | 1725 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_SHA1, |
1731 &(certID->issuerNameHash)) == NULL) { | 1726 &(certID->issuerNameHash)) == NULL) { |
1732 goto loser; | 1727 goto loser; |
1733 } | 1728 } |
1734 certID->issuerSHA1NameHash.data = certID->issuerNameHash.data; | 1729 certID->issuerSHA1NameHash.data = certID->issuerNameHash.data; |
1735 certID->issuerSHA1NameHash.len = certID->issuerNameHash.len; | 1730 certID->issuerSHA1NameHash.len = certID->issuerNameHash.len; |
1736 | 1731 |
1737 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD5, | 1732 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD5, |
1738 &(certID->issuerMD5NameHash)) == NULL) { | 1733 &(certID->issuerMD5NameHash)) == NULL) { |
1739 goto loser; | 1734 goto loser; |
1740 } | 1735 } |
1741 | 1736 |
1742 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD2, | 1737 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD2, |
1743 &(certID->issuerMD2NameHash)) == NULL) { | 1738 &(certID->issuerMD2NameHash)) == NULL) { |
1744 goto loser; | 1739 goto loser; |
1745 } | 1740 } |
1746 | 1741 |
1747 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_SHA1, | 1742 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_SHA1, |
1748 » » » » &certID->issuerKeyHash) == NULL) { | 1743 &certID->issuerKeyHash) == NULL) { |
1749 » goto loser; | 1744 goto loser; |
1750 } | 1745 } |
1751 certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data; | 1746 certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data; |
1752 certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len; | 1747 certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len; |
1753 /* cache the other two hash algorithms as well */ | 1748 /* cache the other two hash algorithms as well */ |
1754 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD5, | 1749 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD5, |
1755 » » » » &certID->issuerMD5KeyHash) == NULL) { | 1750 &certID->issuerMD5KeyHash) == NULL) { |
1756 » goto loser; | 1751 goto loser; |
1757 } | 1752 } |
1758 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD2, | 1753 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD2, |
1759 » » » » &certID->issuerMD2KeyHash) == NULL) { | 1754 &certID->issuerMD2KeyHash) == NULL) { |
1760 » goto loser; | 1755 goto loser; |
1761 } | 1756 } |
1762 | 1757 |
1763 | |
1764 /* now we are done with issuerCert */ | 1758 /* now we are done with issuerCert */ |
1765 CERT_DestroyCertificate(issuerCert); | 1759 CERT_DestroyCertificate(issuerCert); |
1766 issuerCert = NULL; | 1760 issuerCert = NULL; |
1767 | 1761 |
1768 rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber); | 1762 rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber); |
1769 if (rv != SECSuccess) { | 1763 if (rv != SECSuccess) { |
1770 » goto loser; | 1764 goto loser; |
1771 } | 1765 } |
1772 | 1766 |
1773 PORT_ArenaUnmark(arena, mark); | 1767 PORT_ArenaUnmark(arena, mark); |
1774 return certID; | 1768 return certID; |
1775 | 1769 |
1776 loser: | 1770 loser: |
1777 if (issuerCert != NULL) { | 1771 if (issuerCert != NULL) { |
1778 » CERT_DestroyCertificate(issuerCert); | 1772 CERT_DestroyCertificate(issuerCert); |
1779 } | 1773 } |
1780 PORT_ArenaRelease(arena, mark); | 1774 PORT_ArenaRelease(arena, mark); |
1781 return NULL; | 1775 return NULL; |
1782 } | 1776 } |
1783 | 1777 |
1784 CERTOCSPCertID* | 1778 CERTOCSPCertID * |
1785 CERT_CreateOCSPCertID(CERTCertificate *cert, PRTime time) | 1779 CERT_CreateOCSPCertID(CERTCertificate *cert, PRTime time) |
1786 { | 1780 { |
1787 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 1781 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
1788 CERTOCSPCertID *certID; | 1782 CERTOCSPCertID *certID; |
1789 PORT_Assert(arena != NULL); | 1783 PORT_Assert(arena != NULL); |
1790 if (!arena) | 1784 if (!arena) |
1791 » return NULL; | 1785 return NULL; |
1792 | 1786 |
1793 certID = ocsp_CreateCertID(arena, cert, time); | 1787 certID = ocsp_CreateCertID(arena, cert, time); |
1794 if (!certID) { | 1788 if (!certID) { |
1795 » PORT_FreeArena(arena, PR_FALSE); | 1789 PORT_FreeArena(arena, PR_FALSE); |
1796 » return NULL; | 1790 return NULL; |
1797 } | 1791 } |
1798 certID->poolp = arena; | 1792 certID->poolp = arena; |
1799 return certID; | 1793 return certID; |
1800 } | 1794 } |
1801 | 1795 |
1802 static CERTOCSPCertID * | 1796 static CERTOCSPCertID * |
1803 cert_DupOCSPCertID(const CERTOCSPCertID *src) | 1797 cert_DupOCSPCertID(const CERTOCSPCertID *src) |
1804 { | 1798 { |
1805 CERTOCSPCertID *dest; | 1799 CERTOCSPCertID *dest; |
1806 PLArenaPool *arena = NULL; | 1800 PLArenaPool *arena = NULL; |
1807 | 1801 |
1808 if (!src) { | 1802 if (!src) { |
1809 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1803 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1810 return NULL; | 1804 return NULL; |
1811 } | 1805 } |
1812 | 1806 |
1813 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 1807 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
1814 if (!arena) | 1808 if (!arena) |
1815 goto loser; | 1809 goto loser; |
1816 | 1810 |
1817 dest = PORT_ArenaZNew(arena, CERTOCSPCertID); | 1811 dest = PORT_ArenaZNew(arena, CERTOCSPCertID); |
1818 if (!dest) | 1812 if (!dest) |
1819 goto loser; | 1813 goto loser; |
1820 | 1814 |
1821 #define DUPHELP(element) \ | 1815 #define DUPHELP(element) \ |
1822 if (src->element.data && \ | 1816 if (src->element.data && \ |
1823 SECITEM_CopyItem(arena, &dest->element, &src->element) \ | 1817 SECITEM_CopyItem(arena, &dest->element, &src->element) != \ |
1824 != SECSuccess) { \ | 1818 SECSuccess) { \ |
1825 goto loser; \ | 1819 goto loser; \ |
1826 } | 1820 } |
1827 | 1821 |
1828 DUPHELP(hashAlgorithm.algorithm) | 1822 DUPHELP(hashAlgorithm.algorithm) |
1829 DUPHELP(hashAlgorithm.parameters) | 1823 DUPHELP(hashAlgorithm.parameters) |
1830 DUPHELP(issuerNameHash) | 1824 DUPHELP(issuerNameHash) |
1831 DUPHELP(issuerKeyHash) | 1825 DUPHELP(issuerKeyHash) |
1832 DUPHELP(serialNumber) | 1826 DUPHELP(serialNumber) |
1833 DUPHELP(issuerSHA1NameHash) | 1827 DUPHELP(issuerSHA1NameHash) |
1834 DUPHELP(issuerMD5NameHash) | 1828 DUPHELP(issuerMD5NameHash) |
1835 DUPHELP(issuerMD2NameHash) | 1829 DUPHELP(issuerMD2NameHash) |
1836 DUPHELP(issuerSHA1KeyHash) | 1830 DUPHELP(issuerSHA1KeyHash) |
1837 DUPHELP(issuerMD5KeyHash) | 1831 DUPHELP(issuerMD5KeyHash) |
1838 DUPHELP(issuerMD2KeyHash) | 1832 DUPHELP(issuerMD2KeyHash) |
1839 | 1833 |
1840 dest->poolp = arena; | 1834 dest->poolp = arena; |
1841 return dest; | 1835 return dest; |
1842 | 1836 |
1843 loser: | 1837 loser: |
1844 if (arena) | 1838 if (arena) |
1845 PORT_FreeArena(arena, PR_FALSE); | 1839 PORT_FreeArena(arena, PR_FALSE); |
1846 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); | 1840 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); |
1847 return NULL; | 1841 return NULL; |
1848 } | 1842 } |
1849 | 1843 |
1850 /* | 1844 /* |
1851 * Callback to set Extensions in request object | 1845 * Callback to set Extensions in request object |
1852 */ | 1846 */ |
1853 void SetSingleReqExts(void *object, CERTCertExtension **exts) | 1847 void |
| 1848 SetSingleReqExts(void *object, CERTCertExtension **exts) |
1854 { | 1849 { |
1855 ocspSingleRequest *singleRequest = | 1850 ocspSingleRequest *singleRequest = |
1856 (ocspSingleRequest *)object; | 1851 (ocspSingleRequest *)object; |
1857 | 1852 |
1858 singleRequest->singleRequestExtensions = exts; | 1853 singleRequest->singleRequestExtensions = exts; |
1859 } | 1854 } |
1860 | 1855 |
1861 /* | 1856 /* |
1862 * Add the Service Locator extension to the singleRequestExtensions | 1857 * Add the Service Locator extension to the singleRequestExtensions |
1863 * for the given singleRequest. | 1858 * for the given singleRequest. |
1864 * | 1859 * |
1865 * All errors are internal or low-level problems (e.g. no memory). | 1860 * All errors are internal or low-level problems (e.g. no memory). |
1866 */ | 1861 */ |
1867 static SECStatus | 1862 static SECStatus |
1868 ocsp_AddServiceLocatorExtension(ocspSingleRequest *singleRequest, | 1863 ocsp_AddServiceLocatorExtension(ocspSingleRequest *singleRequest, |
1869 » » » » CERTCertificate *cert) | 1864 CERTCertificate *cert) |
1870 { | 1865 { |
1871 ocspServiceLocator *serviceLocator = NULL; | 1866 ocspServiceLocator *serviceLocator = NULL; |
1872 void *extensionHandle = NULL; | 1867 void *extensionHandle = NULL; |
1873 SECStatus rv = SECFailure; | 1868 SECStatus rv = SECFailure; |
1874 | 1869 |
1875 serviceLocator = PORT_ZNew(ocspServiceLocator); | 1870 serviceLocator = PORT_ZNew(ocspServiceLocator); |
1876 if (serviceLocator == NULL) | 1871 if (serviceLocator == NULL) |
1877 » goto loser; | 1872 goto loser; |
1878 | 1873 |
1879 /* | 1874 /* |
1880 * Normally it would be a bad idea to do a direct reference like | 1875 * Normally it would be a bad idea to do a direct reference like |
1881 * this rather than allocate and copy the name *or* at least dup | 1876 * this rather than allocate and copy the name *or* at least dup |
1882 * a reference of the cert. But all we need is to be able to read | 1877 * a reference of the cert. But all we need is to be able to read |
1883 * the issuer name during the encoding we are about to do, so a | 1878 * the issuer name during the encoding we are about to do, so a |
1884 * copy is just a waste of time. | 1879 * copy is just a waste of time. |
1885 */ | 1880 */ |
1886 serviceLocator->issuer = &cert->issuer; | 1881 serviceLocator->issuer = &cert->issuer; |
1887 | 1882 |
1888 rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS, | 1883 rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS, |
1889 » » » » &serviceLocator->locator); | 1884 &serviceLocator->locator); |
1890 if (rv != SECSuccess) { | 1885 if (rv != SECSuccess) { |
1891 » if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) | 1886 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) |
1892 » goto loser; | 1887 goto loser; |
1893 } | 1888 } |
1894 | 1889 |
1895 /* prepare for following loser gotos */ | 1890 /* prepare for following loser gotos */ |
1896 rv = SECFailure; | 1891 rv = SECFailure; |
1897 PORT_SetError(0); | 1892 PORT_SetError(0); |
1898 | 1893 |
1899 extensionHandle = cert_StartExtensions(singleRequest, | 1894 extensionHandle = cert_StartExtensions(singleRequest, |
1900 singleRequest->arena, SetSingleReqExts); | 1895 singleRequest->arena, SetSingleReqExt
s); |
1901 if (extensionHandle == NULL) | 1896 if (extensionHandle == NULL) |
1902 » goto loser; | 1897 goto loser; |
1903 | 1898 |
1904 rv = CERT_EncodeAndAddExtension(extensionHandle, | 1899 rv = CERT_EncodeAndAddExtension(extensionHandle, |
1905 » » » » SEC_OID_PKIX_OCSP_SERVICE_LOCATOR, | 1900 SEC_OID_PKIX_OCSP_SERVICE_LOCATOR, |
1906 » » » » serviceLocator, PR_FALSE, | 1901 serviceLocator, PR_FALSE, |
1907 » » » » ocsp_ServiceLocatorTemplate); | 1902 ocsp_ServiceLocatorTemplate); |
1908 | 1903 |
1909 loser: | 1904 loser: |
1910 if (extensionHandle != NULL) { | 1905 if (extensionHandle != NULL) { |
1911 » /* | 1906 /* |
1912 * Either way we have to finish out the extension context (so it gets | 1907 * Either way we have to finish out the extension context (so it gets |
1913 * freed). But careful not to override any already-set bad status. | 1908 * freed). But careful not to override any already-set bad status. |
1914 */ | 1909 */ |
1915 » SECStatus tmprv = CERT_FinishExtensions(extensionHandle); | 1910 SECStatus tmprv = CERT_FinishExtensions(extensionHandle); |
1916 » if (rv == SECSuccess) | 1911 if (rv == SECSuccess) |
1917 » rv = tmprv; | 1912 rv = tmprv; |
1918 } | 1913 } |
1919 | 1914 |
1920 /* | 1915 /* |
1921 * Finally, free the serviceLocator structure itself and we are done. | 1916 * Finally, free the serviceLocator structure itself and we are done. |
1922 */ | 1917 */ |
1923 if (serviceLocator != NULL) { | 1918 if (serviceLocator != NULL) { |
1924 » if (serviceLocator->locator.data != NULL) | 1919 if (serviceLocator->locator.data != NULL) |
1925 » SECITEM_FreeItem(&serviceLocator->locator, PR_FALSE); | 1920 SECITEM_FreeItem(&serviceLocator->locator, PR_FALSE); |
1926 » PORT_Free(serviceLocator); | 1921 PORT_Free(serviceLocator); |
1927 } | 1922 } |
1928 | 1923 |
1929 return rv; | 1924 return rv; |
1930 } | 1925 } |
1931 | 1926 |
1932 /* | 1927 /* |
1933 * Creates an array of ocspSingleRequest based on a list of certs. | 1928 * Creates an array of ocspSingleRequest based on a list of certs. |
1934 * Note that the code which later compares the request list with the | 1929 * Note that the code which later compares the request list with the |
1935 * response expects this array to be in the exact same order as the | 1930 * response expects this array to be in the exact same order as the |
1936 * certs are found in the list. It would be harder to change that | 1931 * certs are found in the list. It would be harder to change that |
1937 * order than preserve it, but since the requirement is not obvious, | 1932 * order than preserve it, but since the requirement is not obvious, |
1938 * it deserves to be mentioned. | 1933 * it deserves to be mentioned. |
1939 * | 1934 * |
1940 * Any problem causes a null return and error set: | 1935 * Any problem causes a null return and error set: |
1941 * SEC_ERROR_UNKNOWN_ISSUER | 1936 * SEC_ERROR_UNKNOWN_ISSUER |
1942 * Other errors are low-level problems (no memory, bad database, etc.). | 1937 * Other errors are low-level problems (no memory, bad database, etc.). |
1943 */ | 1938 */ |
1944 static ocspSingleRequest ** | 1939 static ocspSingleRequest ** |
1945 ocsp_CreateSingleRequestList(PLArenaPool *arena, CERTCertList *certList, | 1940 ocsp_CreateSingleRequestList(PLArenaPool *arena, CERTCertList *certList, |
1946 PRTime time, PRBool includeLocator) | 1941 PRTime time, PRBool includeLocator) |
1947 { | 1942 { |
1948 ocspSingleRequest **requestList = NULL; | 1943 ocspSingleRequest **requestList = NULL; |
1949 CERTCertListNode *node = NULL; | 1944 CERTCertListNode *node = NULL; |
1950 int i, count; | 1945 int i, count; |
1951 void *mark = PORT_ArenaMark(arena); | 1946 void *mark = PORT_ArenaMark(arena); |
1952 | 1947 |
1953 node = CERT_LIST_HEAD(certList); | 1948 node = CERT_LIST_HEAD(certList); |
1954 for (count = 0; !CERT_LIST_END(node, certList); count++) { | 1949 for (count = 0; !CERT_LIST_END(node, certList); count++) { |
1955 node = CERT_LIST_NEXT(node); | 1950 node = CERT_LIST_NEXT(node); |
1956 } | 1951 } |
1957 | 1952 |
1958 if (count == 0) | 1953 if (count == 0) |
1959 » goto loser; | 1954 goto loser; |
1960 | 1955 |
1961 requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, count + 1); | 1956 requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, count + 1); |
1962 if (requestList == NULL) | 1957 if (requestList == NULL) |
1963 » goto loser; | 1958 goto loser; |
1964 | 1959 |
1965 node = CERT_LIST_HEAD(certList); | 1960 node = CERT_LIST_HEAD(certList); |
1966 for (i = 0; !CERT_LIST_END(node, certList); i++) { | 1961 for (i = 0; !CERT_LIST_END(node, certList); i++) { |
1967 requestList[i] = PORT_ArenaZNew(arena, ocspSingleRequest); | 1962 requestList[i] = PORT_ArenaZNew(arena, ocspSingleRequest); |
1968 if (requestList[i] == NULL) | 1963 if (requestList[i] == NULL) |
1969 goto loser; | 1964 goto loser; |
1970 | 1965 |
1971 OCSP_TRACE(("OCSP CERT_CreateOCSPRequest %s\n", node->cert->subjectName)
); | 1966 OCSP_TRACE(("OCSP CERT_CreateOCSPRequest %s\n", node->cert->subjectName)
); |
1972 requestList[i]->arena = arena; | 1967 requestList[i]->arena = arena; |
1973 requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time); | 1968 requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time); |
(...skipping 17 matching lines...) Expand all Loading... |
1991 requestList[i] = NULL; | 1986 requestList[i] = NULL; |
1992 return requestList; | 1987 return requestList; |
1993 | 1988 |
1994 loser: | 1989 loser: |
1995 PORT_ArenaRelease(arena, mark); | 1990 PORT_ArenaRelease(arena, mark); |
1996 return NULL; | 1991 return NULL; |
1997 } | 1992 } |
1998 | 1993 |
1999 static ocspSingleRequest ** | 1994 static ocspSingleRequest ** |
2000 ocsp_CreateRequestFromCert(PLArenaPool *arena, | 1995 ocsp_CreateRequestFromCert(PLArenaPool *arena, |
2001 CERTOCSPCertID *certID, | 1996 CERTOCSPCertID *certID, |
2002 CERTCertificate *singleCert, | 1997 CERTCertificate *singleCert, |
2003 PRTime time, | 1998 PRTime time, |
2004 PRBool includeLocator) | 1999 PRBool includeLocator) |
2005 { | 2000 { |
2006 ocspSingleRequest **requestList = NULL; | 2001 ocspSingleRequest **requestList = NULL; |
2007 void *mark = PORT_ArenaMark(arena); | 2002 void *mark = PORT_ArenaMark(arena); |
2008 PORT_Assert(certID != NULL && singleCert != NULL); | 2003 PORT_Assert(certID != NULL && singleCert != NULL); |
2009 | 2004 |
2010 /* meaning of value 2: one entry + one end marker */ | 2005 /* meaning of value 2: one entry + one end marker */ |
2011 requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, 2); | 2006 requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, 2); |
2012 if (requestList == NULL) | 2007 if (requestList == NULL) |
2013 goto loser; | 2008 goto loser; |
2014 requestList[0] = PORT_ArenaZNew(arena, ocspSingleRequest); | 2009 requestList[0] = PORT_ArenaZNew(arena, ocspSingleRequest); |
2015 if (requestList[0] == NULL) | 2010 if (requestList[0] == NULL) |
2016 goto loser; | 2011 goto loser; |
2017 requestList[0]->arena = arena; | 2012 requestList[0]->arena = arena; |
2018 /* certID will live longer than the request */ | 2013 /* certID will live longer than the request */ |
2019 requestList[0]->reqCert = certID; | 2014 requestList[0]->reqCert = certID; |
2020 | 2015 |
2021 if (includeLocator == PR_TRUE) { | 2016 if (includeLocator == PR_TRUE) { |
2022 SECStatus rv; | 2017 SECStatus rv; |
2023 rv = ocsp_AddServiceLocatorExtension(requestList[0], singleCert); | 2018 rv = ocsp_AddServiceLocatorExtension(requestList[0], singleCert); |
2024 if (rv != SECSuccess) | 2019 if (rv != SECSuccess) |
2025 goto loser; | 2020 goto loser; |
2026 } | 2021 } |
2027 | 2022 |
2028 PORT_ArenaUnmark(arena, mark); | 2023 PORT_ArenaUnmark(arena, mark); |
2029 requestList[1] = NULL; | 2024 requestList[1] = NULL; |
(...skipping 30 matching lines...) Expand all Loading... |
2060 return request; | 2055 return request; |
2061 | 2056 |
2062 loser: | 2057 loser: |
2063 if (arena != NULL) { | 2058 if (arena != NULL) { |
2064 PORT_FreeArena(arena, PR_FALSE); | 2059 PORT_FreeArena(arena, PR_FALSE); |
2065 } | 2060 } |
2066 return NULL; | 2061 return NULL; |
2067 } | 2062 } |
2068 | 2063 |
2069 CERTOCSPRequest * | 2064 CERTOCSPRequest * |
2070 cert_CreateSingleCertOCSPRequest(CERTOCSPCertID *certID, | 2065 cert_CreateSingleCertOCSPRequest(CERTOCSPCertID *certID, |
2071 CERTCertificate *singleCert, | 2066 CERTCertificate *singleCert, |
2072 PRTime time, | 2067 PRTime time, |
2073 PRBool addServiceLocator, | 2068 PRBool addServiceLocator, |
2074 CERTCertificate *signerCert) | 2069 CERTCertificate *signerCert) |
2075 { | 2070 { |
2076 CERTOCSPRequest *request; | 2071 CERTOCSPRequest *request; |
2077 OCSP_TRACE(("OCSP cert_CreateSingleCertOCSPRequest %s\n", singleCert->subjec
tName)); | 2072 OCSP_TRACE(("OCSP cert_CreateSingleCertOCSPRequest %s\n", singleCert->subjec
tName)); |
2078 | 2073 |
2079 /* XXX Support for signerCert may be implemented later, | 2074 /* XXX Support for signerCert may be implemented later, |
2080 * see also the comment in CERT_CreateOCSPRequest. | 2075 * see also the comment in CERT_CreateOCSPRequest. |
2081 */ | 2076 */ |
2082 if (signerCert != NULL) { | 2077 if (signerCert != NULL) { |
2083 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | 2078 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
2084 return NULL; | 2079 return NULL; |
2085 } | 2080 } |
2086 | 2081 |
2087 request = ocsp_prepareEmptyOCSPRequest(); | 2082 request = ocsp_prepareEmptyOCSPRequest(); |
2088 if (!request) | 2083 if (!request) |
2089 return NULL; | 2084 return NULL; |
2090 /* | 2085 /* |
2091 * Version 1 is the default, so we need not fill in a version number. | 2086 * Version 1 is the default, so we need not fill in a version number. |
2092 * Now create the list of single requests, one for each cert. | 2087 * Now create the list of single requests, one for each cert. |
2093 */ | 2088 */ |
2094 request->tbsRequest->requestList = | 2089 request->tbsRequest->requestList = |
2095 ocsp_CreateRequestFromCert(request->arena, | 2090 ocsp_CreateRequestFromCert(request->arena, |
2096 certID, | 2091 certID, |
2097 singleCert, | 2092 singleCert, |
2098 time, | 2093 time, |
2099 addServiceLocator); | 2094 addServiceLocator); |
2100 if (request->tbsRequest->requestList == NULL) { | 2095 if (request->tbsRequest->requestList == NULL) { |
2101 PORT_FreeArena(request->arena, PR_FALSE); | 2096 PORT_FreeArena(request->arena, PR_FALSE); |
2102 return NULL; | 2097 return NULL; |
2103 } | 2098 } |
2104 return request; | 2099 return request; |
2105 } | 2100 } |
2106 | 2101 |
2107 /* | 2102 /* |
2108 * FUNCTION: CERT_CreateOCSPRequest | 2103 * FUNCTION: CERT_CreateOCSPRequest |
2109 * Creates a CERTOCSPRequest, requesting the status of the certs in | 2104 * Creates a CERTOCSPRequest, requesting the status of the certs in |
2110 * the given list. | 2105 * the given list. |
2111 * INPUTS: | 2106 * INPUTS: |
2112 * CERTCertList *certList | 2107 * CERTCertList *certList |
2113 * A list of certs for which status will be requested. | 2108 * A list of certs for which status will be requested. |
2114 * Note that all of these certificates should have the same issuer, | 2109 * Note that all of these certificates should have the same issuer, |
2115 * or it's expected the response will be signed by a trusted responder. | 2110 * or it's expected the response will be signed by a trusted responder. |
2116 * If the certs need to be broken up into multiple requests, that | 2111 * If the certs need to be broken up into multiple requests, that |
2117 * must be handled by the caller (and thus by having multiple calls | 2112 * must be handled by the caller (and thus by having multiple calls |
2118 * to this routine), who knows about where the request(s) are being | 2113 * to this routine), who knows about where the request(s) are being |
2119 * sent and whether there are any trusted responders in place. | 2114 * sent and whether there are any trusted responders in place. |
2120 * PRTime time | 2115 * PRTime time |
2121 * Indicates the time for which the certificate status is to be | 2116 * Indicates the time for which the certificate status is to be |
2122 * determined -- this may be used in the search for the cert's issuer | 2117 * determined -- this may be used in the search for the cert's issuer |
2123 * but has no effect on the request itself. | 2118 * but has no effect on the request itself. |
2124 * PRBool addServiceLocator | 2119 * PRBool addServiceLocator |
2125 * If true, the Service Locator extension should be added to the | 2120 * If true, the Service Locator extension should be added to the |
2126 * single request(s) for each cert. | 2121 * single request(s) for each cert. |
2127 * CERTCertificate *signerCert | 2122 * CERTCertificate *signerCert |
2128 * If non-NULL, means sign the request using this cert. Otherwise, | 2123 * If non-NULL, means sign the request using this cert. Otherwise, |
2129 * do not sign. | 2124 * do not sign. |
2130 * XXX note that request signing is not yet supported; see comment in code | 2125 * XXX note that request signing is not yet supported; see comment in code |
2131 * RETURN: | 2126 * RETURN: |
2132 * A pointer to a CERTOCSPRequest structure containing an OCSP request | 2127 * A pointer to a CERTOCSPRequest structure containing an OCSP request |
2133 * for the cert list. On error, null is returned, with an error set | 2128 * for the cert list. On error, null is returned, with an error set |
2134 * indicating the reason. This is likely SEC_ERROR_UNKNOWN_ISSUER. | 2129 * indicating the reason. This is likely SEC_ERROR_UNKNOWN_ISSUER. |
2135 * (The issuer is needed to create a request for the certificate.) | 2130 * (The issuer is needed to create a request for the certificate.) |
2136 * Other errors are low-level problems (no memory, bad database, etc.). | 2131 * Other errors are low-level problems (no memory, bad database, etc.). |
2137 */ | 2132 */ |
2138 CERTOCSPRequest * | 2133 CERTOCSPRequest * |
2139 CERT_CreateOCSPRequest(CERTCertList *certList, PRTime time, | 2134 CERT_CreateOCSPRequest(CERTCertList *certList, PRTime time, |
2140 » » PRBool addServiceLocator, | 2135 PRBool addServiceLocator, |
2141 » » CERTCertificate *signerCert) | 2136 CERTCertificate *signerCert) |
2142 { | 2137 { |
2143 CERTOCSPRequest *request = NULL; | 2138 CERTOCSPRequest *request = NULL; |
2144 | 2139 |
2145 if (!certList) { | 2140 if (!certList) { |
2146 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 2141 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
2147 return NULL; | 2142 return NULL; |
2148 } | 2143 } |
2149 /* | 2144 /* |
2150 * XXX When we are prepared to put signing of requests back in, | 2145 * XXX When we are prepared to put signing of requests back in, |
2151 * we will need to allocate a signature | 2146 * we will need to allocate a signature |
2152 * structure for the request, fill in the "derCerts" field in it, | 2147 * structure for the request, fill in the "derCerts" field in it, |
2153 * save the signerCert there, as well as fill in the "requestorName" | 2148 * save the signerCert there, as well as fill in the "requestorName" |
2154 * field of the tbsRequest. | 2149 * field of the tbsRequest. |
2155 */ | 2150 */ |
2156 if (signerCert != NULL) { | 2151 if (signerCert != NULL) { |
2157 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | 2152 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
2158 return NULL; | 2153 return NULL; |
2159 } | 2154 } |
2160 request = ocsp_prepareEmptyOCSPRequest(); | 2155 request = ocsp_prepareEmptyOCSPRequest(); |
2161 if (!request) | 2156 if (!request) |
2162 return NULL; | 2157 return NULL; |
2163 /* | 2158 /* |
2164 * Now create the list of single requests, one for each cert. | 2159 * Now create the list of single requests, one for each cert. |
2165 */ | 2160 */ |
2166 request->tbsRequest->requestList = | 2161 request->tbsRequest->requestList = |
2167 ocsp_CreateSingleRequestList(request->arena, | 2162 ocsp_CreateSingleRequestList(request->arena, |
2168 certList, | 2163 certList, |
2169 time, | 2164 time, |
2170 addServiceLocator); | 2165 addServiceLocator); |
2171 if (request->tbsRequest->requestList == NULL) { | 2166 if (request->tbsRequest->requestList == NULL) { |
2172 PORT_FreeArena(request->arena, PR_FALSE); | 2167 PORT_FreeArena(request->arena, PR_FALSE); |
2173 return NULL; | 2168 return NULL; |
2174 } | 2169 } |
2175 return request; | 2170 return request; |
2176 } | 2171 } |
2177 | 2172 |
2178 /* | 2173 /* |
2179 * FUNCTION: CERT_AddOCSPAcceptableResponses | 2174 * FUNCTION: CERT_AddOCSPAcceptableResponses |
2180 * Add the AcceptableResponses extension to an OCSP Request. | 2175 * Add the AcceptableResponses extension to an OCSP Request. |
2181 * INPUTS: | 2176 * INPUTS: |
2182 * CERTOCSPRequest *request | 2177 * CERTOCSPRequest *request |
2183 * The request to which the extension should be added. | 2178 * The request to which the extension should be added. |
2184 * ... | 2179 * ... |
2185 * A list (of one or more) of SECOidTag -- each of the response types | 2180 * A list (of one or more) of SECOidTag -- each of the response types |
2186 * to be added. The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE. | 2181 * to be added. The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE. |
2187 * (This marks the end of the list, and it must be specified because a | 2182 * (This marks the end of the list, and it must be specified because a |
2188 * client conforming to the OCSP standard is required to handle the basic | 2183 * client conforming to the OCSP standard is required to handle the basic |
2189 * response type.) The OIDs are not checked in any way. | 2184 * response type.) The OIDs are not checked in any way. |
2190 * RETURN: | 2185 * RETURN: |
2191 * SECSuccess if the extension is added; SECFailure if anything goes wrong. | 2186 * SECSuccess if the extension is added; SECFailure if anything goes wrong. |
2192 * All errors are internal or low-level problems (e.g. no memory). | 2187 * All errors are internal or low-level problems (e.g. no memory). |
2193 */ | 2188 */ |
2194 | 2189 |
2195 void SetRequestExts(void *object, CERTCertExtension **exts) | 2190 void |
| 2191 SetRequestExts(void *object, CERTCertExtension **exts) |
2196 { | 2192 { |
2197 CERTOCSPRequest *request = (CERTOCSPRequest *)object; | 2193 CERTOCSPRequest *request = (CERTOCSPRequest *)object; |
2198 | 2194 |
2199 request->tbsRequest->requestExtensions = exts; | 2195 request->tbsRequest->requestExtensions = exts; |
2200 } | 2196 } |
2201 | 2197 |
2202 SECStatus | 2198 SECStatus |
2203 CERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request, | 2199 CERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request, |
2204 » » » » SECOidTag responseType0, ...) | 2200 SECOidTag responseType0, ...) |
2205 { | 2201 { |
2206 void *extHandle; | 2202 void *extHandle; |
2207 va_list ap; | 2203 va_list ap; |
2208 int i, count; | 2204 int i, count; |
2209 SECOidTag responseType; | 2205 SECOidTag responseType; |
2210 SECOidData *responseOid; | 2206 SECOidData *responseOid; |
2211 SECItem **acceptableResponses = NULL; | 2207 SECItem **acceptableResponses = NULL; |
2212 SECStatus rv = SECFailure; | 2208 SECStatus rv = SECFailure; |
2213 | 2209 |
2214 extHandle = request->tbsRequest->extensionHandle; | 2210 extHandle = request->tbsRequest->extensionHandle; |
2215 if (extHandle == NULL) { | 2211 if (extHandle == NULL) { |
2216 » extHandle = cert_StartExtensions(request, request->arena, SetRequestExts
); | 2212 extHandle = cert_StartExtensions(request, request->arena, SetRequestExts
); |
2217 » if (extHandle == NULL) | 2213 if (extHandle == NULL) |
2218 » goto loser; | 2214 goto loser; |
2219 } | 2215 } |
2220 | 2216 |
2221 /* Count number of OIDS going into the extension value. */ | 2217 /* Count number of OIDS going into the extension value. */ |
2222 count = 1; | 2218 count = 1; |
2223 if (responseType0 != SEC_OID_PKIX_OCSP_BASIC_RESPONSE) { | 2219 if (responseType0 != SEC_OID_PKIX_OCSP_BASIC_RESPONSE) { |
2224 » va_start(ap, responseType0); | 2220 va_start(ap, responseType0); |
2225 » do { | 2221 do { |
2226 » count++; | 2222 count++; |
2227 » responseType = va_arg(ap, SECOidTag); | 2223 responseType = va_arg(ap, SECOidTag); |
2228 » } while (responseType != SEC_OID_PKIX_OCSP_BASIC_RESPONSE); | 2224 } while (responseType != SEC_OID_PKIX_OCSP_BASIC_RESPONSE); |
2229 » va_end(ap); | 2225 va_end(ap); |
2230 } | 2226 } |
2231 | 2227 |
2232 acceptableResponses = PORT_NewArray(SECItem *, count + 1); | 2228 acceptableResponses = PORT_NewArray(SECItem *, count + 1); |
2233 if (acceptableResponses == NULL) | 2229 if (acceptableResponses == NULL) |
2234 » goto loser; | 2230 goto loser; |
2235 | 2231 |
2236 i = 0; | 2232 i = 0; |
2237 responseOid = SECOID_FindOIDByTag(responseType0); | 2233 responseOid = SECOID_FindOIDByTag(responseType0); |
2238 acceptableResponses[i++] = &(responseOid->oid); | 2234 acceptableResponses[i++] = &(responseOid->oid); |
2239 if (count > 1) { | 2235 if (count > 1) { |
2240 » va_start(ap, responseType0); | 2236 va_start(ap, responseType0); |
2241 » for ( ; i < count; i++) { | 2237 for (; i < count; i++) { |
2242 » responseType = va_arg(ap, SECOidTag); | 2238 responseType = va_arg(ap, SECOidTag); |
2243 » responseOid = SECOID_FindOIDByTag(responseType); | 2239 responseOid = SECOID_FindOIDByTag(responseType); |
2244 » acceptableResponses[i] = &(responseOid->oid); | 2240 acceptableResponses[i] = &(responseOid->oid); |
2245 » } | 2241 } |
2246 » va_end(ap); | 2242 va_end(ap); |
2247 } | 2243 } |
2248 acceptableResponses[i] = NULL; | 2244 acceptableResponses[i] = NULL; |
2249 | 2245 |
2250 rv = CERT_EncodeAndAddExtension(extHandle, SEC_OID_PKIX_OCSP_RESPONSE, | 2246 rv = CERT_EncodeAndAddExtension(extHandle, SEC_OID_PKIX_OCSP_RESPONSE, |
2251 &acceptableResponses, PR_FALSE, | 2247 &acceptableResponses, PR_FALSE, |
2252 SEC_ASN1_GET(SEC_SequenceOfObjectIDTemplate)); | 2248 SEC_ASN1_GET(SEC_SequenceOfObjectIDTemplate)
); |
2253 if (rv != SECSuccess) | 2249 if (rv != SECSuccess) |
2254 » goto loser; | 2250 goto loser; |
2255 | 2251 |
2256 PORT_Free(acceptableResponses); | 2252 PORT_Free(acceptableResponses); |
2257 if (request->tbsRequest->extensionHandle == NULL) | 2253 if (request->tbsRequest->extensionHandle == NULL) |
2258 » request->tbsRequest->extensionHandle = extHandle; | 2254 request->tbsRequest->extensionHandle = extHandle; |
2259 return SECSuccess; | 2255 return SECSuccess; |
2260 | 2256 |
2261 loser: | 2257 loser: |
2262 if (acceptableResponses != NULL) | 2258 if (acceptableResponses != NULL) |
2263 » PORT_Free(acceptableResponses); | 2259 PORT_Free(acceptableResponses); |
2264 if (extHandle != NULL) | 2260 if (extHandle != NULL) |
2265 » (void) CERT_FinishExtensions(extHandle); | 2261 (void)CERT_FinishExtensions(extHandle); |
2266 return rv; | 2262 return rv; |
2267 } | 2263 } |
2268 | 2264 |
2269 | |
2270 /* | 2265 /* |
2271 * FUNCTION: CERT_DestroyOCSPRequest | 2266 * FUNCTION: CERT_DestroyOCSPRequest |
2272 * Frees an OCSP Request structure. | 2267 * Frees an OCSP Request structure. |
2273 * INPUTS: | 2268 * INPUTS: |
2274 * CERTOCSPRequest *request | 2269 * CERTOCSPRequest *request |
2275 * Pointer to CERTOCSPRequest to be freed. | 2270 * Pointer to CERTOCSPRequest to be freed. |
2276 * RETURN: | 2271 * RETURN: |
2277 * No return value; no errors. | 2272 * No return value; no errors. |
2278 */ | 2273 */ |
2279 void | 2274 void |
2280 CERT_DestroyOCSPRequest(CERTOCSPRequest *request) | 2275 CERT_DestroyOCSPRequest(CERTOCSPRequest *request) |
2281 { | 2276 { |
2282 if (request == NULL) | 2277 if (request == NULL) |
2283 » return; | 2278 return; |
2284 | 2279 |
2285 if (request->tbsRequest != NULL) { | 2280 if (request->tbsRequest != NULL) { |
2286 » if (request->tbsRequest->requestorName != NULL) | 2281 if (request->tbsRequest->requestorName != NULL) |
2287 » CERT_DestroyGeneralNameList(request->tbsRequest->requestorName); | 2282 CERT_DestroyGeneralNameList(request->tbsRequest->requestorName); |
2288 » if (request->tbsRequest->extensionHandle != NULL) | 2283 if (request->tbsRequest->extensionHandle != NULL) |
2289 » (void) CERT_FinishExtensions(request->tbsRequest->extensionHandle); | 2284 (void)CERT_FinishExtensions(request->tbsRequest->extensionHandle); |
2290 } | 2285 } |
2291 | 2286 |
2292 if (request->optionalSignature != NULL) { | 2287 if (request->optionalSignature != NULL) { |
2293 » if (request->optionalSignature->cert != NULL) | 2288 if (request->optionalSignature->cert != NULL) |
2294 » CERT_DestroyCertificate(request->optionalSignature->cert); | 2289 CERT_DestroyCertificate(request->optionalSignature->cert); |
2295 | 2290 |
2296 » /* | 2291 /* |
2297 * XXX Need to free derCerts? Or do they come out of arena? | 2292 * XXX Need to free derCerts? Or do they come out of arena? |
2298 * (Currently we never fill in derCerts, which is why the | 2293 * (Currently we never fill in derCerts, which is why the |
2299 * answer is not obvious. Once we do, add any necessary code | 2294 * answer is not obvious. Once we do, add any necessary code |
2300 * here and remove this comment.) | 2295 * here and remove this comment.) |
2301 */ | 2296 */ |
2302 } | 2297 } |
2303 | 2298 |
2304 /* | 2299 /* |
2305 * We should actually never have a request without an arena, | 2300 * We should actually never have a request without an arena, |
2306 * but check just in case. (If there isn't one, there is not | 2301 * but check just in case. (If there isn't one, there is not |
2307 * much we can do about it...) | 2302 * much we can do about it...) |
2308 */ | 2303 */ |
2309 PORT_Assert(request->arena != NULL); | 2304 PORT_Assert(request->arena != NULL); |
2310 if (request->arena != NULL) | 2305 if (request->arena != NULL) |
2311 » PORT_FreeArena(request->arena, PR_FALSE); | 2306 PORT_FreeArena(request->arena, PR_FALSE); |
2312 } | 2307 } |
2313 | 2308 |
2314 | |
2315 /* | 2309 /* |
2316 * RESPONSE SUPPORT FUNCTIONS (encode/create/decode/destroy): | 2310 * RESPONSE SUPPORT FUNCTIONS (encode/create/decode/destroy): |
2317 */ | 2311 */ |
2318 | 2312 |
2319 /* | 2313 /* |
2320 * Helper function for encoding or decoding a ResponderID -- based on the | 2314 * Helper function for encoding or decoding a ResponderID -- based on the |
2321 * given type, return the associated template for that choice. | 2315 * given type, return the associated template for that choice. |
2322 */ | 2316 */ |
2323 static const SEC_ASN1Template * | 2317 static const SEC_ASN1Template * |
2324 ocsp_ResponderIDTemplateByType(CERTOCSPResponderIDType responderIDType) | 2318 ocsp_ResponderIDTemplateByType(CERTOCSPResponderIDType responderIDType) |
2325 { | 2319 { |
2326 const SEC_ASN1Template *responderIDTemplate; | 2320 const SEC_ASN1Template *responderIDTemplate; |
2327 | 2321 |
2328 switch (responderIDType) { | 2322 switch (responderIDType) { |
2329 » case ocspResponderID_byName: | 2323 case ocspResponderID_byName: |
2330 » responderIDTemplate = ocsp_ResponderIDByNameTemplate; | 2324 responderIDTemplate = ocsp_ResponderIDByNameTemplate; |
2331 » break; | 2325 break; |
2332 » case ocspResponderID_byKey: | 2326 case ocspResponderID_byKey: |
2333 » responderIDTemplate = ocsp_ResponderIDByKeyTemplate; | 2327 responderIDTemplate = ocsp_ResponderIDByKeyTemplate; |
2334 » break; | 2328 break; |
2335 » case ocspResponderID_other: | 2329 case ocspResponderID_other: |
2336 » default: | 2330 default: |
2337 » PORT_Assert(responderIDType == ocspResponderID_other); | 2331 PORT_Assert(responderIDType == ocspResponderID_other); |
2338 » responderIDTemplate = ocsp_ResponderIDOtherTemplate; | 2332 responderIDTemplate = ocsp_ResponderIDOtherTemplate; |
2339 » break; | 2333 break; |
2340 } | 2334 } |
2341 | 2335 |
2342 return responderIDTemplate; | 2336 return responderIDTemplate; |
2343 } | 2337 } |
2344 | 2338 |
2345 /* | 2339 /* |
2346 * Helper function for encoding or decoding a CertStatus -- based on the | 2340 * Helper function for encoding or decoding a CertStatus -- based on the |
2347 * given type, return the associated template for that choice. | 2341 * given type, return the associated template for that choice. |
2348 */ | 2342 */ |
2349 static const SEC_ASN1Template * | 2343 static const SEC_ASN1Template * |
2350 ocsp_CertStatusTemplateByType(ocspCertStatusType certStatusType) | 2344 ocsp_CertStatusTemplateByType(ocspCertStatusType certStatusType) |
2351 { | 2345 { |
2352 const SEC_ASN1Template *certStatusTemplate; | 2346 const SEC_ASN1Template *certStatusTemplate; |
2353 | 2347 |
2354 switch (certStatusType) { | 2348 switch (certStatusType) { |
2355 » case ocspCertStatus_good: | 2349 case ocspCertStatus_good: |
2356 » certStatusTemplate = ocsp_CertStatusGoodTemplate; | 2350 certStatusTemplate = ocsp_CertStatusGoodTemplate; |
2357 » break; | 2351 break; |
2358 » case ocspCertStatus_revoked: | 2352 case ocspCertStatus_revoked: |
2359 » certStatusTemplate = ocsp_CertStatusRevokedTemplate; | 2353 certStatusTemplate = ocsp_CertStatusRevokedTemplate; |
2360 » break; | 2354 break; |
2361 » case ocspCertStatus_unknown: | 2355 case ocspCertStatus_unknown: |
2362 » certStatusTemplate = ocsp_CertStatusUnknownTemplate; | 2356 certStatusTemplate = ocsp_CertStatusUnknownTemplate; |
2363 » break; | 2357 break; |
2364 » case ocspCertStatus_other: | 2358 case ocspCertStatus_other: |
2365 » default: | 2359 default: |
2366 » PORT_Assert(certStatusType == ocspCertStatus_other); | 2360 PORT_Assert(certStatusType == ocspCertStatus_other); |
2367 » certStatusTemplate = ocsp_CertStatusOtherTemplate; | 2361 certStatusTemplate = ocsp_CertStatusOtherTemplate; |
2368 » break; | 2362 break; |
2369 } | 2363 } |
2370 | 2364 |
2371 return certStatusTemplate; | 2365 return certStatusTemplate; |
2372 } | 2366 } |
2373 | 2367 |
2374 /* | 2368 /* |
2375 * Helper function for decoding a certStatus -- turn the actual DER tag | 2369 * Helper function for decoding a certStatus -- turn the actual DER tag |
2376 * into our local translation. | 2370 * into our local translation. |
2377 */ | 2371 */ |
2378 static ocspCertStatusType | 2372 static ocspCertStatusType |
2379 ocsp_CertStatusTypeByTag(int derTag) | 2373 ocsp_CertStatusTypeByTag(int derTag) |
2380 { | 2374 { |
2381 ocspCertStatusType certStatusType; | 2375 ocspCertStatusType certStatusType; |
2382 | 2376 |
2383 switch (derTag) { | 2377 switch (derTag) { |
2384 » case 0: | 2378 case 0: |
2385 » certStatusType = ocspCertStatus_good; | 2379 certStatusType = ocspCertStatus_good; |
2386 » break; | 2380 break; |
2387 » case 1: | 2381 case 1: |
2388 » certStatusType = ocspCertStatus_revoked; | 2382 certStatusType = ocspCertStatus_revoked; |
2389 » break; | 2383 break; |
2390 » case 2: | 2384 case 2: |
2391 » certStatusType = ocspCertStatus_unknown; | 2385 certStatusType = ocspCertStatus_unknown; |
2392 » break; | 2386 break; |
2393 » default: | 2387 default: |
2394 » certStatusType = ocspCertStatus_other; | 2388 certStatusType = ocspCertStatus_other; |
2395 » break; | 2389 break; |
2396 } | 2390 } |
2397 | 2391 |
2398 return certStatusType; | 2392 return certStatusType; |
2399 } | 2393 } |
2400 | 2394 |
2401 /* | 2395 /* |
2402 * Helper function for decoding SingleResponses -- they each contain | 2396 * Helper function for decoding SingleResponses -- they each contain |
2403 * a status which is encoded as CHOICE, which needs to be decoded "by hand". | 2397 * a status which is encoded as CHOICE, which needs to be decoded "by hand". |
2404 * | 2398 * |
2405 * Note -- on error, this routine does not release the memory it may | 2399 * Note -- on error, this routine does not release the memory it may |
2406 * have allocated; it expects its caller to do that. | 2400 * have allocated; it expects its caller to do that. |
2407 */ | 2401 */ |
2408 static SECStatus | 2402 static SECStatus |
2409 ocsp_FinishDecodingSingleResponses(PLArenaPool *reqArena, | 2403 ocsp_FinishDecodingSingleResponses(PLArenaPool *reqArena, |
2410 » » » » CERTOCSPSingleResponse **responses) | 2404 CERTOCSPSingleResponse **responses) |
2411 { | 2405 { |
2412 ocspCertStatus *certStatus; | 2406 ocspCertStatus *certStatus; |
2413 ocspCertStatusType certStatusType; | 2407 ocspCertStatusType certStatusType; |
2414 const SEC_ASN1Template *certStatusTemplate; | 2408 const SEC_ASN1Template *certStatusTemplate; |
2415 int derTag; | 2409 int derTag; |
2416 int i; | 2410 int i; |
2417 SECStatus rv = SECFailure; | 2411 SECStatus rv = SECFailure; |
2418 | 2412 |
2419 if (!reqArena) { | 2413 if (!reqArena) { |
2420 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 2414 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
2421 return SECFailure; | 2415 return SECFailure; |
2422 } | 2416 } |
2423 | 2417 |
2424 if (responses == NULL)» » » /* nothing to do */ | 2418 if (responses == NULL) /* nothing to do */ |
2425 » return SECSuccess; | 2419 return SECSuccess; |
2426 | 2420 |
2427 for (i = 0; responses[i] != NULL; i++) { | 2421 for (i = 0; responses[i] != NULL; i++) { |
2428 SECItem* newStatus; | 2422 SECItem *newStatus; |
2429 » /* | 2423 /* |
2430 * The following assert points out internal errors (problems in | 2424 * The following assert points out internal errors (problems in |
2431 * the template definitions or in the ASN.1 decoder itself, etc.). | 2425 * the template definitions or in the ASN.1 decoder itself, etc.). |
2432 */ | 2426 */ |
2433 » PORT_Assert(responses[i]->derCertStatus.data != NULL); | 2427 PORT_Assert(responses[i]->derCertStatus.data != NULL); |
2434 | 2428 |
2435 » derTag = responses[i]->derCertStatus.data[0] & SEC_ASN1_TAGNUM_MASK; | 2429 derTag = responses[i]->derCertStatus.data[0] & SEC_ASN1_TAGNUM_MASK; |
2436 » certStatusType = ocsp_CertStatusTypeByTag(derTag); | 2430 certStatusType = ocsp_CertStatusTypeByTag(derTag); |
2437 » certStatusTemplate = ocsp_CertStatusTemplateByType(certStatusType); | 2431 certStatusTemplate = ocsp_CertStatusTemplateByType(certStatusType); |
2438 | 2432 |
2439 » certStatus = PORT_ArenaZAlloc(reqArena, sizeof(ocspCertStatus)); | 2433 certStatus = PORT_ArenaZAlloc(reqArena, sizeof(ocspCertStatus)); |
2440 » if (certStatus == NULL) { | 2434 if (certStatus == NULL) { |
2441 » goto loser; | 2435 goto loser; |
2442 » } | 2436 } |
2443 newStatus = SECITEM_ArenaDupItem(reqArena, &responses[i]->derCertStatus)
; | 2437 newStatus = SECITEM_ArenaDupItem(reqArena, &responses[i]->derCertStatus)
; |
2444 if (!newStatus) { | 2438 if (!newStatus) { |
2445 goto loser; | 2439 goto loser; |
2446 } | 2440 } |
2447 » rv = SEC_QuickDERDecodeItem(reqArena, certStatus, certStatusTemplate, | 2441 rv = SEC_QuickDERDecodeItem(reqArena, certStatus, certStatusTemplate, |
2448 » » » » newStatus); | 2442 newStatus); |
2449 » if (rv != SECSuccess) { | 2443 if (rv != SECSuccess) { |
2450 » if (PORT_GetError() == SEC_ERROR_BAD_DER) | 2444 if (PORT_GetError() == SEC_ERROR_BAD_DER) |
2451 » » PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); | 2445 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); |
2452 » goto loser; | 2446 goto loser; |
2453 » } | 2447 } |
2454 | 2448 |
2455 » certStatus->certStatusType = certStatusType; | 2449 certStatus->certStatusType = certStatusType; |
2456 » responses[i]->certStatus = certStatus; | 2450 responses[i]->certStatus = certStatus; |
2457 } | 2451 } |
2458 | 2452 |
2459 return SECSuccess; | 2453 return SECSuccess; |
2460 | 2454 |
2461 loser: | 2455 loser: |
2462 return rv; | 2456 return rv; |
2463 } | 2457 } |
2464 | 2458 |
2465 /* | 2459 /* |
2466 * Helper function for decoding a responderID -- turn the actual DER tag | 2460 * Helper function for decoding a responderID -- turn the actual DER tag |
2467 * into our local translation. | 2461 * into our local translation. |
2468 */ | 2462 */ |
2469 static CERTOCSPResponderIDType | 2463 static CERTOCSPResponderIDType |
2470 ocsp_ResponderIDTypeByTag(int derTag) | 2464 ocsp_ResponderIDTypeByTag(int derTag) |
2471 { | 2465 { |
2472 CERTOCSPResponderIDType responderIDType; | 2466 CERTOCSPResponderIDType responderIDType; |
2473 | 2467 |
2474 switch (derTag) { | 2468 switch (derTag) { |
2475 » case 1: | 2469 case 1: |
2476 » responderIDType = ocspResponderID_byName; | 2470 responderIDType = ocspResponderID_byName; |
2477 » break; | 2471 break; |
2478 » case 2: | 2472 case 2: |
2479 » responderIDType = ocspResponderID_byKey; | 2473 responderIDType = ocspResponderID_byKey; |
2480 » break; | 2474 break; |
2481 » default: | 2475 default: |
2482 » responderIDType = ocspResponderID_other; | 2476 responderIDType = ocspResponderID_other; |
2483 » break; | 2477 break; |
2484 } | 2478 } |
2485 | 2479 |
2486 return responderIDType; | 2480 return responderIDType; |
2487 } | 2481 } |
2488 | 2482 |
2489 /* | 2483 /* |
2490 * Decode "src" as a BasicOCSPResponse, returning the result. | 2484 * Decode "src" as a BasicOCSPResponse, returning the result. |
2491 */ | 2485 */ |
2492 static ocspBasicOCSPResponse * | 2486 static ocspBasicOCSPResponse * |
2493 ocsp_DecodeBasicOCSPResponse(PLArenaPool *arena, SECItem *src) | 2487 ocsp_DecodeBasicOCSPResponse(PLArenaPool *arena, SECItem *src) |
2494 { | 2488 { |
2495 void *mark; | 2489 void *mark; |
2496 ocspBasicOCSPResponse *basicResponse; | 2490 ocspBasicOCSPResponse *basicResponse; |
2497 ocspResponseData *responseData; | 2491 ocspResponseData *responseData; |
2498 ocspResponderID *responderID; | 2492 ocspResponderID *responderID; |
2499 CERTOCSPResponderIDType responderIDType; | 2493 CERTOCSPResponderIDType responderIDType; |
2500 const SEC_ASN1Template *responderIDTemplate; | 2494 const SEC_ASN1Template *responderIDTemplate; |
2501 int derTag; | 2495 int derTag; |
2502 SECStatus rv; | 2496 SECStatus rv; |
2503 SECItem newsrc; | 2497 SECItem newsrc; |
2504 | 2498 |
2505 mark = PORT_ArenaMark(arena); | 2499 mark = PORT_ArenaMark(arena); |
2506 | 2500 |
2507 basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse)); | 2501 basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse)); |
2508 if (basicResponse == NULL) { | 2502 if (basicResponse == NULL) { |
2509 » goto loser; | 2503 goto loser; |
2510 } | 2504 } |
2511 | 2505 |
2512 /* copy the DER into the arena, since Quick DER returns data that points | 2506 /* copy the DER into the arena, since Quick DER returns data that points |
2513 into the DER input, which may get freed by the caller */ | 2507 into the DER input, which may get freed by the caller */ |
2514 rv = SECITEM_CopyItem(arena, &newsrc, src); | 2508 rv = SECITEM_CopyItem(arena, &newsrc, src); |
2515 if ( rv != SECSuccess ) { | 2509 if (rv != SECSuccess) { |
2516 » goto loser; | 2510 goto loser; |
2517 } | 2511 } |
2518 | 2512 |
2519 rv = SEC_QuickDERDecodeItem(arena, basicResponse, | 2513 rv = SEC_QuickDERDecodeItem(arena, basicResponse, |
2520 » » » ocsp_BasicOCSPResponseTemplate, &newsrc); | 2514 ocsp_BasicOCSPResponseTemplate, &newsrc); |
2521 if (rv != SECSuccess) { | 2515 if (rv != SECSuccess) { |
2522 » if (PORT_GetError() == SEC_ERROR_BAD_DER) | 2516 if (PORT_GetError() == SEC_ERROR_BAD_DER) |
2523 » PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); | 2517 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); |
2524 » goto loser; | 2518 goto loser; |
2525 } | 2519 } |
2526 | 2520 |
2527 responseData = basicResponse->tbsResponseData; | 2521 responseData = basicResponse->tbsResponseData; |
2528 | 2522 |
2529 /* | 2523 /* |
2530 * The following asserts point out internal errors (problems in | 2524 * The following asserts point out internal errors (problems in |
2531 * the template definitions or in the ASN.1 decoder itself, etc.). | 2525 * the template definitions or in the ASN.1 decoder itself, etc.). |
2532 */ | 2526 */ |
2533 PORT_Assert(responseData != NULL); | 2527 PORT_Assert(responseData != NULL); |
2534 PORT_Assert(responseData->derResponderID.data != NULL); | 2528 PORT_Assert(responseData->derResponderID.data != NULL); |
2535 | 2529 |
2536 /* | 2530 /* |
2537 * XXX Because responderID is a CHOICE, which is not currently handled | 2531 * XXX Because responderID is a CHOICE, which is not currently handled |
2538 * by our ASN.1 decoder, we have to decode it "by hand". | 2532 * by our ASN.1 decoder, we have to decode it "by hand". |
2539 */ | 2533 */ |
2540 derTag = responseData->derResponderID.data[0] & SEC_ASN1_TAGNUM_MASK; | 2534 derTag = responseData->derResponderID.data[0] & SEC_ASN1_TAGNUM_MASK; |
2541 responderIDType = ocsp_ResponderIDTypeByTag(derTag); | 2535 responderIDType = ocsp_ResponderIDTypeByTag(derTag); |
2542 responderIDTemplate = ocsp_ResponderIDTemplateByType(responderIDType); | 2536 responderIDTemplate = ocsp_ResponderIDTemplateByType(responderIDType); |
2543 | 2537 |
2544 responderID = PORT_ArenaZAlloc(arena, sizeof(ocspResponderID)); | 2538 responderID = PORT_ArenaZAlloc(arena, sizeof(ocspResponderID)); |
2545 if (responderID == NULL) { | 2539 if (responderID == NULL) { |
2546 » goto loser; | 2540 goto loser; |
2547 } | 2541 } |
2548 | 2542 |
2549 rv = SEC_QuickDERDecodeItem(arena, responderID, responderIDTemplate, | 2543 rv = SEC_QuickDERDecodeItem(arena, responderID, responderIDTemplate, |
2550 » » » &responseData->derResponderID); | 2544 &responseData->derResponderID); |
2551 if (rv != SECSuccess) { | 2545 if (rv != SECSuccess) { |
2552 » if (PORT_GetError() == SEC_ERROR_BAD_DER) | 2546 if (PORT_GetError() == SEC_ERROR_BAD_DER) |
2553 » PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); | 2547 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); |
2554 » goto loser; | 2548 goto loser; |
2555 } | 2549 } |
2556 | 2550 |
2557 responderID->responderIDType = responderIDType; | 2551 responderID->responderIDType = responderIDType; |
2558 responseData->responderID = responderID; | 2552 responseData->responderID = responderID; |
2559 | 2553 |
2560 /* | 2554 /* |
2561 * XXX Each SingleResponse also contains a CHOICE, which has to be | 2555 * XXX Each SingleResponse also contains a CHOICE, which has to be |
2562 * fixed up by hand. | 2556 * fixed up by hand. |
2563 */ | 2557 */ |
2564 rv = ocsp_FinishDecodingSingleResponses(arena, responseData->responses); | 2558 rv = ocsp_FinishDecodingSingleResponses(arena, responseData->responses); |
2565 if (rv != SECSuccess) { | 2559 if (rv != SECSuccess) { |
2566 » goto loser; | 2560 goto loser; |
2567 } | 2561 } |
2568 | 2562 |
2569 PORT_ArenaUnmark(arena, mark); | 2563 PORT_ArenaUnmark(arena, mark); |
2570 return basicResponse; | 2564 return basicResponse; |
2571 | 2565 |
2572 loser: | 2566 loser: |
2573 PORT_ArenaRelease(arena, mark); | 2567 PORT_ArenaRelease(arena, mark); |
2574 return NULL; | 2568 return NULL; |
2575 } | 2569 } |
2576 | 2570 |
2577 | |
2578 /* | 2571 /* |
2579 * Decode the responseBytes based on the responseType found in "rbytes", | 2572 * Decode the responseBytes based on the responseType found in "rbytes", |
2580 * leaving the resulting translated/decoded information in there as well. | 2573 * leaving the resulting translated/decoded information in there as well. |
2581 */ | 2574 */ |
2582 static SECStatus | 2575 static SECStatus |
2583 ocsp_DecodeResponseBytes(PLArenaPool *arena, ocspResponseBytes *rbytes) | 2576 ocsp_DecodeResponseBytes(PLArenaPool *arena, ocspResponseBytes *rbytes) |
2584 { | 2577 { |
2585 if (rbytes == NULL) { | 2578 if (rbytes == NULL) { |
2586 » PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE); | 2579 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE); |
2587 » return SECFailure; | 2580 return SECFailure; |
2588 } | 2581 } |
2589 | 2582 |
2590 rbytes->responseTypeTag = SECOID_FindOIDTag(&rbytes->responseType); | 2583 rbytes->responseTypeTag = SECOID_FindOIDTag(&rbytes->responseType); |
2591 switch (rbytes->responseTypeTag) { | 2584 switch (rbytes->responseTypeTag) { |
2592 » case SEC_OID_PKIX_OCSP_BASIC_RESPONSE: | 2585 case SEC_OID_PKIX_OCSP_BASIC_RESPONSE: { |
2593 » { | 2586 ocspBasicOCSPResponse *basicResponse; |
2594 » » ocspBasicOCSPResponse *basicResponse; | |
2595 | 2587 |
2596 » » basicResponse = ocsp_DecodeBasicOCSPResponse(arena, | 2588 basicResponse = ocsp_DecodeBasicOCSPResponse(arena, |
2597 » » » » » » » &rbytes->response); | 2589 &rbytes->response); |
2598 » » if (basicResponse == NULL) | 2590 if (basicResponse == NULL) |
2599 » » return SECFailure; | 2591 return SECFailure; |
2600 | 2592 |
2601 » » rbytes->decodedResponse.basic = basicResponse; | 2593 rbytes->decodedResponse.basic = basicResponse; |
2602 » } | 2594 } break; |
2603 » break; | |
2604 | 2595 |
2605 » /* | 2596 /* |
2606 * Add new/future response types here. | 2597 * Add new/future response types here. |
2607 */ | 2598 */ |
2608 | 2599 |
2609 » default: | 2600 default: |
2610 » PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE); | 2601 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE); |
2611 » return SECFailure; | 2602 return SECFailure; |
2612 } | 2603 } |
2613 | 2604 |
2614 return SECSuccess; | 2605 return SECSuccess; |
2615 } | 2606 } |
2616 | 2607 |
2617 | |
2618 /* | 2608 /* |
2619 * FUNCTION: CERT_DecodeOCSPResponse | 2609 * FUNCTION: CERT_DecodeOCSPResponse |
2620 * Decode a DER encoded OCSP Response. | 2610 * Decode a DER encoded OCSP Response. |
2621 * INPUTS: | 2611 * INPUTS: |
2622 * SECItem *src | 2612 * SECItem *src |
2623 * Pointer to a SECItem holding DER encoded OCSP Response. | 2613 * Pointer to a SECItem holding DER encoded OCSP Response. |
2624 * RETURN: | 2614 * RETURN: |
2625 * Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response); | 2615 * Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response); |
2626 * the caller is responsible for destroying it. Or NULL if error (either | 2616 * the caller is responsible for destroying it. Or NULL if error (either |
2627 * response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE), | 2617 * response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE), |
2628 * it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE), | 2618 * it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE), |
2629 * or a low-level or internal error occurred). | 2619 * or a low-level or internal error occurred). |
2630 */ | 2620 */ |
2631 CERTOCSPResponse * | 2621 CERTOCSPResponse * |
2632 CERT_DecodeOCSPResponse(const SECItem *src) | 2622 CERT_DecodeOCSPResponse(const SECItem *src) |
2633 { | 2623 { |
2634 PLArenaPool *arena = NULL; | 2624 PLArenaPool *arena = NULL; |
2635 CERTOCSPResponse *response = NULL; | 2625 CERTOCSPResponse *response = NULL; |
2636 SECStatus rv = SECFailure; | 2626 SECStatus rv = SECFailure; |
2637 ocspResponseStatus sv; | 2627 ocspResponseStatus sv; |
2638 SECItem newSrc; | 2628 SECItem newSrc; |
2639 | 2629 |
2640 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 2630 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
2641 if (arena == NULL) { | 2631 if (arena == NULL) { |
2642 » goto loser; | 2632 goto loser; |
2643 } | 2633 } |
2644 response = (CERTOCSPResponse *) PORT_ArenaZAlloc(arena, | 2634 response = (CERTOCSPResponse *)PORT_ArenaZAlloc(arena, |
2645 » » » » » » sizeof(CERTOCSPResponse)); | 2635 sizeof(CERTOCSPResponse)); |
2646 if (response == NULL) { | 2636 if (response == NULL) { |
2647 » goto loser; | 2637 goto loser; |
2648 } | 2638 } |
2649 response->arena = arena; | 2639 response->arena = arena; |
2650 | 2640 |
2651 /* copy the DER into the arena, since Quick DER returns data that points | 2641 /* copy the DER into the arena, since Quick DER returns data that points |
2652 into the DER input, which may get freed by the caller */ | 2642 into the DER input, which may get freed by the caller */ |
2653 rv = SECITEM_CopyItem(arena, &newSrc, src); | 2643 rv = SECITEM_CopyItem(arena, &newSrc, src); |
2654 if ( rv != SECSuccess ) { | 2644 if (rv != SECSuccess) { |
2655 » goto loser; | 2645 goto loser; |
2656 } | 2646 } |
2657 | 2647 |
2658 rv = SEC_QuickDERDecodeItem(arena, response, ocsp_OCSPResponseTemplate, &new
Src); | 2648 rv = SEC_QuickDERDecodeItem(arena, response, ocsp_OCSPResponseTemplate, &new
Src); |
2659 if (rv != SECSuccess) { | 2649 if (rv != SECSuccess) { |
2660 » if (PORT_GetError() == SEC_ERROR_BAD_DER) | 2650 if (PORT_GetError() == SEC_ERROR_BAD_DER) |
2661 » PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); | 2651 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); |
2662 » goto loser; | 2652 goto loser; |
2663 } | 2653 } |
2664 | 2654 |
2665 sv = (ocspResponseStatus) DER_GetInteger(&response->responseStatus); | 2655 sv = (ocspResponseStatus)DER_GetInteger(&response->responseStatus); |
2666 response->statusValue = sv; | 2656 response->statusValue = sv; |
2667 if (sv != ocspResponse_successful) { | 2657 if (sv != ocspResponse_successful) { |
2668 » /* | 2658 /* |
2669 * If the response status is anything but successful, then we | 2659 * If the response status is anything but successful, then we |
2670 * are all done with decoding; the status is all there is. | 2660 * are all done with decoding; the status is all there is. |
2671 */ | 2661 */ |
2672 » return response; | 2662 return response; |
2673 } | 2663 } |
2674 | 2664 |
2675 /* | 2665 /* |
2676 * A successful response contains much more information, still encoded. | 2666 * A successful response contains much more information, still encoded. |
2677 * Now we need to decode that. | 2667 * Now we need to decode that. |
2678 */ | 2668 */ |
2679 rv = ocsp_DecodeResponseBytes(arena, response->responseBytes); | 2669 rv = ocsp_DecodeResponseBytes(arena, response->responseBytes); |
2680 if (rv != SECSuccess) { | 2670 if (rv != SECSuccess) { |
2681 » goto loser; | 2671 goto loser; |
2682 } | 2672 } |
2683 | 2673 |
2684 return response; | 2674 return response; |
2685 | 2675 |
2686 loser: | 2676 loser: |
2687 if (arena != NULL) { | 2677 if (arena != NULL) { |
2688 » PORT_FreeArena(arena, PR_FALSE); | 2678 PORT_FreeArena(arena, PR_FALSE); |
2689 } | 2679 } |
2690 return NULL; | 2680 return NULL; |
2691 } | 2681 } |
2692 | 2682 |
2693 /* | 2683 /* |
2694 * The way an OCSPResponse is defined, there are many levels to descend | 2684 * The way an OCSPResponse is defined, there are many levels to descend |
2695 * before getting to the actual response information. And along the way | 2685 * before getting to the actual response information. And along the way |
2696 * we need to check that the response *type* is recognizable, which for | 2686 * we need to check that the response *type* is recognizable, which for |
2697 * now means that it is a BasicOCSPResponse, because that is the only | 2687 * now means that it is a BasicOCSPResponse, because that is the only |
2698 * type currently defined. Rather than force all routines to perform | 2688 * type currently defined. Rather than force all routines to perform |
2699 * a bunch of sanity checking every time they want to work on a response, | 2689 * a bunch of sanity checking every time they want to work on a response, |
2700 * this function isolates that and gives back the interesting part. | 2690 * this function isolates that and gives back the interesting part. |
2701 * Note that no copying is done, this just returns a pointer into the | 2691 * Note that no copying is done, this just returns a pointer into the |
2702 * substructure of the response which is passed in. | 2692 * substructure of the response which is passed in. |
2703 * | 2693 * |
2704 * XXX This routine only works when a valid response structure is passed | 2694 * XXX This routine only works when a valid response structure is passed |
2705 * into it; this is checked with many assertions. Assuming the response | 2695 * into it; this is checked with many assertions. Assuming the response |
2706 * was creating by decoding, it wouldn't make it this far without being | 2696 * was creating by decoding, it wouldn't make it this far without being |
2707 * okay. That is a sufficient assumption since the entire OCSP interface | 2697 * okay. That is a sufficient assumption since the entire OCSP interface |
2708 * is only used internally. When this interface is officially exported, | 2698 * is only used internally. When this interface is officially exported, |
2709 * each assertion below will need to be followed-up with setting an error | 2699 * each assertion below will need to be followed-up with setting an error |
2710 * and returning (null). | 2700 * and returning (null). |
2711 * | 2701 * |
2712 * FUNCTION: ocsp_GetResponseData | 2702 * FUNCTION: ocsp_GetResponseData |
2713 * Returns ocspResponseData structure and a pointer to tbs response | 2703 * Returns ocspResponseData structure and a pointer to tbs response |
2714 * data DER from a valid ocsp response. | 2704 * data DER from a valid ocsp response. |
2715 * INPUTS: | 2705 * INPUTS: |
2716 * CERTOCSPResponse *response | 2706 * CERTOCSPResponse *response |
2717 * structure of a valid ocsp response | 2707 * structure of a valid ocsp response |
2718 * RETURN: | 2708 * RETURN: |
2719 * Returns a pointer to ocspResponseData structure: decoded OCSP response | 2709 * Returns a pointer to ocspResponseData structure: decoded OCSP response |
2720 * data, and a pointer(tbsResponseDataDER) to its undecoded data DER. | 2710 * data, and a pointer(tbsResponseDataDER) to its undecoded data DER. |
2721 */ | 2711 */ |
2722 ocspResponseData * | 2712 ocspResponseData * |
2723 ocsp_GetResponseData(CERTOCSPResponse *response, SECItem **tbsResponseDataDER) | 2713 ocsp_GetResponseData(CERTOCSPResponse *response, SECItem **tbsResponseDataDER) |
2724 { | 2714 { |
2725 ocspBasicOCSPResponse *basic; | 2715 ocspBasicOCSPResponse *basic; |
2726 ocspResponseData *responseData; | 2716 ocspResponseData *responseData; |
2727 | 2717 |
2728 PORT_Assert(response != NULL); | 2718 PORT_Assert(response != NULL); |
2729 | 2719 |
2730 PORT_Assert(response->responseBytes != NULL); | 2720 PORT_Assert(response->responseBytes != NULL); |
2731 | 2721 |
2732 PORT_Assert(response->responseBytes->responseTypeTag | 2722 PORT_Assert(response->responseBytes->responseTypeTag == |
2733 » » == SEC_OID_PKIX_OCSP_BASIC_RESPONSE); | 2723 SEC_OID_PKIX_OCSP_BASIC_RESPONSE); |
2734 | 2724 |
2735 basic = response->responseBytes->decodedResponse.basic; | 2725 basic = response->responseBytes->decodedResponse.basic; |
2736 PORT_Assert(basic != NULL); | 2726 PORT_Assert(basic != NULL); |
2737 | 2727 |
2738 responseData = basic->tbsResponseData; | 2728 responseData = basic->tbsResponseData; |
2739 PORT_Assert(responseData != NULL); | 2729 PORT_Assert(responseData != NULL); |
2740 | 2730 |
2741 if (tbsResponseDataDER) { | 2731 if (tbsResponseDataDER) { |
2742 *tbsResponseDataDER = &basic->tbsResponseDataDER; | 2732 *tbsResponseDataDER = &basic->tbsResponseDataDER; |
2743 | 2733 |
(...skipping 10 matching lines...) Expand all Loading... |
2754 */ | 2744 */ |
2755 ocspSignature * | 2745 ocspSignature * |
2756 ocsp_GetResponseSignature(CERTOCSPResponse *response) | 2746 ocsp_GetResponseSignature(CERTOCSPResponse *response) |
2757 { | 2747 { |
2758 ocspBasicOCSPResponse *basic; | 2748 ocspBasicOCSPResponse *basic; |
2759 | 2749 |
2760 PORT_Assert(response != NULL); | 2750 PORT_Assert(response != NULL); |
2761 if (NULL == response->responseBytes) { | 2751 if (NULL == response->responseBytes) { |
2762 return NULL; | 2752 return NULL; |
2763 } | 2753 } |
2764 if (response->responseBytes->responseTypeTag | 2754 if (response->responseBytes->responseTypeTag != |
2765 != SEC_OID_PKIX_OCSP_BASIC_RESPONSE) { | 2755 SEC_OID_PKIX_OCSP_BASIC_RESPONSE) { |
2766 return NULL; | 2756 return NULL; |
2767 } | 2757 } |
2768 basic = response->responseBytes->decodedResponse.basic; | 2758 basic = response->responseBytes->decodedResponse.basic; |
2769 PORT_Assert(basic != NULL); | 2759 PORT_Assert(basic != NULL); |
2770 | 2760 |
2771 return &(basic->responseSignature); | 2761 return &(basic->responseSignature); |
2772 } | 2762 } |
2773 | 2763 |
2774 | |
2775 /* | 2764 /* |
2776 * FUNCTION: CERT_DestroyOCSPResponse | 2765 * FUNCTION: CERT_DestroyOCSPResponse |
2777 * Frees an OCSP Response structure. | 2766 * Frees an OCSP Response structure. |
2778 * INPUTS: | 2767 * INPUTS: |
2779 * CERTOCSPResponse *request | 2768 * CERTOCSPResponse *request |
2780 * Pointer to CERTOCSPResponse to be freed. | 2769 * Pointer to CERTOCSPResponse to be freed. |
2781 * RETURN: | 2770 * RETURN: |
2782 * No return value; no errors. | 2771 * No return value; no errors. |
2783 */ | 2772 */ |
2784 void | 2773 void |
2785 CERT_DestroyOCSPResponse(CERTOCSPResponse *response) | 2774 CERT_DestroyOCSPResponse(CERTOCSPResponse *response) |
2786 { | 2775 { |
2787 if (response != NULL) { | 2776 if (response != NULL) { |
2788 » ocspSignature *signature = ocsp_GetResponseSignature(response); | 2777 ocspSignature *signature = ocsp_GetResponseSignature(response); |
2789 » if (signature && signature->cert != NULL) | 2778 if (signature && signature->cert != NULL) |
2790 » CERT_DestroyCertificate(signature->cert); | 2779 CERT_DestroyCertificate(signature->cert); |
2791 | 2780 |
2792 » /* | 2781 /* |
2793 * We should actually never have a response without an arena, | 2782 * We should actually never have a response without an arena, |
2794 * but check just in case. (If there isn't one, there is not | 2783 * but check just in case. (If there isn't one, there is not |
2795 * much we can do about it...) | 2784 * much we can do about it...) |
2796 */ | 2785 */ |
2797 » PORT_Assert(response->arena != NULL); | 2786 PORT_Assert(response->arena != NULL); |
2798 » if (response->arena != NULL) { | 2787 if (response->arena != NULL) { |
2799 » PORT_FreeArena(response->arena, PR_FALSE); | 2788 PORT_FreeArena(response->arena, PR_FALSE); |
2800 » } | 2789 } |
2801 } | 2790 } |
2802 } | 2791 } |
2803 | 2792 |
2804 | |
2805 /* | 2793 /* |
2806 * OVERALL OCSP CLIENT SUPPORT (make and send a request, verify a response): | 2794 * OVERALL OCSP CLIENT SUPPORT (make and send a request, verify a response): |
2807 */ | 2795 */ |
2808 | 2796 |
2809 | |
2810 /* | 2797 /* |
2811 * Pick apart a URL, saving the important things in the passed-in pointers. | 2798 * Pick apart a URL, saving the important things in the passed-in pointers. |
2812 * | 2799 * |
2813 * We expect to find "http://<hostname>[:<port>]/[path]", though we will | 2800 * We expect to find "http://<hostname>[:<port>]/[path]", though we will |
2814 * tolerate that final slash character missing, as well as beginning and | 2801 * tolerate that final slash character missing, as well as beginning and |
2815 * trailing whitespace, and any-case-characters for "http". All of that | 2802 * trailing whitespace, and any-case-characters for "http". All of that |
2816 * tolerance is what complicates this routine. What we want is just to | 2803 * tolerance is what complicates this routine. What we want is just to |
2817 * pick out the hostname, the port, and the path. | 2804 * pick out the hostname, the port, and the path. |
2818 * | 2805 * |
2819 * On a successful return, the caller will need to free the output pieces | 2806 * On a successful return, the caller will need to free the output pieces |
2820 * of hostname and path, which are copies of the values found in the url. | 2807 * of hostname and path, which are copies of the values found in the url. |
2821 */ | 2808 */ |
2822 static SECStatus | 2809 static SECStatus |
2823 ocsp_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath) | 2810 ocsp_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath) |
2824 { | 2811 { |
2825 unsigned short port = 80;» » /* default, in case not in url */ | 2812 unsigned short port = 80; /* default, in case not in url */ |
2826 char *hostname = NULL; | 2813 char *hostname = NULL; |
2827 char *path = NULL; | 2814 char *path = NULL; |
2828 const char *save; | 2815 const char *save; |
2829 char c; | 2816 char c; |
2830 int len; | 2817 int len; |
2831 | 2818 |
2832 if (url == NULL) | 2819 if (url == NULL) |
2833 » goto loser; | 2820 goto loser; |
2834 | 2821 |
2835 /* | 2822 /* |
2836 * Skip beginning whitespace. | 2823 * Skip beginning whitespace. |
2837 */ | 2824 */ |
2838 c = *url; | 2825 c = *url; |
2839 while ((c == ' ' || c == '\t') && c != '\0') { | 2826 while ((c == ' ' || c == '\t') && c != '\0') { |
2840 » url++; | 2827 url++; |
2841 » c = *url; | 2828 c = *url; |
2842 } | 2829 } |
2843 if (c == '\0') | 2830 if (c == '\0') |
2844 » goto loser; | 2831 goto loser; |
2845 | 2832 |
2846 /* | 2833 /* |
2847 * Confirm, then skip, protocol. (Since we only know how to do http, | 2834 * Confirm, then skip, protocol. (Since we only know how to do http, |
2848 * that is all we will accept). | 2835 * that is all we will accept). |
2849 */ | 2836 */ |
2850 if (PORT_Strncasecmp(url, "http://", 7) != 0) | 2837 if (PORT_Strncasecmp(url, "http://", 7) != 0) |
2851 » goto loser; | 2838 goto loser; |
2852 url += 7; | 2839 url += 7; |
2853 | 2840 |
2854 /* | 2841 /* |
2855 * Whatever comes next is the hostname (or host IP address). We just | 2842 * Whatever comes next is the hostname (or host IP address). We just |
2856 * save it aside and then search for its end so we can determine its | 2843 * save it aside and then search for its end so we can determine its |
2857 * length and copy it. | 2844 * length and copy it. |
2858 * | 2845 * |
2859 * XXX Note that because we treat a ':' as a terminator character | 2846 * XXX Note that because we treat a ':' as a terminator character |
2860 * (and below, we expect that to mean there is a port specification | 2847 * (and below, we expect that to mean there is a port specification |
2861 * immediately following), we will not handle IPv6 addresses. That is | 2848 * immediately following), we will not handle IPv6 addresses. That is |
2862 * apparently an acceptable limitation, for the time being. Some day, | 2849 * apparently an acceptable limitation, for the time being. Some day, |
2863 * when there is a clear way to specify a URL with an IPv6 address that | 2850 * when there is a clear way to specify a URL with an IPv6 address that |
2864 * can be parsed unambiguously, this code should be made to do that. | 2851 * can be parsed unambiguously, this code should be made to do that. |
2865 */ | 2852 */ |
2866 save = url; | 2853 save = url; |
2867 c = *url; | 2854 c = *url; |
2868 while (c != '/' && c != ':' && c != '\0' && c != ' ' && c != '\t') { | 2855 while (c != '/' && c != ':' && c != '\0' && c != ' ' && c != '\t') { |
2869 » url++; | 2856 url++; |
2870 » c = *url; | 2857 c = *url; |
2871 } | 2858 } |
2872 len = url - save; | 2859 len = url - save; |
2873 hostname = PORT_Alloc(len + 1); | 2860 hostname = PORT_Alloc(len + 1); |
2874 if (hostname == NULL) | 2861 if (hostname == NULL) |
2875 » goto loser; | 2862 goto loser; |
2876 PORT_Memcpy(hostname, save, len); | 2863 PORT_Memcpy(hostname, save, len); |
2877 hostname[len] = '\0'; | 2864 hostname[len] = '\0'; |
2878 | 2865 |
2879 /* | 2866 /* |
2880 * Now we figure out if there was a port specified or not. | 2867 * Now we figure out if there was a port specified or not. |
2881 * If so, we need to parse it (as a number) and skip it. | 2868 * If so, we need to parse it (as a number) and skip it. |
2882 */ | 2869 */ |
2883 if (c == ':') { | 2870 if (c == ':') { |
2884 » url++; | 2871 url++; |
2885 » port = (unsigned short) PORT_Atoi(url); | 2872 port = (unsigned short)PORT_Atoi(url); |
2886 » c = *url; | 2873 c = *url; |
2887 » while (c != '/' && c != '\0' && c != ' ' && c != '\t') { | 2874 while (c != '/' && c != '\0' && c != ' ' && c != '\t') { |
2888 » if (c < '0' || c > '9') | 2875 if (c < '0' || c > '9') |
2889 » » goto loser; | 2876 goto loser; |
2890 » url++; | 2877 url++; |
2891 » c = *url; | 2878 c = *url; |
2892 » } | 2879 } |
2893 } | 2880 } |
2894 | 2881 |
2895 /* | 2882 /* |
2896 * Last thing to find is a path. There *should* be a slash, | 2883 * Last thing to find is a path. There *should* be a slash, |
2897 * if nothing else -- but if there is not we provide one. | 2884 * if nothing else -- but if there is not we provide one. |
2898 */ | 2885 */ |
2899 if (c == '/') { | 2886 if (c == '/') { |
2900 » save = url; | 2887 save = url; |
2901 » while (c != '\0' && c != ' ' && c != '\t') { | 2888 while (c != '\0' && c != ' ' && c != '\t') { |
2902 » url++; | 2889 url++; |
2903 » c = *url; | 2890 c = *url; |
2904 » } | 2891 } |
2905 » len = url - save; | 2892 len = url - save; |
2906 » path = PORT_Alloc(len + 1); | 2893 path = PORT_Alloc(len + 1); |
2907 » if (path == NULL) | 2894 if (path == NULL) |
2908 » goto loser; | 2895 goto loser; |
2909 » PORT_Memcpy(path, save, len); | 2896 PORT_Memcpy(path, save, len); |
2910 » path[len] = '\0'; | 2897 path[len] = '\0'; |
2911 } else { | 2898 } else { |
2912 » path = PORT_Strdup("/"); | 2899 path = PORT_Strdup("/"); |
2913 » if (path == NULL) | 2900 if (path == NULL) |
2914 » goto loser; | 2901 goto loser; |
2915 } | 2902 } |
2916 | 2903 |
2917 *pHostname = hostname; | 2904 *pHostname = hostname; |
2918 *pPort = port; | 2905 *pPort = port; |
2919 *pPath = path; | 2906 *pPath = path; |
2920 return SECSuccess; | 2907 return SECSuccess; |
2921 | 2908 |
2922 loser: | 2909 loser: |
2923 if (hostname != NULL) | 2910 if (hostname != NULL) |
2924 » PORT_Free(hostname); | 2911 PORT_Free(hostname); |
2925 PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); | 2912 PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); |
2926 return SECFailure; | 2913 return SECFailure; |
2927 } | 2914 } |
2928 | 2915 |
2929 /* | 2916 /* |
2930 * Open a socket to the specified host on the specified port, and return it. | 2917 * Open a socket to the specified host on the specified port, and return it. |
2931 * The host is either a hostname or an IP address. | 2918 * The host is either a hostname or an IP address. |
2932 */ | 2919 */ |
2933 static PRFileDesc * | 2920 static PRFileDesc * |
2934 ocsp_ConnectToHost(const char *host, PRUint16 port) | 2921 ocsp_ConnectToHost(const char *host, PRUint16 port) |
2935 { | 2922 { |
2936 PRFileDesc *sock = NULL; | 2923 PRFileDesc *sock = NULL; |
2937 PRIntervalTime timeout; | 2924 PRIntervalTime timeout; |
2938 PRNetAddr addr; | 2925 PRNetAddr addr; |
2939 char *netdbbuf = NULL; | 2926 char *netdbbuf = NULL; |
2940 | 2927 |
2941 sock = PR_NewTCPSocket(); | 2928 sock = PR_NewTCPSocket(); |
2942 if (sock == NULL) | 2929 if (sock == NULL) |
2943 » goto loser; | 2930 goto loser; |
2944 | 2931 |
2945 /* XXX Some day need a way to set (and get?) the following value */ | 2932 /* XXX Some day need a way to set (and get?) the following value */ |
2946 timeout = PR_SecondsToInterval(30); | 2933 timeout = PR_SecondsToInterval(30); |
2947 | 2934 |
2948 /* | 2935 /* |
2949 * If the following converts an IP address string in "dot notation" | 2936 * If the following converts an IP address string in "dot notation" |
2950 * into a PRNetAddr. If it fails, we assume that is because we do not | 2937 * into a PRNetAddr. If it fails, we assume that is because we do not |
2951 * have such an address, but instead a host *name*. In that case we | 2938 * have such an address, but instead a host *name*. In that case we |
2952 * then lookup the host by name. Using the NSPR function this way | 2939 * then lookup the host by name. Using the NSPR function this way |
2953 * means we do not have to have our own logic for distinguishing a | 2940 * means we do not have to have our own logic for distinguishing a |
2954 * valid numerical IP address from a hostname. | 2941 * valid numerical IP address from a hostname. |
2955 */ | 2942 */ |
2956 if (PR_StringToNetAddr(host, &addr) != PR_SUCCESS) { | 2943 if (PR_StringToNetAddr(host, &addr) != PR_SUCCESS) { |
2957 » PRIntn hostIndex; | 2944 PRIntn hostIndex; |
2958 » PRHostEnt hostEntry; | 2945 PRHostEnt hostEntry; |
2959 | 2946 |
2960 » netdbbuf = PORT_Alloc(PR_NETDB_BUF_SIZE); | 2947 netdbbuf = PORT_Alloc(PR_NETDB_BUF_SIZE); |
2961 » if (netdbbuf == NULL) | 2948 if (netdbbuf == NULL) |
2962 » goto loser; | 2949 goto loser; |
2963 | 2950 |
2964 » if (PR_GetHostByName(host, netdbbuf, PR_NETDB_BUF_SIZE, | 2951 if (PR_GetHostByName(host, netdbbuf, PR_NETDB_BUF_SIZE, |
2965 » » » &hostEntry) != PR_SUCCESS) | 2952 &hostEntry) != PR_SUCCESS) |
2966 » goto loser; | 2953 goto loser; |
2967 | 2954 |
2968 » hostIndex = 0; | 2955 hostIndex = 0; |
2969 » do { | 2956 do { |
2970 » hostIndex = PR_EnumerateHostEnt(hostIndex, &hostEntry, port, &addr); | 2957 hostIndex = PR_EnumerateHostEnt(hostIndex, &hostEntry, port, &addr); |
2971 » if (hostIndex <= 0) | 2958 if (hostIndex <= 0) |
2972 » » goto loser; | 2959 goto loser; |
2973 » } while (PR_Connect(sock, &addr, timeout) != PR_SUCCESS); | 2960 } while (PR_Connect(sock, &addr, timeout) != PR_SUCCESS); |
2974 | 2961 |
2975 » PORT_Free(netdbbuf); | 2962 PORT_Free(netdbbuf); |
2976 } else { | 2963 } else { |
2977 » /* | 2964 /* |
2978 * First put the port into the address, then connect. | 2965 * First put the port into the address, then connect. |
2979 */ | 2966 */ |
2980 » if (PR_InitializeNetAddr(PR_IpAddrNull, port, &addr) != PR_SUCCESS) | 2967 if (PR_InitializeNetAddr(PR_IpAddrNull, port, &addr) != PR_SUCCESS) |
2981 » goto loser; | 2968 goto loser; |
2982 » if (PR_Connect(sock, &addr, timeout) != PR_SUCCESS) | 2969 if (PR_Connect(sock, &addr, timeout) != PR_SUCCESS) |
2983 » goto loser; | 2970 goto loser; |
2984 } | 2971 } |
2985 | 2972 |
2986 return sock; | 2973 return sock; |
2987 | 2974 |
2988 loser: | 2975 loser: |
2989 if (sock != NULL) | 2976 if (sock != NULL) |
2990 » PR_Close(sock); | 2977 PR_Close(sock); |
2991 if (netdbbuf != NULL) | 2978 if (netdbbuf != NULL) |
2992 » PORT_Free(netdbbuf); | 2979 PORT_Free(netdbbuf); |
2993 return NULL; | 2980 return NULL; |
2994 } | 2981 } |
2995 | 2982 |
2996 /* | 2983 /* |
2997 * Sends an encoded OCSP request to the server identified by "location", | 2984 * Sends an encoded OCSP request to the server identified by "location", |
2998 * and returns the socket on which it was sent (so can listen for the reply). | 2985 * and returns the socket on which it was sent (so can listen for the reply). |
2999 * "location" is expected to be a valid URL -- an error parsing it produces | 2986 * "location" is expected to be a valid URL -- an error parsing it produces |
3000 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION. Other errors are likely problems | 2987 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION. Other errors are likely problems |
3001 * connecting to it, or writing to it, or allocating memory, and the low-level | 2988 * connecting to it, or writing to it, or allocating memory, and the low-level |
3002 * errors appropriate to the problem will be set. | 2989 * errors appropriate to the problem will be set. |
(...skipping 14 matching lines...) Expand all Loading... |
3017 PRFileDesc *sock = NULL; | 3004 PRFileDesc *sock = NULL; |
3018 PRFileDesc *returnSock = NULL; | 3005 PRFileDesc *returnSock = NULL; |
3019 char *header = NULL; | 3006 char *header = NULL; |
3020 char portstr[16]; | 3007 char portstr[16]; |
3021 | 3008 |
3022 /* | 3009 /* |
3023 * Take apart the location, getting the hostname, port, and path. | 3010 * Take apart the location, getting the hostname, port, and path. |
3024 */ | 3011 */ |
3025 rv = ocsp_ParseURL(location, &hostname, &port, &path); | 3012 rv = ocsp_ParseURL(location, &hostname, &port, &path); |
3026 if (rv != SECSuccess) | 3013 if (rv != SECSuccess) |
3027 » goto loser; | 3014 goto loser; |
3028 | 3015 |
3029 PORT_Assert(hostname != NULL); | 3016 PORT_Assert(hostname != NULL); |
3030 PORT_Assert(path != NULL); | 3017 PORT_Assert(path != NULL); |
3031 | 3018 |
3032 sock = ocsp_ConnectToHost(hostname, port); | 3019 sock = ocsp_ConnectToHost(hostname, port); |
3033 if (sock == NULL) | 3020 if (sock == NULL) |
3034 » goto loser; | 3021 goto loser; |
3035 | 3022 |
3036 portstr[0] = '\0'; | 3023 portstr[0] = '\0'; |
3037 if (port != 80) { | 3024 if (port != 80) { |
3038 PR_snprintf(portstr, sizeof(portstr), ":%d", port); | 3025 PR_snprintf(portstr, sizeof(portstr), ":%d", port); |
3039 } | 3026 } |
3040 | 3027 |
3041 if (!encodedRequest) { | 3028 if (!encodedRequest) { |
3042 header = PR_smprintf("GET %s HTTP/1.0\r\n" | 3029 header = PR_smprintf("GET %s HTTP/1.0\r\n" |
3043 "Host: %s%s\r\n\r\n", | 3030 "Host: %s%s\r\n\r\n", |
3044 path, hostname, portstr); | 3031 path, hostname, portstr); |
3045 if (header == NULL) | 3032 if (header == NULL) |
3046 goto loser; | 3033 goto loser; |
3047 | 3034 |
3048 /* | 3035 /* |
3049 * The NSPR documentation promises that if it can, it will write the full | 3036 * The NSPR documentation promises that if it can, it will write the ful
l |
3050 * amount; this will not return a partial value expecting us to loop. | 3037 * amount; this will not return a partial value expecting us to loop. |
3051 */ | 3038 */ |
3052 if (PR_Write(sock, header, (PRInt32) PORT_Strlen(header)) < 0) | 3039 if (PR_Write(sock, header, (PRInt32)PORT_Strlen(header)) < 0) |
3053 goto loser; | 3040 goto loser; |
3054 } | 3041 } else { |
3055 else { | 3042 header = PR_smprintf("POST %s HTTP/1.0\r\n" |
3056 header = PR_smprintf("POST %s HTTP/1.0\r\n" | 3043 "Host: %s%s\r\n" |
3057 "Host: %s%s\r\n" | 3044 "Content-Type: application/ocsp-request\r\n" |
3058 "Content-Type: application/ocsp-request\r\n" | 3045 "Content-Length: %u\r\n\r\n", |
3059 "Content-Length: %u\r\n\r\n", | 3046 path, hostname, portstr, encodedRequest->len); |
3060 path, hostname, portstr, encodedRequest->len); | 3047 if (header == NULL) |
3061 if (header == NULL) | 3048 goto loser; |
3062 goto loser; | |
3063 | 3049 |
3064 /* | 3050 /* |
3065 * The NSPR documentation promises that if it can, it will write the full | 3051 * The NSPR documentation promises that if it can, it will write the ful
l |
3066 * amount; this will not return a partial value expecting us to loop. | 3052 * amount; this will not return a partial value expecting us to loop. |
3067 */ | 3053 */ |
3068 if (PR_Write(sock, header, (PRInt32) PORT_Strlen(header)) < 0) | 3054 if (PR_Write(sock, header, (PRInt32)PORT_Strlen(header)) < 0) |
3069 goto loser; | 3055 goto loser; |
3070 | 3056 |
3071 if (PR_Write(sock, encodedRequest->data, | 3057 if (PR_Write(sock, encodedRequest->data, |
3072 (PRInt32) encodedRequest->len) < 0) | 3058 (PRInt32)encodedRequest->len) < 0) |
3073 goto loser; | 3059 goto loser; |
3074 } | 3060 } |
3075 | 3061 |
3076 returnSock = sock; | 3062 returnSock = sock; |
3077 sock = NULL; | 3063 sock = NULL; |
3078 | 3064 |
3079 loser: | 3065 loser: |
3080 if (header != NULL) | 3066 if (header != NULL) |
3081 » PORT_Free(header); | 3067 PORT_Free(header); |
3082 if (sock != NULL) | 3068 if (sock != NULL) |
3083 » PR_Close(sock); | 3069 PR_Close(sock); |
3084 if (path != NULL) | 3070 if (path != NULL) |
3085 » PORT_Free(path); | 3071 PORT_Free(path); |
3086 if (hostname != NULL) | 3072 if (hostname != NULL) |
3087 » PORT_Free(hostname); | 3073 PORT_Free(hostname); |
3088 | 3074 |
3089 return returnSock; | 3075 return returnSock; |
3090 } | 3076 } |
3091 | 3077 |
3092 /* | 3078 /* |
3093 * Read from "fd" into "buf" -- expect/attempt to read a given number of bytes | 3079 * Read from "fd" into "buf" -- expect/attempt to read a given number of bytes |
3094 * Obviously, stop if hit end-of-stream. Timeout is passed in. | 3080 * Obviously, stop if hit end-of-stream. Timeout is passed in. |
3095 */ | 3081 */ |
3096 | 3082 |
3097 static int | 3083 static int |
3098 ocsp_read(PRFileDesc *fd, char *buf, int toread, PRIntervalTime timeout) | 3084 ocsp_read(PRFileDesc *fd, char *buf, int toread, PRIntervalTime timeout) |
3099 { | 3085 { |
3100 int total = 0; | 3086 int total = 0; |
3101 | 3087 |
3102 while (total < toread) | 3088 while (total < toread) { |
3103 { | |
3104 PRInt32 got; | 3089 PRInt32 got; |
3105 | 3090 |
3106 got = PR_Recv(fd, buf + total, (PRInt32) (toread - total), 0, timeout); | 3091 got = PR_Recv(fd, buf + total, (PRInt32)(toread - total), 0, timeout); |
3107 if (got < 0) | 3092 if (got < 0) { |
3108 { | 3093 if (0 == total) { |
3109 if (0 == total) | |
3110 { | |
3111 total = -1; /* report the error if we didn't read anything yet *
/ | 3094 total = -1; /* report the error if we didn't read anything yet *
/ |
3112 } | 3095 } |
3113 break; | 3096 break; |
3114 } | 3097 } else if (got == 0) { /* EOS */ |
3115 else | |
3116 if (got == 0) | |
3117 {» » » /* EOS */ | |
3118 break; | 3098 break; |
3119 } | 3099 } |
3120 | 3100 |
3121 total += got; | 3101 total += got; |
3122 } | 3102 } |
3123 | 3103 |
3124 return total; | 3104 return total; |
3125 } | 3105 } |
3126 | 3106 |
3127 #define OCSP_BUFSIZE 1024 | 3107 #define OCSP_BUFSIZE 1024 |
3128 | 3108 |
3129 #define AbortHttpDecode(error) \ | 3109 #define AbortHttpDecode(error) \ |
3130 { \ | 3110 { \ |
3131 if (inBuffer) \ | 3111 if (inBuffer) \ |
3132 PORT_Free(inBuffer); \ | 3112 PORT_Free(inBuffer); \ |
3133 PORT_SetError(error); \ | 3113 PORT_SetError(error); \ |
3134 return NULL; \ | 3114 return NULL; \ |
3135 } | 3115 } |
3136 | |
3137 | 3116 |
3138 /* | 3117 /* |
3139 * Reads on the given socket and returns an encoded response when received. | 3118 * Reads on the given socket and returns an encoded response when received. |
3140 * Properly formatted HTTP/1.0 response headers are expected to be read | 3119 * Properly formatted HTTP/1.0 response headers are expected to be read |
3141 * from the socket, preceding a binary-encoded OCSP response. Problems | 3120 * from the socket, preceding a binary-encoded OCSP response. Problems |
3142 * with parsing cause the error SEC_ERROR_OCSP_BAD_HTTP_RESPONSE to be | 3121 * with parsing cause the error SEC_ERROR_OCSP_BAD_HTTP_RESPONSE to be |
3143 * set; any other problems are likely low-level i/o or memory allocation | 3122 * set; any other problems are likely low-level i/o or memory allocation |
3144 * errors. | 3123 * errors. |
3145 */ | 3124 */ |
3146 static SECItem * | 3125 static SECItem * |
3147 ocsp_GetEncodedResponse(PLArenaPool *arena, PRFileDesc *sock) | 3126 ocsp_GetEncodedResponse(PLArenaPool *arena, PRFileDesc *sock) |
3148 { | 3127 { |
3149 /* first read HTTP status line and headers */ | 3128 /* first read HTTP status line and headers */ |
3150 | 3129 |
3151 char* inBuffer = NULL; | 3130 char *inBuffer = NULL; |
3152 PRInt32 offset = 0; | 3131 PRInt32 offset = 0; |
3153 PRInt32 inBufsize = 0; | 3132 PRInt32 inBufsize = 0; |
3154 const PRInt32 bufSizeIncrement = OCSP_BUFSIZE; /* 1 KB at a time */ | 3133 const PRInt32 bufSizeIncrement = OCSP_BUFSIZE; /* 1 KB at a time */ |
3155 const PRInt32 maxBufSize = 8 * bufSizeIncrement ; /* 8 KB max */ | 3134 const PRInt32 maxBufSize = 8 * bufSizeIncrement; /* 8 KB max */ |
3156 const char* CRLF = "\r\n"; | 3135 const char *CRLF = "\r\n"; |
3157 const PRInt32 CRLFlen = strlen(CRLF); | 3136 const PRInt32 CRLFlen = strlen(CRLF); |
3158 const char* headerEndMark = "\r\n\r\n"; | 3137 const char *headerEndMark = "\r\n\r\n"; |
3159 const PRInt32 markLen = strlen(headerEndMark); | 3138 const PRInt32 markLen = strlen(headerEndMark); |
3160 const PRIntervalTime ocsptimeout = | 3139 const PRIntervalTime ocsptimeout = |
3161 PR_SecondsToInterval(30); /* hardcoded to 30s for now */ | 3140 PR_SecondsToInterval(30); /* hardcoded to 30s for now */ |
3162 char* headerEnd = NULL; | 3141 char *headerEnd = NULL; |
3163 PRBool EOS = PR_FALSE; | 3142 PRBool EOS = PR_FALSE; |
3164 const char* httpprotocol = "HTTP/"; | 3143 const char *httpprotocol = "HTTP/"; |
3165 const PRInt32 httplen = strlen(httpprotocol); | 3144 const PRInt32 httplen = strlen(httpprotocol); |
3166 const char* httpcode = NULL; | 3145 const char *httpcode = NULL; |
3167 const char* contenttype = NULL; | 3146 const char *contenttype = NULL; |
3168 PRInt32 contentlength = 0; | 3147 PRInt32 contentlength = 0; |
3169 PRInt32 bytesRead = 0; | 3148 PRInt32 bytesRead = 0; |
3170 char* statusLineEnd = NULL; | 3149 char *statusLineEnd = NULL; |
3171 char* space = NULL; | 3150 char *space = NULL; |
3172 char* nextHeader = NULL; | 3151 char *nextHeader = NULL; |
3173 SECItem* result = NULL; | 3152 SECItem *result = NULL; |
3174 | 3153 |
3175 /* read up to at least the end of the HTTP headers */ | 3154 /* read up to at least the end of the HTTP headers */ |
3176 do | 3155 do { |
3177 { | |
3178 inBufsize += bufSizeIncrement; | 3156 inBufsize += bufSizeIncrement; |
3179 inBuffer = PORT_Realloc(inBuffer, inBufsize+1); | 3157 inBuffer = PORT_Realloc(inBuffer, inBufsize + 1); |
3180 if (NULL == inBuffer) | 3158 if (NULL == inBuffer) { |
3181 { | |
3182 AbortHttpDecode(SEC_ERROR_NO_MEMORY); | 3159 AbortHttpDecode(SEC_ERROR_NO_MEMORY); |
3183 } | 3160 } |
3184 bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement, | 3161 bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement, |
3185 ocsptimeout); | 3162 ocsptimeout); |
3186 if (bytesRead > 0) | 3163 if (bytesRead > 0) { |
3187 { | 3164 PRInt32 searchOffset = (offset - markLen) > 0 ? offset - markLen : 0
; |
3188 PRInt32 searchOffset = (offset - markLen) >0 ? offset-markLen : 0; | |
3189 offset += bytesRead; | 3165 offset += bytesRead; |
3190 *(inBuffer + offset) = '\0'; /* NULL termination */ | 3166 *(inBuffer + offset) = '\0'; /* NULL termination */ |
3191 headerEnd = strstr((const char*)inBuffer + searchOffset, headerEndMa
rk); | 3167 headerEnd = strstr((const char *)inBuffer + searchOffset, headerEndM
ark); |
3192 if (bytesRead < bufSizeIncrement) | 3168 if (bytesRead < bufSizeIncrement) { |
3193 { | |
3194 /* we read less data than requested, therefore we are at | 3169 /* we read less data than requested, therefore we are at |
3195 EOS or there was a read error */ | 3170 EOS or there was a read error */ |
3196 EOS = PR_TRUE; | 3171 EOS = PR_TRUE; |
3197 } | 3172 } |
3198 } | 3173 } else { |
3199 else | |
3200 { | |
3201 /* recv error or EOS */ | 3174 /* recv error or EOS */ |
3202 EOS = PR_TRUE; | 3175 EOS = PR_TRUE; |
3203 } | 3176 } |
3204 } while ( (!headerEnd) && (PR_FALSE == EOS) && | 3177 } while ((!headerEnd) && (PR_FALSE == EOS) && |
3205 (inBufsize < maxBufSize) ); | 3178 (inBufsize < maxBufSize)); |
3206 | 3179 |
3207 if (!headerEnd) | 3180 if (!headerEnd) { |
3208 { | |
3209 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3181 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3210 } | 3182 } |
3211 | 3183 |
3212 /* parse the HTTP status line */ | 3184 /* parse the HTTP status line */ |
3213 statusLineEnd = strstr((const char*)inBuffer, CRLF); | 3185 statusLineEnd = strstr((const char *)inBuffer, CRLF); |
3214 if (!statusLineEnd) | 3186 if (!statusLineEnd) { |
3215 { | |
3216 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3187 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3217 } | 3188 } |
3218 *statusLineEnd = '\0'; | 3189 *statusLineEnd = '\0'; |
3219 | 3190 |
3220 /* check for HTTP/ response */ | 3191 /* check for HTTP/ response */ |
3221 space = strchr((const char*)inBuffer, ' '); | 3192 space = strchr((const char *)inBuffer, ' '); |
3222 if (!space || PORT_Strncasecmp((const char*)inBuffer, httpprotocol, httplen)
!= 0 ) | 3193 if (!space || PORT_Strncasecmp((const char *)inBuffer, httpprotocol, httplen
) != 0) { |
3223 { | |
3224 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3194 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3225 } | 3195 } |
3226 | 3196 |
3227 /* check the HTTP status code of 200 */ | 3197 /* check the HTTP status code of 200 */ |
3228 httpcode = space +1; | 3198 httpcode = space + 1; |
3229 space = strchr(httpcode, ' '); | 3199 space = strchr(httpcode, ' '); |
3230 if (!space) | 3200 if (!space) { |
3231 { | |
3232 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3201 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3233 } | 3202 } |
3234 *space = 0; | 3203 *space = 0; |
3235 if (0 != strcmp(httpcode, "200")) | 3204 if (0 != strcmp(httpcode, "200")) { |
3236 { | |
3237 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3205 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3238 } | 3206 } |
3239 | 3207 |
3240 /* parse the HTTP headers in the buffer . We only care about | 3208 /* parse the HTTP headers in the buffer . We only care about |
3241 content-type and content-length | 3209 content-type and content-length |
3242 */ | 3210 */ |
3243 | 3211 |
3244 nextHeader = statusLineEnd + CRLFlen; | 3212 nextHeader = statusLineEnd + CRLFlen; |
3245 *headerEnd = '\0'; /* terminate */ | 3213 *headerEnd = '\0'; /* terminate */ |
3246 do | 3214 do { |
3247 { | 3215 char *thisHeaderEnd = NULL; |
3248 char* thisHeaderEnd = NULL; | 3216 char *value = NULL; |
3249 char* value = NULL; | 3217 char *colon = strchr(nextHeader, ':'); |
3250 char* colon = strchr(nextHeader, ':'); | 3218 |
3251 | 3219 if (!colon) { |
3252 if (!colon) | |
3253 { | |
3254 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3220 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3255 } | 3221 } |
3256 | 3222 |
3257 *colon = '\0'; | 3223 *colon = '\0'; |
3258 value = colon + 1; | 3224 value = colon + 1; |
3259 | 3225 |
3260 /* jpierre - note : the following code will only handle the basic form | 3226 /* jpierre - note : the following code will only handle the basic form |
3261 of HTTP/1.0 response headers, of the form "name: value" . Headers | 3227 of HTTP/1.0 response headers, of the form "name: value" . Headers |
3262 split among multiple lines are not supported. This is not common | 3228 split among multiple lines are not supported. This is not common |
3263 and should not be an issue, but it could become one in the | 3229 and should not be an issue, but it could become one in the |
3264 future */ | 3230 future */ |
3265 | 3231 |
3266 if (*value != ' ') | 3232 if (*value != ' ') { |
3267 { | |
3268 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3233 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3269 } | 3234 } |
3270 | 3235 |
3271 value++; | 3236 value++; |
3272 thisHeaderEnd = strstr(value, CRLF); | 3237 thisHeaderEnd = strstr(value, CRLF); |
3273 if (thisHeaderEnd ) | 3238 if (thisHeaderEnd) { |
3274 { | 3239 *thisHeaderEnd = '\0'; |
3275 *thisHeaderEnd = '\0'; | |
3276 } | 3240 } |
3277 | 3241 |
3278 if (0 == PORT_Strcasecmp(nextHeader, "content-type")) | 3242 if (0 == PORT_Strcasecmp(nextHeader, "content-type")) { |
3279 { | |
3280 contenttype = value; | 3243 contenttype = value; |
3281 } | 3244 } else if (0 == PORT_Strcasecmp(nextHeader, "content-length")) { |
3282 else | |
3283 if (0 == PORT_Strcasecmp(nextHeader, "content-length")) | |
3284 { | |
3285 contentlength = atoi(value); | 3245 contentlength = atoi(value); |
3286 } | 3246 } |
3287 | 3247 |
3288 if (thisHeaderEnd ) | 3248 if (thisHeaderEnd) { |
3289 { | |
3290 nextHeader = thisHeaderEnd + CRLFlen; | 3249 nextHeader = thisHeaderEnd + CRLFlen; |
3291 } | 3250 } else { |
3292 else | |
3293 { | |
3294 nextHeader = NULL; | 3251 nextHeader = NULL; |
3295 } | 3252 } |
3296 | 3253 |
3297 } while (nextHeader && (nextHeader < (headerEnd + CRLFlen) ) ); | 3254 } while (nextHeader && (nextHeader < (headerEnd + CRLFlen))); |
3298 | 3255 |
3299 /* check content-type */ | 3256 /* check content-type */ |
3300 if (!contenttype || | 3257 if (!contenttype || |
3301 (0 != PORT_Strcasecmp(contenttype, "application/ocsp-response")) ) | 3258 (0 != PORT_Strcasecmp(contenttype, "application/ocsp-response"))) { |
3302 { | |
3303 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3259 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3304 } | 3260 } |
3305 | 3261 |
3306 /* read the body of the OCSP response */ | 3262 /* read the body of the OCSP response */ |
3307 offset = offset - (PRInt32) (headerEnd - (const char*)inBuffer) - markLen; | 3263 offset = offset - (PRInt32)(headerEnd - (const char *)inBuffer) - markLen; |
3308 if (offset) | 3264 if (offset) { |
3309 { | |
3310 /* move all data to the beginning of the buffer */ | 3265 /* move all data to the beginning of the buffer */ |
3311 PORT_Memmove(inBuffer, headerEnd + markLen, offset); | 3266 PORT_Memmove(inBuffer, headerEnd + markLen, offset); |
3312 } | 3267 } |
3313 | 3268 |
3314 /* resize buffer to only what's needed to hold the current response */ | 3269 /* resize buffer to only what's needed to hold the current response */ |
3315 inBufsize = (1 + (offset-1) / bufSizeIncrement ) * bufSizeIncrement ; | 3270 inBufsize = (1 + (offset - 1) / bufSizeIncrement) * bufSizeIncrement; |
3316 | 3271 |
3317 while ( (PR_FALSE == EOS) && | 3272 while ((PR_FALSE == EOS) && |
3318 ( (contentlength == 0) || (offset < contentlength) ) && | 3273 ((contentlength == 0) || (offset < contentlength)) && |
3319 (inBufsize < maxBufSize) | 3274 (inBufsize < maxBufSize)) { |
3320 ) | |
3321 { | |
3322 /* we still need to receive more body data */ | 3275 /* we still need to receive more body data */ |
3323 inBufsize += bufSizeIncrement; | 3276 inBufsize += bufSizeIncrement; |
3324 inBuffer = PORT_Realloc(inBuffer, inBufsize+1); | 3277 inBuffer = PORT_Realloc(inBuffer, inBufsize + 1); |
3325 if (NULL == inBuffer) | 3278 if (NULL == inBuffer) { |
3326 { | |
3327 AbortHttpDecode(SEC_ERROR_NO_MEMORY); | 3279 AbortHttpDecode(SEC_ERROR_NO_MEMORY); |
3328 } | 3280 } |
3329 bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement, | 3281 bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement, |
3330 ocsptimeout); | 3282 ocsptimeout); |
3331 if (bytesRead > 0) | 3283 if (bytesRead > 0) { |
3332 { | |
3333 offset += bytesRead; | 3284 offset += bytesRead; |
3334 if (bytesRead < bufSizeIncrement) | 3285 if (bytesRead < bufSizeIncrement) { |
3335 { | |
3336 /* we read less data than requested, therefore we are at | 3286 /* we read less data than requested, therefore we are at |
3337 EOS or there was a read error */ | 3287 EOS or there was a read error */ |
3338 EOS = PR_TRUE; | 3288 EOS = PR_TRUE; |
3339 } | 3289 } |
3340 } | 3290 } else { |
3341 else | |
3342 { | |
3343 /* recv error or EOS */ | 3291 /* recv error or EOS */ |
3344 EOS = PR_TRUE; | 3292 EOS = PR_TRUE; |
3345 } | 3293 } |
3346 } | 3294 } |
3347 | 3295 |
3348 if (0 == offset) | 3296 if (0 == offset) { |
3349 { | |
3350 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3297 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3351 } | 3298 } |
3352 | 3299 |
3353 /* | 3300 /* |
3354 * Now allocate the item to hold the data. | 3301 * Now allocate the item to hold the data. |
3355 */ | 3302 */ |
3356 result = SECITEM_AllocItem(arena, NULL, offset); | 3303 result = SECITEM_AllocItem(arena, NULL, offset); |
3357 if (NULL == result) | 3304 if (NULL == result) { |
3358 { | |
3359 AbortHttpDecode(SEC_ERROR_NO_MEMORY); | 3305 AbortHttpDecode(SEC_ERROR_NO_MEMORY); |
3360 } | 3306 } |
3361 | 3307 |
3362 /* | 3308 /* |
3363 * And copy the data left in the buffer. | 3309 * And copy the data left in the buffer. |
3364 */ | 3310 */ |
3365 PORT_Memcpy(result->data, inBuffer, offset); | 3311 PORT_Memcpy(result->data, inBuffer, offset); |
3366 | 3312 |
3367 /* and free the temporary buffer */ | 3313 /* and free the temporary buffer */ |
3368 PORT_Free(inBuffer); | 3314 PORT_Free(inBuffer); |
3369 return result; | 3315 return result; |
3370 } | 3316 } |
3371 | 3317 |
3372 SECStatus | 3318 SECStatus |
3373 CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath) | 3319 CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath) |
3374 { | 3320 { |
3375 return ocsp_ParseURL(url, pHostname, pPort, pPath); | 3321 return ocsp_ParseURL(url, pHostname, pPort, pPath); |
3376 } | 3322 } |
3377 | 3323 |
3378 /* | 3324 /* |
3379 * Limit the size of http responses we are willing to accept. | 3325 * Limit the size of http responses we are willing to accept. |
3380 */ | 3326 */ |
3381 #define MAX_WANTED_OCSP_RESPONSE_LEN 64*1024 | 3327 #define MAX_WANTED_OCSP_RESPONSE_LEN 64 * 1024 |
3382 | 3328 |
3383 /* if (encodedRequest == NULL) | 3329 /* if (encodedRequest == NULL) |
3384 * then location MUST already include the full request, | 3330 * then location MUST already include the full request, |
3385 * including base64 and urlencode, | 3331 * including base64 and urlencode, |
3386 * and the request will be sent with GET | 3332 * and the request will be sent with GET |
3387 * if (encodedRequest != NULL) | 3333 * if (encodedRequest != NULL) |
3388 * then the request will be sent with POST | 3334 * then the request will be sent with POST |
3389 */ | 3335 */ |
3390 static SECItem * | 3336 static SECItem * |
3391 fetchOcspHttpClientV1(PLArenaPool *arena, | 3337 fetchOcspHttpClientV1(PLArenaPool *arena, |
3392 const SEC_HttpClientFcnV1 *hcv1, | 3338 const SEC_HttpClientFcnV1 *hcv1, |
3393 const char *location, | 3339 const char *location, |
3394 const SECItem *encodedRequest) | 3340 const SECItem *encodedRequest) |
3395 { | 3341 { |
3396 char *hostname = NULL; | 3342 char *hostname = NULL; |
3397 char *path = NULL; | 3343 char *path = NULL; |
3398 PRUint16 port; | 3344 PRUint16 port; |
3399 SECItem *encodedResponse = NULL; | 3345 SECItem *encodedResponse = NULL; |
3400 SEC_HTTP_SERVER_SESSION pServerSession = NULL; | 3346 SEC_HTTP_SERVER_SESSION pServerSession = NULL; |
3401 SEC_HTTP_REQUEST_SESSION pRequestSession = NULL; | 3347 SEC_HTTP_REQUEST_SESSION pRequestSession = NULL; |
3402 PRUint16 myHttpResponseCode; | 3348 PRUint16 myHttpResponseCode; |
3403 const char *myHttpResponseData; | 3349 const char *myHttpResponseData; |
3404 PRUint32 myHttpResponseDataLen; | 3350 PRUint32 myHttpResponseDataLen; |
3405 | 3351 |
3406 if (ocsp_ParseURL(location, &hostname, &port, &path) == SECFailure) { | 3352 if (ocsp_ParseURL(location, &hostname, &port, &path) == SECFailure) { |
3407 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST); | 3353 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST); |
3408 goto loser; | 3354 goto loser; |
3409 } | 3355 } |
3410 | 3356 |
3411 PORT_Assert(hostname != NULL); | 3357 PORT_Assert(hostname != NULL); |
3412 PORT_Assert(path != NULL); | 3358 PORT_Assert(path != NULL); |
3413 | 3359 |
3414 if ((*hcv1->createSessionFcn)( | 3360 if ((*hcv1->createSessionFcn)( |
3415 hostname, | 3361 hostname, |
3416 port, | 3362 port, |
3417 &pServerSession) != SECSuccess) { | 3363 &pServerSession) != SECSuccess) { |
3418 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); | 3364 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); |
3419 goto loser; | 3365 goto loser; |
3420 } | 3366 } |
3421 | 3367 |
3422 /* We use a non-zero timeout, which means: | 3368 /* We use a non-zero timeout, which means: |
3423 - the client will use blocking I/O | 3369 - the client will use blocking I/O |
3424 - TryFcn will not return WOULD_BLOCK nor a poll descriptor | 3370 - TryFcn will not return WOULD_BLOCK nor a poll descriptor |
3425 - it's sufficient to call TryFcn once | 3371 - it's sufficient to call TryFcn once |
3426 No lock for accessing OCSP_Global.timeoutSeconds, bug 406120 | 3372 No lock for accessing OCSP_Global.timeoutSeconds, bug 406120 |
3427 */ | 3373 */ |
3428 | 3374 |
3429 if ((*hcv1->createFcn)( | 3375 if ((*hcv1->createFcn)( |
3430 pServerSession, | 3376 pServerSession, |
3431 "http", | 3377 "http", |
3432 path, | 3378 path, |
3433 encodedRequest ? "POST" : "GET", | 3379 encodedRequest ? "POST" : "GET", |
3434 PR_TicksPerSecond() * OCSP_Global.timeoutSeconds, | 3380 PR_TicksPerSecond() * OCSP_Global.timeoutSeconds, |
3435 &pRequestSession) != SECSuccess) { | 3381 &pRequestSession) != SECSuccess) { |
3436 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); | 3382 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); |
3437 goto loser; | 3383 goto loser; |
3438 } | 3384 } |
3439 | 3385 |
3440 if (encodedRequest && | 3386 if (encodedRequest && |
3441 (*hcv1->setPostDataFcn)( | 3387 (*hcv1->setPostDataFcn)( |
3442 pRequestSession, | 3388 pRequestSession, |
3443 (char*)encodedRequest->data, | 3389 (char *)encodedRequest->data, |
3444 encodedRequest->len, | 3390 encodedRequest->len, |
3445 "application/ocsp-request") != SECSuccess) { | 3391 "application/ocsp-request") != SECSuccess) { |
3446 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); | 3392 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); |
3447 goto loser; | 3393 goto loser; |
3448 } | 3394 } |
3449 | 3395 |
3450 /* we don't want result objects larger than this: */ | 3396 /* we don't want result objects larger than this: */ |
3451 myHttpResponseDataLen = MAX_WANTED_OCSP_RESPONSE_LEN; | 3397 myHttpResponseDataLen = MAX_WANTED_OCSP_RESPONSE_LEN; |
3452 | 3398 |
3453 OCSP_TRACE(("OCSP trySendAndReceive %s\n", location)); | 3399 OCSP_TRACE(("OCSP trySendAndReceive %s\n", location)); |
3454 | 3400 |
3455 if ((*hcv1->trySendAndReceiveFcn)( | 3401 if ((*hcv1->trySendAndReceiveFcn)( |
3456 pRequestSession, | 3402 pRequestSession, |
3457 NULL, | 3403 NULL, |
3458 &myHttpResponseCode, | 3404 &myHttpResponseCode, |
3459 NULL, | 3405 NULL, |
3460 NULL, | 3406 NULL, |
3461 &myHttpResponseData, | 3407 &myHttpResponseData, |
3462 &myHttpResponseDataLen) != SECSuccess) { | 3408 &myHttpResponseDataLen) != SECSuccess) { |
3463 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); | 3409 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); |
3464 goto loser; | 3410 goto loser; |
3465 } | 3411 } |
3466 | 3412 |
3467 OCSP_TRACE(("OCSP trySendAndReceive result http %d\n", myHttpResponseCode)); | 3413 OCSP_TRACE(("OCSP trySendAndReceive result http %d\n", myHttpResponseCode)); |
3468 | 3414 |
3469 if (myHttpResponseCode != 200) { | 3415 if (myHttpResponseCode != 200) { |
3470 PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | 3416 PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
3471 goto loser; | 3417 goto loser; |
3472 } | 3418 } |
3473 | 3419 |
3474 encodedResponse = SECITEM_AllocItem(arena, NULL, myHttpResponseDataLen); | 3420 encodedResponse = SECITEM_AllocItem(arena, NULL, myHttpResponseDataLen); |
3475 | 3421 |
3476 if (!encodedResponse) { | 3422 if (!encodedResponse) { |
3477 PORT_SetError(SEC_ERROR_NO_MEMORY); | 3423 PORT_SetError(SEC_ERROR_NO_MEMORY); |
3478 goto loser; | 3424 goto loser; |
3479 } | 3425 } |
3480 | 3426 |
3481 PORT_Memcpy(encodedResponse->data, myHttpResponseData, myHttpResponseDataLen
); | 3427 PORT_Memcpy(encodedResponse->data, myHttpResponseData, myHttpResponseDataLen
); |
3482 | 3428 |
3483 loser: | 3429 loser: |
3484 if (pRequestSession != NULL) | 3430 if (pRequestSession != NULL) |
3485 (*hcv1->freeFcn)(pRequestSession); | 3431 (*hcv1->freeFcn)(pRequestSession); |
3486 if (pServerSession != NULL) | 3432 if (pServerSession != NULL) |
3487 (*hcv1->freeSessionFcn)(pServerSession); | 3433 (*hcv1->freeSessionFcn)(pServerSession); |
3488 if (path != NULL) | 3434 if (path != NULL) |
3489 » PORT_Free(path); | 3435 PORT_Free(path); |
3490 if (hostname != NULL) | 3436 if (hostname != NULL) |
3491 » PORT_Free(hostname); | 3437 PORT_Free(hostname); |
3492 | 3438 |
3493 return encodedResponse; | 3439 return encodedResponse; |
3494 } | 3440 } |
3495 | 3441 |
3496 /* | 3442 /* |
3497 * FUNCTION: CERT_GetEncodedOCSPResponseByMethod | 3443 * FUNCTION: CERT_GetEncodedOCSPResponseByMethod |
3498 * Creates and sends a request to an OCSP responder, then reads and | 3444 * Creates and sends a request to an OCSP responder, then reads and |
3499 * returns the (encoded) response. | 3445 * returns the (encoded) response. |
3500 * INPUTS: | 3446 * INPUTS: |
3501 * PLArenaPool *arena | 3447 * PLArenaPool *arena |
3502 * Pointer to arena from which return value will be allocated. | 3448 * Pointer to arena from which return value will be allocated. |
3503 * If NULL, result will be allocated from the heap (and thus should | 3449 * If NULL, result will be allocated from the heap (and thus should |
3504 * be freed via SECITEM_FreeItem). | 3450 * be freed via SECITEM_FreeItem). |
3505 * CERTCertList *certList | 3451 * CERTCertList *certList |
3506 * A list of certs for which status will be requested. | 3452 * A list of certs for which status will be requested. |
3507 * Note that all of these certificates should have the same issuer, | 3453 * Note that all of these certificates should have the same issuer, |
3508 * or it's expected the response will be signed by a trusted responder. | 3454 * or it's expected the response will be signed by a trusted responder. |
3509 * If the certs need to be broken up into multiple requests, that | 3455 * If the certs need to be broken up into multiple requests, that |
3510 * must be handled by the caller (and thus by having multiple calls | 3456 * must be handled by the caller (and thus by having multiple calls |
3511 * to this routine), who knows about where the request(s) are being | 3457 * to this routine), who knows about where the request(s) are being |
3512 * sent and whether there are any trusted responders in place. | 3458 * sent and whether there are any trusted responders in place. |
3513 * const char *location | 3459 * const char *location |
3514 * The location of the OCSP responder (a URL). | 3460 * The location of the OCSP responder (a URL). |
3515 * const char *method | 3461 * const char *method |
3516 * The protocol method used when retrieving the OCSP response. | 3462 * The protocol method used when retrieving the OCSP response. |
3517 * Currently support: "GET" (http GET) and "POST" (http POST). | 3463 * Currently support: "GET" (http GET) and "POST" (http POST). |
3518 * Additionals methods for http or other protocols might be added | 3464 * Additionals methods for http or other protocols might be added |
3519 * in the future. | 3465 * in the future. |
3520 * PRTime time | 3466 * PRTime time |
3521 * Indicates the time for which the certificate status is to be | 3467 * Indicates the time for which the certificate status is to be |
3522 * determined -- this may be used in the search for the cert's issuer | 3468 * determined -- this may be used in the search for the cert's issuer |
3523 * but has no other bearing on the operation. | 3469 * but has no other bearing on the operation. |
3524 * PRBool addServiceLocator | 3470 * PRBool addServiceLocator |
3525 * If true, the Service Locator extension should be added to the | 3471 * If true, the Service Locator extension should be added to the |
3526 * single request(s) for each cert. | 3472 * single request(s) for each cert. |
3527 * CERTCertificate *signerCert | 3473 * CERTCertificate *signerCert |
3528 * If non-NULL, means sign the request using this cert. Otherwise, | 3474 * If non-NULL, means sign the request using this cert. Otherwise, |
3529 * do not sign. | 3475 * do not sign. |
3530 * void *pwArg | 3476 * void *pwArg |
3531 * Pointer to argument for password prompting, if needed. (Definitely | 3477 * Pointer to argument for password prompting, if needed. (Definitely |
3532 * not needed if not signing.) | 3478 * not needed if not signing.) |
3533 * OUTPUTS: | 3479 * OUTPUTS: |
3534 * CERTOCSPRequest **pRequest | 3480 * CERTOCSPRequest **pRequest |
3535 * Pointer in which to store the OCSP request created for the given | 3481 * Pointer in which to store the OCSP request created for the given |
3536 * list of certificates. It is only filled in if the entire operation | 3482 * list of certificates. It is only filled in if the entire operation |
3537 * is successful and the pointer is not null -- and in that case the | 3483 * is successful and the pointer is not null -- and in that case the |
3538 * caller is then reponsible for destroying it. | 3484 * caller is then reponsible for destroying it. |
3539 * RETURN: | 3485 * RETURN: |
3540 * Returns a pointer to the SECItem holding the response. | 3486 * Returns a pointer to the SECItem holding the response. |
3541 * On error, returns null with error set describing the reason: | 3487 * On error, returns null with error set describing the reason: |
3542 * SEC_ERROR_UNKNOWN_ISSUER | 3488 * SEC_ERROR_UNKNOWN_ISSUER |
3543 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION | 3489 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION |
3544 * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE | 3490 * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE |
3545 * Other errors are low-level problems (no memory, bad database, etc.). | 3491 * Other errors are low-level problems (no memory, bad database, etc.). |
3546 */ | 3492 */ |
3547 SECItem * | 3493 SECItem * |
3548 CERT_GetEncodedOCSPResponseByMethod(PLArenaPool *arena, CERTCertList *certList, | 3494 CERT_GetEncodedOCSPResponseByMethod(PLArenaPool *arena, CERTCertList *certList, |
3549 » » » » const char *location, const char *method, | 3495 const char *location, const char *method, |
3550 » » » » PRTime time, PRBool addServiceLocator, | 3496 PRTime time, PRBool addServiceLocator, |
3551 » » » » CERTCertificate *signerCert, void *pwArg, | 3497 CERTCertificate *signerCert, void *pwArg, |
3552 » » » » CERTOCSPRequest **pRequest) | 3498 CERTOCSPRequest **pRequest) |
3553 { | 3499 { |
3554 CERTOCSPRequest *request; | 3500 CERTOCSPRequest *request; |
3555 request = CERT_CreateOCSPRequest(certList, time, addServiceLocator, | 3501 request = CERT_CreateOCSPRequest(certList, time, addServiceLocator, |
3556 signerCert); | 3502 signerCert); |
3557 if (!request) | 3503 if (!request) |
3558 return NULL; | 3504 return NULL; |
3559 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, | 3505 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, |
3560 method, time, addServiceLocato
r, | 3506 method, time, addServiceLocato
r, |
3561 pwArg, pRequest); | 3507 pwArg, pRequest); |
3562 } | 3508 } |
3563 | 3509 |
3564 /* | 3510 /* |
3565 * FUNCTION: CERT_GetEncodedOCSPResponse | 3511 * FUNCTION: CERT_GetEncodedOCSPResponse |
3566 * Creates and sends a request to an OCSP responder, then reads and | 3512 * Creates and sends a request to an OCSP responder, then reads and |
3567 * returns the (encoded) response. | 3513 * returns the (encoded) response. |
3568 * | 3514 * |
3569 * This is a legacy API that behaves identically to | 3515 * This is a legacy API that behaves identically to |
3570 * CERT_GetEncodedOCSPResponseByMethod using the "POST" method. | 3516 * CERT_GetEncodedOCSPResponseByMethod using the "POST" method. |
3571 */ | 3517 */ |
3572 SECItem * | 3518 SECItem * |
3573 CERT_GetEncodedOCSPResponse(PLArenaPool *arena, CERTCertList *certList, | 3519 CERT_GetEncodedOCSPResponse(PLArenaPool *arena, CERTCertList *certList, |
3574 » » » const char *location, PRTime time, | 3520 const char *location, PRTime time, |
3575 » » » PRBool addServiceLocator, | 3521 PRBool addServiceLocator, |
3576 » » » CERTCertificate *signerCert, void *pwArg, | 3522 CERTCertificate *signerCert, void *pwArg, |
3577 » » » CERTOCSPRequest **pRequest) | 3523 CERTOCSPRequest **pRequest) |
3578 { | 3524 { |
3579 return CERT_GetEncodedOCSPResponseByMethod(arena, certList, location, | 3525 return CERT_GetEncodedOCSPResponseByMethod(arena, certList, location, |
3580 » » » » » "POST", time, addServiceLocator, | 3526 "POST", time, addServiceLocator, |
3581 » » » » » signerCert, pwArg, pRequest); | 3527 signerCert, pwArg, pRequest); |
3582 } | 3528 } |
3583 | 3529 |
3584 /* URL encode a buffer that consists of base64-characters, only, | 3530 /* URL encode a buffer that consists of base64-characters, only, |
3585 * which means we can use a simple encoding logic. | 3531 * which means we can use a simple encoding logic. |
3586 * | 3532 * |
3587 * No output buffer size checking is performed. | 3533 * No output buffer size checking is performed. |
3588 * You should call the function twice, to calculate the required buffer size. | 3534 * You should call the function twice, to calculate the required buffer size. |
3589 * | 3535 * |
3590 * If the outpufBuf parameter is NULL, the function will calculate the | 3536 * If the outpufBuf parameter is NULL, the function will calculate the |
3591 * required size, including the trailing zero termination char. | 3537 * required size, including the trailing zero termination char. |
3592 * | 3538 * |
3593 * The function returns the number of bytes calculated or produced. | 3539 * The function returns the number of bytes calculated or produced. |
3594 */ | 3540 */ |
3595 size_t | 3541 size_t |
3596 ocsp_UrlEncodeBase64Buf(const char *base64Buf, char *outputBuf) | 3542 ocsp_UrlEncodeBase64Buf(const char *base64Buf, char *outputBuf) |
3597 { | 3543 { |
3598 const char *walkInput = NULL; | 3544 const char *walkInput = NULL; |
3599 char *walkOutput = outputBuf; | 3545 char *walkOutput = outputBuf; |
3600 size_t count = 0; | 3546 size_t count = 0; |
3601 | 3547 |
3602 for (walkInput=base64Buf; *walkInput; ++walkInput) { | 3548 for (walkInput = base64Buf; *walkInput; ++walkInput) { |
3603 » char c = *walkInput; | 3549 char c = *walkInput; |
3604 » if (isspace(c)) | 3550 if (isspace(c)) |
3605 » continue; | 3551 continue; |
3606 » switch (c) { | 3552 switch (c) { |
3607 » case '+': | 3553 case '+': |
3608 » if (outputBuf) { | 3554 if (outputBuf) { |
3609 » » strcpy(walkOutput, "%2B"); | 3555 strcpy(walkOutput, "%2B"); |
3610 » » walkOutput += 3; | 3556 walkOutput += 3; |
3611 » } | 3557 } |
3612 » count += 3; | 3558 count += 3; |
3613 » break; | 3559 break; |
3614 » case '/': | 3560 case '/': |
3615 » if (outputBuf) { | 3561 if (outputBuf) { |
3616 » » strcpy(walkOutput, "%2F"); | 3562 strcpy(walkOutput, "%2F"); |
3617 » » walkOutput += 3; | 3563 walkOutput += 3; |
3618 » } | 3564 } |
3619 » count += 3; | 3565 count += 3; |
3620 » break; | 3566 break; |
3621 » case '=': | 3567 case '=': |
3622 » if (outputBuf) { | 3568 if (outputBuf) { |
3623 » » strcpy(walkOutput, "%3D"); | 3569 strcpy(walkOutput, "%3D"); |
3624 » » walkOutput += 3; | 3570 walkOutput += 3; |
3625 » } | 3571 } |
3626 » count += 3; | 3572 count += 3; |
3627 » break; | 3573 break; |
3628 » default: | 3574 default: |
3629 » if (outputBuf) { | 3575 if (outputBuf) { |
3630 » » *walkOutput = *walkInput; | 3576 *walkOutput = *walkInput; |
3631 » » ++walkOutput; | 3577 ++walkOutput; |
3632 » } | 3578 } |
3633 » ++count; | 3579 ++count; |
3634 » break; | 3580 break; |
3635 » } | 3581 } |
3636 } | 3582 } |
3637 if (outputBuf) { | 3583 if (outputBuf) { |
3638 » *walkOutput = 0; | 3584 *walkOutput = 0; |
3639 } | 3585 } |
3640 ++count; | 3586 ++count; |
3641 return count; | 3587 return count; |
3642 } | 3588 } |
3643 | 3589 |
3644 enum { max_get_request_size = 255 }; /* defined by RFC2560 */ | 3590 enum { max_get_request_size = 255 }; /* defined by RFC2560 */ |
3645 | 3591 |
3646 static SECItem * | 3592 static SECItem * |
3647 cert_GetOCSPResponse(PLArenaPool *arena, const char *location, | 3593 cert_GetOCSPResponse(PLArenaPool *arena, const char *location, |
3648 const SECItem *encodedRequest); | 3594 const SECItem *encodedRequest); |
3649 | 3595 |
3650 static SECItem * | 3596 static SECItem * |
3651 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena, | 3597 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena, |
3652 CERTOCSPRequest *request, | 3598 CERTOCSPRequest *request, |
3653 const char *location, | 3599 const char *location, |
3654 » » » » const char *method, | 3600 const char *method, |
3655 » » » » PRTime time, | 3601 PRTime time, |
3656 PRBool addServiceLocator, | 3602 PRBool addServiceLocator, |
3657 void *pwArg, | 3603 void *pwArg, |
3658 CERTOCSPRequest **pRequest) | 3604 CERTOCSPRequest **pRequest) |
3659 { | 3605 { |
3660 SECItem *encodedRequest = NULL; | 3606 SECItem *encodedRequest = NULL; |
3661 SECItem *encodedResponse = NULL; | 3607 SECItem *encodedResponse = NULL; |
3662 SECStatus rv; | 3608 SECStatus rv; |
3663 | 3609 |
3664 if (!location || !*location) /* location should be at least one byte */ | 3610 if (!location || !*location) /* location should be at least one byte */ |
3665 goto loser; | 3611 goto loser; |
3666 | 3612 |
3667 rv = CERT_AddOCSPAcceptableResponses(request, | 3613 rv = CERT_AddOCSPAcceptableResponses(request, |
3668 » » » » » SEC_OID_PKIX_OCSP_BASIC_RESPONSE); | 3614 SEC_OID_PKIX_OCSP_BASIC_RESPONSE); |
3669 if (rv != SECSuccess) | 3615 if (rv != SECSuccess) |
3670 » goto loser; | 3616 goto loser; |
3671 | 3617 |
3672 encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg); | 3618 encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg); |
3673 if (encodedRequest == NULL) | 3619 if (encodedRequest == NULL) |
3674 » goto loser; | 3620 goto loser; |
3675 | 3621 |
3676 if (!strcmp(method, "GET")) { | 3622 if (!strcmp(method, "GET")) { |
3677 encodedResponse = cert_GetOCSPResponse(arena, location, encodedRequest); | 3623 encodedResponse = cert_GetOCSPResponse(arena, location, encodedRequest); |
3678 } | 3624 } else if (!strcmp(method, "POST")) { |
3679 else if (!strcmp(method, "POST")) { | |
3680 encodedResponse = CERT_PostOCSPRequest(arena, location, encodedRequest); | 3625 encodedResponse = CERT_PostOCSPRequest(arena, location, encodedRequest); |
3681 } | 3626 } else { |
3682 else { | 3627 goto loser; |
3683 » goto loser; | |
3684 } | 3628 } |
3685 | 3629 |
3686 if (encodedResponse != NULL && pRequest != NULL) { | 3630 if (encodedResponse != NULL && pRequest != NULL) { |
3687 » *pRequest = request; | 3631 *pRequest = request; |
3688 » request = NULL;»» » /* avoid destroying below */ | 3632 request = NULL; /* avoid destroying below */ |
3689 } | 3633 } |
3690 | 3634 |
3691 loser: | 3635 loser: |
3692 if (request != NULL) | 3636 if (request != NULL) |
3693 » CERT_DestroyOCSPRequest(request); | 3637 CERT_DestroyOCSPRequest(request); |
3694 if (encodedRequest != NULL) | 3638 if (encodedRequest != NULL) |
3695 » SECITEM_FreeItem(encodedRequest, PR_TRUE); | 3639 SECITEM_FreeItem(encodedRequest, PR_TRUE); |
3696 return encodedResponse; | 3640 return encodedResponse; |
3697 } | 3641 } |
3698 | 3642 |
3699 static SECItem * | 3643 static SECItem * |
3700 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location, | 3644 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location, |
3701 const SECItem *encodedRequest); | 3645 const SECItem *encodedRequest); |
3702 | 3646 |
3703 /* using HTTP GET method */ | 3647 /* using HTTP GET method */ |
3704 static SECItem * | 3648 static SECItem * |
3705 cert_GetOCSPResponse(PLArenaPool *arena, const char *location, | 3649 cert_GetOCSPResponse(PLArenaPool *arena, const char *location, |
3706 const SECItem *encodedRequest) | 3650 const SECItem *encodedRequest) |
3707 { | 3651 { |
3708 char *walkOutput = NULL; | 3652 char *walkOutput = NULL; |
3709 char *fullGetPath = NULL; | 3653 char *fullGetPath = NULL; |
3710 size_t pathLength; | 3654 size_t pathLength; |
3711 PRInt32 urlEncodedBufLength; | 3655 PRInt32 urlEncodedBufLength; |
3712 size_t base64size; | 3656 size_t base64size; |
3713 char b64ReqBuf[max_get_request_size+1]; | 3657 char b64ReqBuf[max_get_request_size + 1]; |
3714 size_t slashLengthIfNeeded = 0; | 3658 size_t slashLengthIfNeeded = 0; |
3715 size_t getURLLength; | 3659 size_t getURLLength; |
3716 SECItem *item; | 3660 SECItem *item; |
3717 | 3661 |
3718 if (!location || !*location) { | 3662 if (!location || !*location) { |
3719 » return NULL; | 3663 return NULL; |
3720 } | 3664 } |
3721 | 3665 |
3722 pathLength = strlen(location); | 3666 pathLength = strlen(location); |
3723 if (location[pathLength-1] != '/') { | 3667 if (location[pathLength - 1] != '/') { |
3724 » slashLengthIfNeeded = 1; | 3668 slashLengthIfNeeded = 1; |
3725 } | 3669 } |
3726 | 3670 |
3727 /* Calculation as documented by PL_Base64Encode function. | 3671 /* Calculation as documented by PL_Base64Encode function. |
3728 * Use integer conversion to avoid having to use function ceil(). | 3672 * Use integer conversion to avoid having to use function ceil(). |
3729 */ | 3673 */ |
3730 base64size = (((encodedRequest->len +2)/3) * 4); | 3674 base64size = (((encodedRequest->len + 2) / 3) * 4); |
3731 if (base64size > max_get_request_size) { | 3675 if (base64size > max_get_request_size) { |
3732 » return NULL; | 3676 return NULL; |
3733 } | 3677 } |
3734 memset(b64ReqBuf, 0, sizeof(b64ReqBuf)); | 3678 memset(b64ReqBuf, 0, sizeof(b64ReqBuf)); |
3735 PL_Base64Encode((const char*)encodedRequest->data, encodedRequest->len, | 3679 PL_Base64Encode((const char *)encodedRequest->data, encodedRequest->len, |
3736 » » b64ReqBuf); | 3680 b64ReqBuf); |
3737 | 3681 |
3738 urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL); | 3682 urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL); |
3739 getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded; | 3683 getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded; |
3740 | 3684 |
3741 /* urlEncodedBufLength already contains room for the zero terminator. | 3685 /* urlEncodedBufLength already contains room for the zero terminator. |
3742 * Add another if we must add the '/' char. | 3686 * Add another if we must add the '/' char. |
3743 */ | 3687 */ |
3744 if (arena) { | 3688 if (arena) { |
3745 fullGetPath = (char*)PORT_ArenaAlloc(arena, getURLLength); | 3689 fullGetPath = (char *)PORT_ArenaAlloc(arena, getURLLength); |
3746 } else { | 3690 } else { |
3747 fullGetPath = (char*)PORT_Alloc(getURLLength); | 3691 fullGetPath = (char *)PORT_Alloc(getURLLength); |
3748 } | 3692 } |
3749 if (!fullGetPath) { | 3693 if (!fullGetPath) { |
3750 » return NULL; | 3694 return NULL; |
3751 } | 3695 } |
3752 | 3696 |
3753 strcpy(fullGetPath, location); | 3697 strcpy(fullGetPath, location); |
3754 walkOutput = fullGetPath + pathLength; | 3698 walkOutput = fullGetPath + pathLength; |
3755 | 3699 |
3756 if (walkOutput > fullGetPath && slashLengthIfNeeded) { | 3700 if (walkOutput > fullGetPath && slashLengthIfNeeded) { |
3757 strcpy(walkOutput, "/"); | 3701 strcpy(walkOutput, "/"); |
3758 ++walkOutput; | 3702 ++walkOutput; |
3759 } | 3703 } |
3760 ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput); | 3704 ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput); |
3761 | 3705 |
3762 item = cert_FetchOCSPResponse(arena, fullGetPath, NULL); | 3706 item = cert_FetchOCSPResponse(arena, fullGetPath, NULL); |
3763 if (!arena) { | 3707 if (!arena) { |
3764 » PORT_Free(fullGetPath); | 3708 PORT_Free(fullGetPath); |
3765 } | 3709 } |
3766 return item; | 3710 return item; |
3767 } | 3711 } |
3768 | 3712 |
3769 SECItem * | 3713 SECItem * |
3770 CERT_PostOCSPRequest(PLArenaPool *arena, const char *location, | 3714 CERT_PostOCSPRequest(PLArenaPool *arena, const char *location, |
3771 const SECItem *encodedRequest) | 3715 const SECItem *encodedRequest) |
3772 { | 3716 { |
3773 return cert_FetchOCSPResponse(arena, location, encodedRequest); | 3717 return cert_FetchOCSPResponse(arena, location, encodedRequest); |
3774 } | 3718 } |
3775 | 3719 |
3776 SECItem * | 3720 SECItem * |
3777 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location, | 3721 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location, |
3778 const SECItem *encodedRequest) | 3722 const SECItem *encodedRequest) |
3779 { | 3723 { |
3780 const SEC_HttpClientFcn *registeredHttpClient; | 3724 const SEC_HttpClientFcn *registeredHttpClient; |
3781 SECItem *encodedResponse = NULL; | 3725 SECItem *encodedResponse = NULL; |
3782 | 3726 |
3783 registeredHttpClient = SEC_GetRegisteredHttpClient(); | 3727 registeredHttpClient = SEC_GetRegisteredHttpClient(); |
3784 | 3728 |
3785 if (registeredHttpClient && registeredHttpClient->version == 1) { | 3729 if (registeredHttpClient && registeredHttpClient->version == 1) { |
3786 encodedResponse = fetchOcspHttpClientV1( | 3730 encodedResponse = fetchOcspHttpClientV1( |
3787 arena, | 3731 arena, |
3788 ®isteredHttpClient->fcnTable.ftable1, | 3732 ®isteredHttpClient->fcnTable.ftable1, |
3789 location, | 3733 location, |
3790 encodedRequest); | 3734 encodedRequest); |
3791 } else { | 3735 } else { |
3792 /* use internal http client */ | 3736 /* use internal http client */ |
3793 PRFileDesc *sock = ocsp_SendEncodedRequest(location, encodedRequest); | 3737 PRFileDesc *sock = ocsp_SendEncodedRequest(location, encodedRequest); |
3794 if (sock) { | 3738 if (sock) { |
3795 encodedResponse = ocsp_GetEncodedResponse(arena, sock); | 3739 encodedResponse = ocsp_GetEncodedResponse(arena, sock); |
3796 PR_Close(sock); | 3740 PR_Close(sock); |
3797 } | 3741 } |
3798 } | 3742 } |
3799 | 3743 |
3800 return encodedResponse; | 3744 return encodedResponse; |
3801 } | 3745 } |
3802 | 3746 |
3803 static SECItem * | 3747 static SECItem * |
3804 ocsp_GetEncodedOCSPResponseForSingleCert(PLArenaPool *arena, | 3748 ocsp_GetEncodedOCSPResponseForSingleCert(PLArenaPool *arena, |
3805 CERTOCSPCertID *certID, | 3749 CERTOCSPCertID *certID, |
3806 CERTCertificate *singleCert, | 3750 CERTCertificate *singleCert, |
3807 const char *location, | 3751 const char *location, |
3808 » » » » » const char *method, | 3752 const char *method, |
3809 » » » » » PRTime time, | 3753 PRTime time, |
3810 PRBool addServiceLocator, | 3754 PRBool addServiceLocator, |
3811 void *pwArg, | 3755 void *pwArg, |
3812 CERTOCSPRequest **pRequest) | 3756 CERTOCSPRequest **pRequest) |
3813 { | 3757 { |
3814 CERTOCSPRequest *request; | 3758 CERTOCSPRequest *request; |
3815 request = cert_CreateSingleCertOCSPRequest(certID, singleCert, time, | 3759 request = cert_CreateSingleCertOCSPRequest(certID, singleCert, time, |
3816 addServiceLocator, NULL); | 3760 addServiceLocator, NULL); |
3817 if (!request) | 3761 if (!request) |
3818 return NULL; | 3762 return NULL; |
3819 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, | 3763 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, |
3820 method, time, addServiceLocato
r, | 3764 method, time, addServiceLocato
r, |
3821 pwArg, pRequest); | 3765 pwArg, pRequest); |
3822 } | 3766 } |
3823 | 3767 |
3824 /* Checks a certificate for the key usage extension of OCSP signer. */ | 3768 /* Checks a certificate for the key usage extension of OCSP signer. */ |
3825 static PRBool | 3769 static PRBool |
3826 ocsp_CertIsOCSPDesignatedResponder(CERTCertificate *cert) | 3770 ocsp_CertIsOCSPDesignatedResponder(CERTCertificate *cert) |
3827 { | 3771 { |
3828 SECStatus rv; | 3772 SECStatus rv; |
3829 SECItem extItem; | 3773 SECItem extItem; |
3830 SECItem **oids; | 3774 SECItem **oids; |
3831 SECItem *oid; | 3775 SECItem *oid; |
3832 SECOidTag oidTag; | 3776 SECOidTag oidTag; |
3833 PRBool retval; | 3777 PRBool retval; |
3834 CERTOidSequence *oidSeq = NULL; | 3778 CERTOidSequence *oidSeq = NULL; |
3835 | 3779 |
3836 | |
3837 extItem.data = NULL; | 3780 extItem.data = NULL; |
3838 rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem); | 3781 rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem); |
3839 if ( rv != SECSuccess ) { | 3782 if (rv != SECSuccess) { |
3840 » goto loser; | 3783 goto loser; |
3841 } | 3784 } |
3842 | 3785 |
3843 oidSeq = CERT_DecodeOidSequence(&extItem); | 3786 oidSeq = CERT_DecodeOidSequence(&extItem); |
3844 if ( oidSeq == NULL ) { | 3787 if (oidSeq == NULL) { |
3845 » goto loser; | 3788 goto loser; |
3846 } | 3789 } |
3847 | 3790 |
3848 oids = oidSeq->oids; | 3791 oids = oidSeq->oids; |
3849 while ( *oids != NULL ) { | 3792 while (*oids != NULL) { |
3850 » oid = *oids; | 3793 oid = *oids; |
3851 » | 3794 |
3852 » oidTag = SECOID_FindOIDTag(oid); | 3795 oidTag = SECOID_FindOIDTag(oid); |
3853 » | 3796 |
3854 » if ( oidTag == SEC_OID_OCSP_RESPONDER ) { | 3797 if (oidTag == SEC_OID_OCSP_RESPONDER) { |
3855 » goto success; | 3798 goto success; |
3856 » } | 3799 } |
3857 » | 3800 |
3858 » oids++; | 3801 oids++; |
3859 } | 3802 } |
3860 | 3803 |
3861 loser: | 3804 loser: |
3862 retval = PR_FALSE; | 3805 retval = PR_FALSE; |
3863 PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT); | 3806 PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT); |
3864 goto done; | 3807 goto done; |
3865 success: | 3808 success: |
3866 retval = PR_TRUE; | 3809 retval = PR_TRUE; |
3867 done: | 3810 done: |
3868 if ( extItem.data != NULL ) { | 3811 if (extItem.data != NULL) { |
3869 » PORT_Free(extItem.data); | 3812 PORT_Free(extItem.data); |
3870 } | 3813 } |
3871 if ( oidSeq != NULL ) { | 3814 if (oidSeq != NULL) { |
3872 » CERT_DestroyOidSequence(oidSeq); | 3815 CERT_DestroyOidSequence(oidSeq); |
3873 } | 3816 } |
3874 | 3817 |
3875 return(retval); | 3818 return (retval); |
3876 } | 3819 } |
3877 | 3820 |
3878 | 3821 #ifdef LATER /* |
3879 #ifdef LATER» /* | 3822 * XXX This function is not currently used, but will |
3880 » » * XXX This function is not currently used, but will | 3823 * be needed later when we do revocation checking of |
3881 » » * be needed later when we do revocation checking of | 3824 * the responder certificate. Of course, it may need |
3882 » » * the responder certificate. Of course, it may need | 3825 * revising then, if the cert extension interface has |
3883 » » * revising then, if the cert extension interface has | 3826 * changed. (Hopefully it will!) |
3884 » » * changed. (Hopefully it will!) | 3827 */ |
3885 » » */ | |
3886 | 3828 |
3887 /* Checks a certificate to see if it has the OCSP no check extension. */ | 3829 /* Checks a certificate to see if it has the OCSP no check extension. */ |
3888 static PRBool | 3830 static PRBool |
3889 ocsp_CertHasNoCheckExtension(CERTCertificate *cert) | 3831 ocsp_CertHasNoCheckExtension(CERTCertificate *cert) |
3890 { | 3832 { |
3891 SECStatus rv; | 3833 SECStatus rv; |
3892 | 3834 |
3893 rv = CERT_FindCertExtension(cert, SEC_OID_PKIX_OCSP_NO_CHECK, | 3835 rv = CERT_FindCertExtension(cert, SEC_OID_PKIX_OCSP_NO_CHECK, |
3894 » » » » NULL); | 3836 NULL); |
3895 if (rv == SECSuccess) { | 3837 if (rv == SECSuccess) { |
3896 » return PR_TRUE; | 3838 return PR_TRUE; |
3897 } | 3839 } |
3898 return PR_FALSE; | 3840 return PR_FALSE; |
3899 } | 3841 } |
3900 #endif» /* LATER */ | 3842 #endif /* LATER */ |
3901 | 3843 |
3902 static PRBool | 3844 static PRBool |
3903 ocsp_matchcert(SECItem *certIndex,CERTCertificate *testCert) | 3845 ocsp_matchcert(SECItem *certIndex, CERTCertificate *testCert) |
3904 { | 3846 { |
3905 SECItem item; | 3847 SECItem item; |
3906 unsigned char buf[HASH_LENGTH_MAX]; | 3848 unsigned char buf[HASH_LENGTH_MAX]; |
3907 | 3849 |
3908 item.data = buf; | 3850 item.data = buf; |
3909 item.len = SHA1_LENGTH; | 3851 item.len = SHA1_LENGTH; |
3910 | 3852 |
3911 if (CERT_GetSubjectPublicKeyDigest(NULL,testCert,SEC_OID_SHA1, | 3853 if (CERT_GetSubjectPublicKeyDigest(NULL, testCert, SEC_OID_SHA1, |
3912 » » » » &item) == NULL) { | 3854 &item) == NULL) { |
3913 » return PR_FALSE; | 3855 return PR_FALSE; |
3914 } | 3856 } |
3915 if (SECITEM_ItemsAreEqual(certIndex,&item)) { | 3857 if (SECITEM_ItemsAreEqual(certIndex, &item)) { |
3916 » return PR_TRUE; | 3858 return PR_TRUE; |
3917 } | 3859 } |
3918 if (CERT_GetSubjectPublicKeyDigest(NULL,testCert,SEC_OID_MD5, | 3860 if (CERT_GetSubjectPublicKeyDigest(NULL, testCert, SEC_OID_MD5, |
3919 » » » » &item) == NULL) { | 3861 &item) == NULL) { |
3920 » return PR_FALSE; | 3862 return PR_FALSE; |
3921 } | 3863 } |
3922 if (SECITEM_ItemsAreEqual(certIndex,&item)) { | 3864 if (SECITEM_ItemsAreEqual(certIndex, &item)) { |
3923 » return PR_TRUE; | 3865 return PR_TRUE; |
3924 } | 3866 } |
3925 if (CERT_GetSubjectPublicKeyDigest(NULL,testCert,SEC_OID_MD2, | 3867 if (CERT_GetSubjectPublicKeyDigest(NULL, testCert, SEC_OID_MD2, |
3926 » » » » &item) == NULL) { | 3868 &item) == NULL) { |
3927 » return PR_FALSE; | 3869 return PR_FALSE; |
3928 } | 3870 } |
3929 if (SECITEM_ItemsAreEqual(certIndex,&item)) { | 3871 if (SECITEM_ItemsAreEqual(certIndex, &item)) { |
3930 » return PR_TRUE; | 3872 return PR_TRUE; |
3931 } | 3873 } |
3932 | 3874 |
3933 return PR_FALSE; | 3875 return PR_FALSE; |
3934 } | 3876 } |
3935 | 3877 |
3936 static CERTCertificate * | 3878 static CERTCertificate * |
3937 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID); | 3879 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle, CERTOCSPCertID *certID); |
3938 | 3880 |
3939 CERTCertificate * | 3881 CERTCertificate * |
3940 ocsp_GetSignerCertificate(CERTCertDBHandle *handle, ocspResponseData *tbsData, | 3882 ocsp_GetSignerCertificate(CERTCertDBHandle *handle, ocspResponseData *tbsData, |
3941 ocspSignature *signature, CERTCertificate *issuer) | 3883 ocspSignature *signature, CERTCertificate *issuer) |
3942 { | 3884 { |
3943 CERTCertificate **certs = NULL; | 3885 CERTCertificate **certs = NULL; |
3944 CERTCertificate *signerCert = NULL; | 3886 CERTCertificate *signerCert = NULL; |
3945 SECStatus rv = SECFailure; | 3887 SECStatus rv = SECFailure; |
3946 PRBool lookupByName = PR_TRUE; | 3888 PRBool lookupByName = PR_TRUE; |
3947 void *certIndex = NULL; | 3889 void *certIndex = NULL; |
3948 int certCount = 0; | 3890 int certCount = 0; |
3949 | 3891 |
3950 PORT_Assert(tbsData->responderID != NULL); | 3892 PORT_Assert(tbsData->responderID != NULL); |
3951 switch (tbsData->responderID->responderIDType) { | 3893 switch (tbsData->responderID->responderIDType) { |
3952 case ocspResponderID_byName: | 3894 case ocspResponderID_byName: |
3953 » lookupByName = PR_TRUE; | 3895 lookupByName = PR_TRUE; |
3954 » certIndex = &tbsData->derResponderID; | 3896 certIndex = &tbsData->derResponderID; |
3955 » break; | 3897 break; |
3956 case ocspResponderID_byKey: | 3898 case ocspResponderID_byKey: |
3957 » lookupByName = PR_FALSE; | 3899 lookupByName = PR_FALSE; |
3958 » certIndex = &tbsData->responderID->responderIDValue.keyHash; | 3900 certIndex = &tbsData->responderID->responderIDValue.keyHash; |
3959 » break; | 3901 break; |
3960 case ocspResponderID_other: | 3902 case ocspResponderID_other: |
3961 default: | 3903 default: |
3962 » PORT_Assert(0); | 3904 PORT_Assert(0); |
3963 » PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); | 3905 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); |
3964 » return NULL; | 3906 return NULL; |
3965 } | 3907 } |
3966 | 3908 |
3967 /* | 3909 /* |
3968 * If the signature contains some certificates as well, temporarily | 3910 * If the signature contains some certificates as well, temporarily |
3969 * import them in case they are needed for verification. | 3911 * import them in case they are needed for verification. |
3970 * | 3912 * |
3971 * Note that the result of this is that each cert in "certs" needs | 3913 * Note that the result of this is that each cert in "certs" needs |
3972 * to be destroyed. | 3914 * to be destroyed. |
3973 */ | 3915 */ |
3974 if (signature->derCerts != NULL) { | 3916 if (signature->derCerts != NULL) { |
3975 » for (; signature->derCerts[certCount] != NULL; certCount++) { | 3917 for (; signature->derCerts[certCount] != NULL; certCount++) { |
3976 » /* just counting */ | 3918 /* just counting */ |
3977 » } | 3919 } |
3978 » rv = CERT_ImportCerts(handle, certUsageStatusResponder, certCount, | 3920 rv = CERT_ImportCerts(handle, certUsageStatusResponder, certCount, |
3979 » signature->derCerts, &certs, | 3921 signature->derCerts, &certs, |
3980 » PR_FALSE, PR_FALSE, NULL); | 3922 PR_FALSE, PR_FALSE, NULL); |
3981 » if (rv != SECSuccess) | 3923 if (rv != SECSuccess) |
3982 » goto finish; | 3924 goto finish; |
3983 } | 3925 } |
3984 | 3926 |
3985 /* | 3927 /* |
3986 * Now look up the certificate that did the signing. | 3928 * Now look up the certificate that did the signing. |
3987 * The signer can be specified either by name or by key hash. | 3929 * The signer can be specified either by name or by key hash. |
3988 */ | 3930 */ |
3989 if (lookupByName) { | 3931 if (lookupByName) { |
3990 » SECItem *crIndex = (SECItem*)certIndex; | 3932 SECItem *crIndex = (SECItem *)certIndex; |
3991 » SECItem encodedName; | 3933 SECItem encodedName; |
3992 » PLArenaPool *arena; | 3934 PLArenaPool *arena; |
3993 | 3935 |
3994 » arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 3936 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
3995 » if (arena != NULL) { | 3937 if (arena != NULL) { |
3996 | 3938 |
3997 » rv = SEC_QuickDERDecodeItem(arena, &encodedName, | 3939 rv = SEC_QuickDERDecodeItem(arena, &encodedName, |
3998 » ocsp_ResponderIDDerNameTemplate, | 3940 ocsp_ResponderIDDerNameTemplate, |
3999 » crIndex); | 3941 crIndex); |
4000 » if (rv != SECSuccess) { | 3942 if (rv != SECSuccess) { |
4001 » if (PORT_GetError() == SEC_ERROR_BAD_DER) | 3943 if (PORT_GetError() == SEC_ERROR_BAD_DER) |
4002 » PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); | 3944 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); |
4003 » } else { | 3945 } else { |
4004 » signerCert = CERT_FindCertByName(handle, &encodedName); | 3946 signerCert = CERT_FindCertByName(handle, &encodedName); |
4005 » } | 3947 } |
4006 » PORT_FreeArena(arena, PR_FALSE); | 3948 PORT_FreeArena(arena, PR_FALSE); |
4007 » } | 3949 } |
4008 } else { | 3950 } else { |
4009 » /* | 3951 /* |
4010 » * The signer is either 1) a known issuer CA we passed in, | 3952 » * The signer is either 1) a known issuer CA we passed in, |
4011 » * 2) the default OCSP responder, or 3) an intermediate CA | 3953 » * 2) the default OCSP responder, or 3) an intermediate CA |
4012 » * passed in the cert list to use. Figure out which it is. | 3954 » * passed in the cert list to use. Figure out which it is. |
4013 » */ | 3955 » */ |
4014 » int i; | 3956 int i; |
4015 » CERTCertificate *responder = | 3957 CERTCertificate *responder = |
4016 ocsp_CertGetDefaultResponder(handle, NULL); | 3958 ocsp_CertGetDefaultResponder(handle, NULL); |
4017 » if (responder && ocsp_matchcert(certIndex,responder)) { | 3959 if (responder && ocsp_matchcert(certIndex, responder)) { |
4018 » signerCert = CERT_DupCertificate(responder); | 3960 signerCert = CERT_DupCertificate(responder); |
4019 » } else if (issuer && ocsp_matchcert(certIndex,issuer)) { | 3961 } else if (issuer && ocsp_matchcert(certIndex, issuer)) { |
4020 » signerCert = CERT_DupCertificate(issuer); | 3962 signerCert = CERT_DupCertificate(issuer); |
4021 » } | 3963 } |
4022 » for (i=0; (signerCert == NULL) && (i < certCount); i++) { | 3964 for (i = 0; (signerCert == NULL) && (i < certCount); i++) { |
4023 » if (ocsp_matchcert(certIndex,certs[i])) { | 3965 if (ocsp_matchcert(certIndex, certs[i])) { |
4024 » » signerCert = CERT_DupCertificate(certs[i]); | 3966 signerCert = CERT_DupCertificate(certs[i]); |
4025 » } | 3967 } |
4026 » } | 3968 } |
4027 » if (signerCert == NULL) { | 3969 if (signerCert == NULL) { |
4028 » PORT_SetError(SEC_ERROR_UNKNOWN_CERT); | 3970 PORT_SetError(SEC_ERROR_UNKNOWN_CERT); |
4029 » } | 3971 } |
4030 } | 3972 } |
4031 | 3973 |
4032 finish: | 3974 finish: |
4033 if (certs != NULL) { | 3975 if (certs != NULL) { |
4034 » CERT_DestroyCertArray(certs, certCount); | 3976 CERT_DestroyCertArray(certs, certCount); |
4035 } | 3977 } |
4036 | 3978 |
4037 return signerCert; | 3979 return signerCert; |
4038 } | 3980 } |
4039 | 3981 |
4040 SECStatus | 3982 SECStatus |
4041 ocsp_VerifyResponseSignature(CERTCertificate *signerCert, | 3983 ocsp_VerifyResponseSignature(CERTCertificate *signerCert, |
4042 ocspSignature *signature, | 3984 ocspSignature *signature, |
4043 SECItem *tbsResponseDataDER, | 3985 SECItem *tbsResponseDataDER, |
4044 void *pwArg) | 3986 void *pwArg) |
(...skipping 15 matching lines...) Expand all Loading... |
4060 * We copy the signature data *pointer* and length, so that we can | 4002 * We copy the signature data *pointer* and length, so that we can |
4061 * modify the length without damaging the original copy. This is a | 4003 * modify the length without damaging the original copy. This is a |
4062 * simple copy, not a dup, so no destroy/free is necessary. | 4004 * simple copy, not a dup, so no destroy/free is necessary. |
4063 */ | 4005 */ |
4064 signedData.signature = signature->signature; | 4006 signedData.signature = signature->signature; |
4065 signedData.signatureAlgorithm = signature->signatureAlgorithm; | 4007 signedData.signatureAlgorithm = signature->signatureAlgorithm; |
4066 signedData.data = *tbsResponseDataDER; | 4008 signedData.data = *tbsResponseDataDER; |
4067 | 4009 |
4068 rv = CERT_VerifySignedDataWithPublicKey(&signedData, signerKey, pwArg); | 4010 rv = CERT_VerifySignedDataWithPublicKey(&signedData, signerKey, pwArg); |
4069 if (rv != SECSuccess && | 4011 if (rv != SECSuccess && |
4070 (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE || | 4012 (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE || |
4071 PORT_GetError() == SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED)) { | 4013 PORT_GetError() == SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED)) { |
4072 PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE); | 4014 PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE); |
4073 } | 4015 } |
4074 | 4016 |
4075 if (signerKey != NULL) { | 4017 if (signerKey != NULL) { |
4076 SECKEY_DestroyPublicKey(signerKey); | 4018 SECKEY_DestroyPublicKey(signerKey); |
4077 } | 4019 } |
4078 | 4020 |
4079 return rv; | 4021 return rv; |
4080 } | 4022 } |
4081 | 4023 |
4082 | |
4083 /* | 4024 /* |
4084 * FUNCTION: CERT_VerifyOCSPResponseSignature | 4025 * FUNCTION: CERT_VerifyOCSPResponseSignature |
4085 * Check the signature on an OCSP Response. Will also perform a | 4026 * Check the signature on an OCSP Response. Will also perform a |
4086 * verification of the signer's certificate. Note, however, that a | 4027 * verification of the signer's certificate. Note, however, that a |
4087 * successful verification does not make any statement about the | 4028 * successful verification does not make any statement about the |
4088 * signer's *authority* to provide status for the certificate(s), | 4029 * signer's *authority* to provide status for the certificate(s), |
4089 * that must be checked individually for each certificate. | 4030 * that must be checked individually for each certificate. |
4090 * INPUTS: | 4031 * INPUTS: |
4091 * CERTOCSPResponse *response | 4032 * CERTOCSPResponse *response |
4092 * Pointer to response structure with signature to be checked. | 4033 * Pointer to response structure with signature to be checked. |
(...skipping 10 matching lines...) Expand all Loading... |
4103 * Possible errors set: | 4044 * Possible errors set: |
4104 * SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID | 4045 * SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID |
4105 * SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time | 4046 * SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time |
4106 * SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found | 4047 * SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found |
4107 * SEC_ERROR_BAD_SIGNATURE - the signature did not verify | 4048 * SEC_ERROR_BAD_SIGNATURE - the signature did not verify |
4108 * Other errors are any of the many possible failures in cert verification | 4049 * Other errors are any of the many possible failures in cert verification |
4109 * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when | 4050 * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when |
4110 * verifying the signer's cert, or low-level problems (no memory, etc.) | 4051 * verifying the signer's cert, or low-level problems (no memory, etc.) |
4111 */ | 4052 */ |
4112 SECStatus | 4053 SECStatus |
4113 CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,» | 4054 CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response, |
4114 » » » » CERTCertDBHandle *handle, void *pwArg, | 4055 CERTCertDBHandle *handle, void *pwArg, |
4115 » » » » CERTCertificate **pSignerCert, | 4056 CERTCertificate **pSignerCert, |
4116 » » » » CERTCertificate *issuer) | 4057 CERTCertificate *issuer) |
4117 { | 4058 { |
4118 SECItem *tbsResponseDataDER; | 4059 SECItem *tbsResponseDataDER; |
4119 CERTCertificate *signerCert = NULL; | 4060 CERTCertificate *signerCert = NULL; |
4120 SECStatus rv = SECFailure; | 4061 SECStatus rv = SECFailure; |
4121 PRTime producedAt; | 4062 PRTime producedAt; |
4122 | 4063 |
4123 /* ocsp_DecodeBasicOCSPResponse will fail if asn1 decoder is unable | 4064 /* ocsp_DecodeBasicOCSPResponse will fail if asn1 decoder is unable |
4124 * to properly decode tbsData (see the function and | 4065 * to properly decode tbsData (see the function and |
4125 * ocsp_BasicOCSPResponseTemplate). Thus, tbsData can not be | 4066 * ocsp_BasicOCSPResponseTemplate). Thus, tbsData can not be |
4126 * equal to null */ | 4067 * equal to null */ |
4127 ocspResponseData *tbsData = ocsp_GetResponseData(response, | 4068 ocspResponseData *tbsData = ocsp_GetResponseData(response, |
4128 &tbsResponseDataDER); | 4069 &tbsResponseDataDER); |
4129 ocspSignature *signature = ocsp_GetResponseSignature(response); | 4070 ocspSignature *signature = ocsp_GetResponseSignature(response); |
4130 | 4071 |
4131 if (!signature) { | 4072 if (!signature) { |
4132 PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE); | 4073 PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE); |
4133 return SECFailure; | 4074 return SECFailure; |
4134 } | 4075 } |
4135 | 4076 |
4136 /* | 4077 /* |
4137 * If this signature has already gone through verification, just | 4078 * If this signature has already gone through verification, just |
4138 * return the cached result. | 4079 * return the cached result. |
4139 */ | 4080 */ |
4140 if (signature->wasChecked) { | 4081 if (signature->wasChecked) { |
4141 » if (signature->status == SECSuccess) { | 4082 if (signature->status == SECSuccess) { |
4142 » if (pSignerCert != NULL) | 4083 if (pSignerCert != NULL) |
4143 » » *pSignerCert = CERT_DupCertificate(signature->cert); | 4084 *pSignerCert = CERT_DupCertificate(signature->cert); |
4144 » } else { | 4085 } else { |
4145 » PORT_SetError(signature->failureReason); | 4086 PORT_SetError(signature->failureReason); |
4146 » } | 4087 } |
4147 » return signature->status; | 4088 return signature->status; |
4148 } | 4089 } |
4149 | 4090 |
4150 signerCert = ocsp_GetSignerCertificate(handle, tbsData, | 4091 signerCert = ocsp_GetSignerCertificate(handle, tbsData, |
4151 signature, issuer); | 4092 signature, issuer); |
4152 if (signerCert == NULL) { | 4093 if (signerCert == NULL) { |
4153 » rv = SECFailure; | 4094 rv = SECFailure; |
4154 » if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) { | 4095 if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) { |
4155 » /* Make the error a little more specific. */ | 4096 /* Make the error a little more specific. */ |
4156 » PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT); | 4097 PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT); |
4157 » } | 4098 } |
4158 » goto finish; | 4099 goto finish; |
4159 } | 4100 } |
4160 | 4101 |
4161 /* | 4102 /* |
4162 * We could mark this true at the top of this function, or always | 4103 * We could mark this true at the top of this function, or always |
4163 * below at "finish", but if the problem was just that we could not | 4104 * below at "finish", but if the problem was just that we could not |
4164 * find the signer's cert, leave that as if the signature hasn't | 4105 * find the signer's cert, leave that as if the signature hasn't |
4165 * been checked in case a subsequent call might have better luck. | 4106 * been checked in case a subsequent call might have better luck. |
4166 */ | 4107 */ |
4167 signature->wasChecked = PR_TRUE; | 4108 signature->wasChecked = PR_TRUE; |
4168 | 4109 |
(...skipping 28 matching lines...) Expand all Loading... |
4197 goto finish; | 4138 goto finish; |
4198 } | 4139 } |
4199 } | 4140 } |
4200 | 4141 |
4201 rv = ocsp_VerifyResponseSignature(signerCert, signature, | 4142 rv = ocsp_VerifyResponseSignature(signerCert, signature, |
4202 tbsResponseDataDER, | 4143 tbsResponseDataDER, |
4203 pwArg); | 4144 pwArg); |
4204 | 4145 |
4205 finish: | 4146 finish: |
4206 if (signature->wasChecked) | 4147 if (signature->wasChecked) |
4207 » signature->status = rv; | 4148 signature->status = rv; |
4208 | 4149 |
4209 if (rv != SECSuccess) { | 4150 if (rv != SECSuccess) { |
4210 » signature->failureReason = PORT_GetError(); | 4151 signature->failureReason = PORT_GetError(); |
4211 » if (signerCert != NULL) | 4152 if (signerCert != NULL) |
4212 » CERT_DestroyCertificate(signerCert); | 4153 CERT_DestroyCertificate(signerCert); |
4213 } else { | 4154 } else { |
4214 » /* | 4155 /* |
4215 » * Save signer's certificate in signature. | 4156 » * Save signer's certificate in signature. |
4216 » */ | 4157 » */ |
4217 » signature->cert = signerCert; | 4158 signature->cert = signerCert; |
4218 » if (pSignerCert != NULL) { | 4159 if (pSignerCert != NULL) { |
4219 » /* | 4160 /* |
4220 » * Pass pointer to signer's certificate back to our caller, | 4161 » * Pass pointer to signer's certificate back to our caller, |
4221 » * who is also now responsible for destroying it. | 4162 » * who is also now responsible for destroying it. |
4222 » */ | 4163 » */ |
4223 » *pSignerCert = CERT_DupCertificate(signerCert); | 4164 *pSignerCert = CERT_DupCertificate(signerCert); |
4224 » } | 4165 } |
4225 } | 4166 } |
4226 | 4167 |
4227 return rv; | 4168 return rv; |
4228 } | 4169 } |
4229 | 4170 |
4230 /* | 4171 /* |
4231 * See if the request's certID and the single response's certID match. | 4172 * See if the request's certID and the single response's certID match. |
4232 * This can be easy or difficult, depending on whether the same hash | 4173 * This can be easy or difficult, depending on whether the same hash |
4233 * algorithm was used. | 4174 * algorithm was used. |
4234 */ | 4175 */ |
4235 static PRBool | 4176 static PRBool |
4236 ocsp_CertIDsMatch(CERTOCSPCertID *requestCertID, | 4177 ocsp_CertIDsMatch(CERTOCSPCertID *requestCertID, |
4237 » » CERTOCSPCertID *responseCertID) | 4178 CERTOCSPCertID *responseCertID) |
4238 { | 4179 { |
4239 PRBool match = PR_FALSE; | 4180 PRBool match = PR_FALSE; |
4240 SECOidTag hashAlg; | 4181 SECOidTag hashAlg; |
4241 SECItem *keyHash = NULL; | 4182 SECItem *keyHash = NULL; |
4242 SECItem *nameHash = NULL; | 4183 SECItem *nameHash = NULL; |
4243 | 4184 |
4244 /* | 4185 /* |
4245 * In order to match, they must have the same issuer and the same | 4186 * In order to match, they must have the same issuer and the same |
4246 * serial number. | 4187 * serial number. |
4247 * | 4188 * |
4248 * We just compare the easier things first. | 4189 * We just compare the easier things first. |
4249 */ | 4190 */ |
4250 if (SECITEM_CompareItem(&requestCertID->serialNumber, | 4191 if (SECITEM_CompareItem(&requestCertID->serialNumber, |
4251 » » » &responseCertID->serialNumber) != SECEqual) { | 4192 &responseCertID->serialNumber) != SECEqual) { |
4252 » goto done; | 4193 goto done; |
4253 } | 4194 } |
4254 | 4195 |
4255 /* | 4196 /* |
4256 * Make sure the "parameters" are not too bogus. Since we encoded | 4197 * Make sure the "parameters" are not too bogus. Since we encoded |
4257 * requestCertID->hashAlgorithm, we don't need to check it. | 4198 * requestCertID->hashAlgorithm, we don't need to check it. |
4258 */ | 4199 */ |
4259 if (responseCertID->hashAlgorithm.parameters.len > 2) { | 4200 if (responseCertID->hashAlgorithm.parameters.len > 2) { |
4260 » goto done; | 4201 goto done; |
4261 } | 4202 } |
4262 if (SECITEM_CompareItem(&requestCertID->hashAlgorithm.algorithm, | 4203 if (SECITEM_CompareItem(&requestCertID->hashAlgorithm.algorithm, |
4263 » » &responseCertID->hashAlgorithm.algorithm) == SECEqual) { | 4204 &responseCertID->hashAlgorithm.algorithm) == |
4264 » /* | 4205 SECEqual) { |
4265 » * If the hash algorithms match then we can do a simple compare | 4206 /* |
4266 » * of the hash values themselves. | 4207 » * If the hash algorithms match then we can do a simple compare |
4267 » */ | 4208 » * of the hash values themselves. |
4268 » if ((SECITEM_CompareItem(&requestCertID->issuerNameHash, | 4209 » */ |
4269 » » » » &responseCertID->issuerNameHash) == SECEqual) | 4210 if ((SECITEM_CompareItem(&requestCertID->issuerNameHash, |
4270 » && (SECITEM_CompareItem(&requestCertID->issuerKeyHash, | 4211 &responseCertID->issuerNameHash) == SECEqual) &
& |
4271 » » » » &responseCertID->issuerKeyHash) == SECEqual)) { | 4212 (SECITEM_CompareItem(&requestCertID->issuerKeyHash, |
4272 » match = PR_TRUE; | 4213 &responseCertID->issuerKeyHash) == SECEqual)) { |
4273 » } | 4214 match = PR_TRUE; |
4274 » goto done; | 4215 } |
| 4216 goto done; |
4275 } | 4217 } |
4276 | 4218 |
4277 hashAlg = SECOID_FindOIDTag(&responseCertID->hashAlgorithm.algorithm); | 4219 hashAlg = SECOID_FindOIDTag(&responseCertID->hashAlgorithm.algorithm); |
4278 switch (hashAlg) { | 4220 switch (hashAlg) { |
4279 case SEC_OID_SHA1: | 4221 case SEC_OID_SHA1: |
4280 » keyHash = &requestCertID->issuerSHA1KeyHash; | 4222 keyHash = &requestCertID->issuerSHA1KeyHash; |
4281 » nameHash = &requestCertID->issuerSHA1NameHash; | 4223 nameHash = &requestCertID->issuerSHA1NameHash; |
4282 » break; | 4224 break; |
4283 case SEC_OID_MD5: | 4225 case SEC_OID_MD5: |
4284 » keyHash = &requestCertID->issuerMD5KeyHash; | 4226 keyHash = &requestCertID->issuerMD5KeyHash; |
4285 » nameHash = &requestCertID->issuerMD5NameHash; | 4227 nameHash = &requestCertID->issuerMD5NameHash; |
4286 » break; | 4228 break; |
4287 case SEC_OID_MD2: | 4229 case SEC_OID_MD2: |
4288 » keyHash = &requestCertID->issuerMD2KeyHash; | 4230 keyHash = &requestCertID->issuerMD2KeyHash; |
4289 » nameHash = &requestCertID->issuerMD2NameHash; | 4231 nameHash = &requestCertID->issuerMD2NameHash; |
4290 » break; | 4232 break; |
4291 default: | 4233 default: |
4292 » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 4234 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
4293 » return PR_FALSE; | 4235 return PR_FALSE; |
4294 } | 4236 } |
4295 | 4237 |
4296 if ((keyHash != NULL) | 4238 if ((keyHash != NULL) && |
4297 » && (SECITEM_CompareItem(nameHash, | 4239 (SECITEM_CompareItem(nameHash, |
4298 » » » » &responseCertID->issuerNameHash) == SECEqual) | 4240 &responseCertID->issuerNameHash) == SECEqual) && |
4299 » && (SECITEM_CompareItem(keyHash, | 4241 (SECITEM_CompareItem(keyHash, |
4300 » » » » &responseCertID->issuerKeyHash) == SECEqual)) { | 4242 &responseCertID->issuerKeyHash) == SECEqual)) { |
4301 » match = PR_TRUE; | 4243 match = PR_TRUE; |
4302 } | 4244 } |
4303 | 4245 |
4304 done: | 4246 done: |
4305 return match; | 4247 return match; |
4306 } | 4248 } |
4307 | 4249 |
4308 /* | 4250 /* |
4309 * Find the single response for the cert specified by certID. | 4251 * Find the single response for the cert specified by certID. |
4310 * No copying is done; this just returns a pointer to the appropriate | 4252 * No copying is done; this just returns a pointer to the appropriate |
4311 * response within responses, if it is found (and null otherwise). | 4253 * response within responses, if it is found (and null otherwise). |
4312 * This is fine, of course, since this function is internal-use only. | 4254 * This is fine, of course, since this function is internal-use only. |
4313 */ | 4255 */ |
4314 static CERTOCSPSingleResponse * | 4256 static CERTOCSPSingleResponse * |
4315 ocsp_GetSingleResponseForCertID(CERTOCSPSingleResponse **responses, | 4257 ocsp_GetSingleResponseForCertID(CERTOCSPSingleResponse **responses, |
4316 » » » » CERTCertDBHandle *handle, | 4258 CERTCertDBHandle *handle, |
4317 » » » » CERTOCSPCertID *certID) | 4259 CERTOCSPCertID *certID) |
4318 { | 4260 { |
4319 CERTOCSPSingleResponse *single; | 4261 CERTOCSPSingleResponse *single; |
4320 int i; | 4262 int i; |
4321 | 4263 |
4322 if (responses == NULL) | 4264 if (responses == NULL) |
4323 » return NULL; | 4265 return NULL; |
4324 | 4266 |
4325 for (i = 0; responses[i] != NULL; i++) { | 4267 for (i = 0; responses[i] != NULL; i++) { |
4326 » single = responses[i]; | 4268 single = responses[i]; |
4327 » if (ocsp_CertIDsMatch(certID, single->certID)) { | 4269 if (ocsp_CertIDsMatch(certID, single->certID)) { |
4328 » return single; | 4270 return single; |
4329 » } | 4271 } |
4330 } | 4272 } |
4331 | 4273 |
4332 /* | 4274 /* |
4333 * The OCSP server should have included a response even if it knew | 4275 * The OCSP server should have included a response even if it knew |
4334 * nothing about the certificate in question. Since it did not, | 4276 * nothing about the certificate in question. Since it did not, |
4335 * this will make it look as if it had. | 4277 * this will make it look as if it had. |
4336 * | 4278 * |
4337 * XXX Should we make this a separate error to notice the server's | 4279 * XXX Should we make this a separate error to notice the server's |
4338 * bad behavior? | 4280 * bad behavior? |
4339 */ | 4281 */ |
4340 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT); | 4282 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT); |
4341 return NULL; | 4283 return NULL; |
4342 } | 4284 } |
4343 | 4285 |
4344 static ocspCheckingContext * | 4286 static ocspCheckingContext * |
4345 ocsp_GetCheckingContext(CERTCertDBHandle *handle) | 4287 ocsp_GetCheckingContext(CERTCertDBHandle *handle) |
4346 { | 4288 { |
4347 CERTStatusConfig *statusConfig; | 4289 CERTStatusConfig *statusConfig; |
4348 ocspCheckingContext *ocspcx = NULL; | 4290 ocspCheckingContext *ocspcx = NULL; |
4349 | 4291 |
4350 statusConfig = CERT_GetStatusConfig(handle); | 4292 statusConfig = CERT_GetStatusConfig(handle); |
4351 if (statusConfig != NULL) { | 4293 if (statusConfig != NULL) { |
4352 » ocspcx = statusConfig->statusContext; | 4294 ocspcx = statusConfig->statusContext; |
4353 | 4295 |
4354 » /* | 4296 /* |
4355 » * This is actually an internal error, because we should never | 4297 » * This is actually an internal error, because we should never |
4356 » * have a good statusConfig without a good statusContext, too. | 4298 » * have a good statusConfig without a good statusContext, too. |
4357 » * For lack of anything better, though, we just assert and use | 4299 » * For lack of anything better, though, we just assert and use |
4358 » * the same error as if there were no statusConfig (set below). | 4300 » * the same error as if there were no statusConfig (set below). |
4359 » */ | 4301 » */ |
4360 » PORT_Assert(ocspcx != NULL); | 4302 PORT_Assert(ocspcx != NULL); |
4361 } | 4303 } |
4362 | 4304 |
4363 if (ocspcx == NULL) | 4305 if (ocspcx == NULL) |
4364 » PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED); | 4306 PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED); |
4365 | 4307 |
4366 return ocspcx; | 4308 return ocspcx; |
4367 } | 4309 } |
4368 | 4310 |
4369 /* | 4311 /* |
4370 * Return cert reference if the given signerCert is the default responder for | 4312 * Return cert reference if the given signerCert is the default responder for |
4371 * the given certID. If not, or if any error, return NULL. | 4313 * the given certID. If not, or if any error, return NULL. |
4372 */ | 4314 */ |
4373 static CERTCertificate * | 4315 static CERTCertificate * |
4374 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle, CERTOCSPCertID *certID) | 4316 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle, CERTOCSPCertID *certID) |
4375 { | 4317 { |
4376 ocspCheckingContext *ocspcx; | 4318 ocspCheckingContext *ocspcx; |
4377 | 4319 |
4378 ocspcx = ocsp_GetCheckingContext(handle); | 4320 ocspcx = ocsp_GetCheckingContext(handle); |
4379 if (ocspcx == NULL) | 4321 if (ocspcx == NULL) |
4380 » goto loser; | 4322 goto loser; |
4381 | 4323 |
4382 /* | 4324 /* |
4383 * Right now we have only one default responder. It applies to | 4325 * Right now we have only one default responder. It applies to |
4384 * all certs when it is used, so the check is simple and certID | 4326 * all certs when it is used, so the check is simple and certID |
4385 * has no bearing on the answer. Someday in the future we may | 4327 * has no bearing on the answer. Someday in the future we may |
4386 * allow configuration of different responders for different | 4328 * allow configuration of different responders for different |
4387 * issuers, and then we would have to use the issuer specified | 4329 * issuers, and then we would have to use the issuer specified |
4388 * in certID to determine if signerCert is the right one. | 4330 * in certID to determine if signerCert is the right one. |
4389 */ | 4331 */ |
4390 if (ocspcx->useDefaultResponder) { | 4332 if (ocspcx->useDefaultResponder) { |
4391 » PORT_Assert(ocspcx->defaultResponderCert != NULL); | 4333 PORT_Assert(ocspcx->defaultResponderCert != NULL); |
4392 » return ocspcx->defaultResponderCert; | 4334 return ocspcx->defaultResponderCert; |
4393 } | 4335 } |
4394 | 4336 |
4395 loser: | 4337 loser: |
4396 return NULL; | 4338 return NULL; |
4397 } | 4339 } |
4398 | 4340 |
4399 /* | 4341 /* |
4400 * Return true if the cert is one of the default responders configured for | 4342 * Return true if the cert is one of the default responders configured for |
4401 * ocsp context. If not, or if any error, return false. | 4343 * ocsp context. If not, or if any error, return false. |
4402 */ | 4344 */ |
4403 PRBool | 4345 PRBool |
4404 ocsp_CertIsOCSPDefaultResponder(CERTCertDBHandle *handle, CERTCertificate *cert) | 4346 ocsp_CertIsOCSPDefaultResponder(CERTCertDBHandle *handle, CERTCertificate *cert) |
4405 { | 4347 { |
4406 ocspCheckingContext *ocspcx; | 4348 ocspCheckingContext *ocspcx; |
4407 | 4349 |
4408 ocspcx = ocsp_GetCheckingContext(handle); | 4350 ocspcx = ocsp_GetCheckingContext(handle); |
4409 if (ocspcx == NULL) | 4351 if (ocspcx == NULL) |
4410 » return PR_FALSE; | 4352 return PR_FALSE; |
4411 | 4353 |
4412 /* | 4354 /* |
4413 * Right now we have only one default responder. It applies to | 4355 * Right now we have only one default responder. It applies to |
4414 * all certs when it is used, so the check is simple and certID | 4356 * all certs when it is used, so the check is simple and certID |
4415 * has no bearing on the answer. Someday in the future we may | 4357 * has no bearing on the answer. Someday in the future we may |
4416 * allow configuration of different responders for different | 4358 * allow configuration of different responders for different |
4417 * issuers, and then we would have to use the issuer specified | 4359 * issuers, and then we would have to use the issuer specified |
4418 * in certID to determine if signerCert is the right one. | 4360 * in certID to determine if signerCert is the right one. |
4419 */ | 4361 */ |
4420 if (ocspcx->useDefaultResponder && | 4362 if (ocspcx->useDefaultResponder && |
4421 CERT_CompareCerts(ocspcx->defaultResponderCert, cert)) { | 4363 CERT_CompareCerts(ocspcx->defaultResponderCert, cert)) { |
4422 » return PR_TRUE; | 4364 return PR_TRUE; |
4423 } | 4365 } |
4424 | 4366 |
4425 return PR_FALSE; | 4367 return PR_FALSE; |
4426 } | 4368 } |
4427 | 4369 |
4428 /* | 4370 /* |
4429 * Check that the given signer certificate is authorized to sign status | 4371 * Check that the given signer certificate is authorized to sign status |
4430 * information for the given certID. Return true if it is, false if not | 4372 * information for the given certID. Return true if it is, false if not |
4431 * (or if there is any error along the way). If false is returned because | 4373 * (or if there is any error along the way). If false is returned because |
4432 * the signer is not authorized, the following error will be set: | 4374 * the signer is not authorized, the following error will be set: |
4433 * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE | 4375 * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE |
4434 * Other errors are low-level problems (no memory, bad database, etc.). | 4376 * Other errors are low-level problems (no memory, bad database, etc.). |
4435 * | 4377 * |
4436 * There are three ways to be authorized. In the order in which we check, | 4378 * There are three ways to be authorized. In the order in which we check, |
4437 * using the terms used in the OCSP spec, the signer must be one of: | 4379 * using the terms used in the OCSP spec, the signer must be one of: |
4438 * 1. A "trusted responder" -- it matches a local configuration | 4380 * 1. A "trusted responder" -- it matches a local configuration |
4439 * of OCSP signing authority for the certificate in question. | 4381 * of OCSP signing authority for the certificate in question. |
4440 * 2. The CA who issued the certificate in question. | 4382 * 2. The CA who issued the certificate in question. |
4441 * 3. A "CA designated responder", aka an "authorized responder" -- it | 4383 * 3. A "CA designated responder", aka an "authorized responder" -- it |
4442 * must be represented by a special cert issued by the CA who issued | 4384 * must be represented by a special cert issued by the CA who issued |
4443 * the certificate in question. | 4385 * the certificate in question. |
4444 */ | 4386 */ |
4445 static PRBool | 4387 static PRBool |
4446 ocsp_AuthorizedResponderForCertID(CERTCertDBHandle *handle, | 4388 ocsp_AuthorizedResponderForCertID(CERTCertDBHandle *handle, |
4447 » » » » CERTCertificate *signerCert, | 4389 CERTCertificate *signerCert, |
4448 » » » » CERTOCSPCertID *certID, | 4390 CERTOCSPCertID *certID, |
4449 » » » » PRTime thisUpdate) | 4391 PRTime thisUpdate) |
4450 { | 4392 { |
4451 CERTCertificate *issuerCert = NULL, *defRespCert; | 4393 CERTCertificate *issuerCert = NULL, *defRespCert; |
4452 SECItem *keyHash = NULL; | 4394 SECItem *keyHash = NULL; |
4453 SECItem *nameHash = NULL; | 4395 SECItem *nameHash = NULL; |
4454 SECOidTag hashAlg; | 4396 SECOidTag hashAlg; |
4455 PRBool keyHashEQ = PR_FALSE, nameHashEQ = PR_FALSE; | 4397 PRBool keyHashEQ = PR_FALSE, nameHashEQ = PR_FALSE; |
4456 | 4398 |
4457 /* | 4399 /* |
4458 * Check first for a trusted responder, which overrides everything else. | 4400 * Check first for a trusted responder, which overrides everything else. |
4459 */ | 4401 */ |
(...skipping 23 matching lines...) Expand all Loading... |
4483 (SECITEM_CompareItem(keyHash, | 4425 (SECITEM_CompareItem(keyHash, |
4484 &certID->issuerKeyHash) == SECEqual); | 4426 &certID->issuerKeyHash) == SECEqual); |
4485 SECITEM_FreeItem(keyHash, PR_TRUE); | 4427 SECITEM_FreeItem(keyHash, PR_TRUE); |
4486 } | 4428 } |
4487 if (keyHashEQ && | 4429 if (keyHashEQ && |
4488 (nameHash = CERT_GetSubjectNameDigest(NULL, signerCert, | 4430 (nameHash = CERT_GetSubjectNameDigest(NULL, signerCert, |
4489 hashAlg, NULL))) { | 4431 hashAlg, NULL))) { |
4490 nameHashEQ = | 4432 nameHashEQ = |
4491 (SECITEM_CompareItem(nameHash, | 4433 (SECITEM_CompareItem(nameHash, |
4492 &certID->issuerNameHash) == SECEqual); | 4434 &certID->issuerNameHash) == SECEqual); |
4493 | 4435 |
4494 SECITEM_FreeItem(nameHash, PR_TRUE); | 4436 SECITEM_FreeItem(nameHash, PR_TRUE); |
4495 if (nameHashEQ) { | 4437 if (nameHashEQ) { |
4496 /* The issuer of the cert is the the signer of the response */ | 4438 /* The issuer of the cert is the the signer of the response */ |
4497 return PR_TRUE; | 4439 return PR_TRUE; |
4498 } | 4440 } |
4499 } | 4441 } |
4500 | 4442 |
4501 | |
4502 keyHashEQ = PR_FALSE; | 4443 keyHashEQ = PR_FALSE; |
4503 nameHashEQ = PR_FALSE; | 4444 nameHashEQ = PR_FALSE; |
4504 | 4445 |
4505 if (!ocsp_CertIsOCSPDesignatedResponder(signerCert)) { | 4446 if (!ocsp_CertIsOCSPDesignatedResponder(signerCert)) { |
4506 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE); | 4447 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE); |
4507 return PR_FALSE; | 4448 return PR_FALSE; |
4508 } | 4449 } |
4509 | 4450 |
4510 /* | 4451 /* |
4511 * The signer is a designated responder. Its issuer must match | 4452 * The signer is a designated responder. Its issuer must match |
(...skipping 10 matching lines...) Expand all Loading... |
4522 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE); | 4463 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE); |
4523 return PR_FALSE; | 4464 return PR_FALSE; |
4524 } | 4465 } |
4525 | 4466 |
4526 keyHash = CERT_GetSubjectPublicKeyDigest(NULL, issuerCert, hashAlg, NULL); | 4467 keyHash = CERT_GetSubjectPublicKeyDigest(NULL, issuerCert, hashAlg, NULL); |
4527 nameHash = CERT_GetSubjectNameDigest(NULL, issuerCert, hashAlg, NULL); | 4468 nameHash = CERT_GetSubjectNameDigest(NULL, issuerCert, hashAlg, NULL); |
4528 | 4469 |
4529 CERT_DestroyCertificate(issuerCert); | 4470 CERT_DestroyCertificate(issuerCert); |
4530 | 4471 |
4531 if (keyHash != NULL && nameHash != NULL) { | 4472 if (keyHash != NULL && nameHash != NULL) { |
4532 keyHashEQ = | 4473 keyHashEQ = |
4533 (SECITEM_CompareItem(keyHash, | 4474 (SECITEM_CompareItem(keyHash, |
4534 &certID->issuerKeyHash) == SECEqual); | 4475 &certID->issuerKeyHash) == SECEqual); |
4535 | 4476 |
4536 nameHashEQ = | 4477 nameHashEQ = |
4537 (SECITEM_CompareItem(nameHash, | 4478 (SECITEM_CompareItem(nameHash, |
4538 &certID->issuerNameHash) == SECEqual); | 4479 &certID->issuerNameHash) == SECEqual); |
4539 } | 4480 } |
4540 | 4481 |
4541 if (keyHash) { | 4482 if (keyHash) { |
4542 SECITEM_FreeItem(keyHash, PR_TRUE); | 4483 SECITEM_FreeItem(keyHash, PR_TRUE); |
(...skipping 15 matching lines...) Expand all Loading... |
4558 * Since a responder can pre-package responses, we need to pick an amount | 4499 * Since a responder can pre-package responses, we need to pick an amount |
4559 * of time that is acceptable to us, and reject any response that is | 4500 * of time that is acceptable to us, and reject any response that is |
4560 * older than that. | 4501 * older than that. |
4561 * | 4502 * |
4562 * XXX This *should* be based on some configuration parameter, so that | 4503 * XXX This *should* be based on some configuration parameter, so that |
4563 * different usages could specify exactly what constitutes "sufficiently | 4504 * different usages could specify exactly what constitutes "sufficiently |
4564 * recent". But that is not going to happen right away. For now, we | 4505 * recent". But that is not going to happen right away. For now, we |
4565 * want something from within the last 24 hours. This macro defines that | 4506 * want something from within the last 24 hours. This macro defines that |
4566 * number in seconds. | 4507 * number in seconds. |
4567 */ | 4508 */ |
4568 #define OCSP_ALLOWABLE_LAPSE_SECONDS» (24L * 60L * 60L) | 4509 #define OCSP_ALLOWABLE_LAPSE_SECONDS (24L * 60L * 60L) |
4569 | 4510 |
4570 static PRBool | 4511 static PRBool |
4571 ocsp_TimeIsRecent(PRTime checkTime) | 4512 ocsp_TimeIsRecent(PRTime checkTime) |
4572 { | 4513 { |
4573 PRTime now = PR_Now(); | 4514 PRTime now = PR_Now(); |
4574 PRTime lapse, tmp; | 4515 PRTime lapse, tmp; |
4575 | 4516 |
4576 LL_I2L(lapse, OCSP_ALLOWABLE_LAPSE_SECONDS); | 4517 LL_I2L(lapse, OCSP_ALLOWABLE_LAPSE_SECONDS); |
4577 LL_I2L(tmp, PR_USEC_PER_SEC); | 4518 LL_I2L(tmp, PR_USEC_PER_SEC); |
4578 LL_MUL(lapse, lapse, tmp);» » /* allowable lapse in microseconds */ | 4519 LL_MUL(lapse, lapse, tmp); /* allowable lapse in microseconds */ |
4579 | 4520 |
4580 LL_ADD(checkTime, checkTime, lapse); | 4521 LL_ADD(checkTime, checkTime, lapse); |
4581 if (LL_CMP(now, >, checkTime)) | 4522 if (LL_CMP(now, >, checkTime)) |
4582 » return PR_FALSE; | 4523 return PR_FALSE; |
4583 | 4524 |
4584 return PR_TRUE; | 4525 return PR_TRUE; |
4585 } | 4526 } |
4586 | 4527 |
4587 #define OCSP_SLOP (5L*60L) /* OCSP responses are allowed to be 5 minutes | 4528 #define OCSP_SLOP (5L * 60L) /* OCSP responses are allowed to be 5 minutes \ |
4588 in the future by default */ | 4529 in the future by default */ |
4589 | 4530 |
4590 static PRUint32 ocspsloptime = OCSP_SLOP;» /* seconds */ | 4531 static PRUint32 ocspsloptime = OCSP_SLOP; /* seconds */ |
4591 | 4532 |
4592 /* | 4533 /* |
4593 * If an old response contains the revoked certificate status, we want | 4534 * If an old response contains the revoked certificate status, we want |
4594 * to return SECSuccess so the response will be used. | 4535 * to return SECSuccess so the response will be used. |
4595 */ | 4536 */ |
4596 static SECStatus | 4537 static SECStatus |
4597 ocsp_HandleOldSingleResponse(CERTOCSPSingleResponse *single, PRTime time) | 4538 ocsp_HandleOldSingleResponse(CERTOCSPSingleResponse *single, PRTime time) |
4598 { | 4539 { |
4599 SECStatus rv; | 4540 SECStatus rv; |
4600 ocspCertStatus *status = single->certStatus; | 4541 ocspCertStatus *status = single->certStatus; |
4601 if (status->certStatusType == ocspCertStatus_revoked) { | 4542 if (status->certStatusType == ocspCertStatus_revoked) { |
4602 rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time); | 4543 rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time); |
4603 if (rv != SECSuccess && | 4544 if (rv != SECSuccess && |
4604 PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE) { | 4545 PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE) { |
4605 /* | 4546 /* |
4606 * Return SECSuccess now. The subsequent ocsp_CertRevokedAfter | 4547 * Return SECSuccess now. The subsequent ocsp_CertRevokedAfter |
4607 * call in ocsp_CertHasGoodStatus will cause | 4548 * call in ocsp_CertHasGoodStatus will cause |
4608 * ocsp_CertHasGoodStatus to fail with | 4549 * ocsp_CertHasGoodStatus to fail with |
4609 * SEC_ERROR_REVOKED_CERTIFICATE. | 4550 * SEC_ERROR_REVOKED_CERTIFICATE. |
4610 */ | 4551 */ |
4611 return SECSuccess; | 4552 return SECSuccess; |
4612 } | 4553 } |
4613 | |
4614 } | 4554 } |
4615 PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE); | 4555 PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE); |
4616 return SECFailure; | 4556 return SECFailure; |
4617 } | 4557 } |
4618 | 4558 |
4619 /* | 4559 /* |
4620 * Check that this single response is okay. A return of SECSuccess means: | 4560 * Check that this single response is okay. A return of SECSuccess means: |
4621 * 1. The signer (represented by "signerCert") is authorized to give status | 4561 * 1. The signer (represented by "signerCert") is authorized to give status |
4622 * for the cert represented by the individual response in "single". | 4562 * for the cert represented by the individual response in "single". |
4623 * 2. The value of thisUpdate is earlier than now. | 4563 * 2. The value of thisUpdate is earlier than now. |
4624 * 3. The value of producedAt is later than or the same as thisUpdate. | 4564 * 3. The value of producedAt is later than or the same as thisUpdate. |
4625 * 4. If nextUpdate is given: | 4565 * 4. If nextUpdate is given: |
4626 * - The value of nextUpdate is later than now. | 4566 * - The value of nextUpdate is later than now. |
4627 * - The value of producedAt is earlier than nextUpdate. | 4567 * - The value of producedAt is earlier than nextUpdate. |
4628 * Else if no nextUpdate: | 4568 * Else if no nextUpdate: |
4629 * - The value of thisUpdate is fairly recent. | 4569 * - The value of thisUpdate is fairly recent. |
4630 * - The value of producedAt is fairly recent. | 4570 * - The value of producedAt is fairly recent. |
4631 * However we do not need to perform an explicit check for this last | 4571 * However we do not need to perform an explicit check for this last |
4632 * constraint because it is already guaranteed by checking that | 4572 * constraint because it is already guaranteed by checking that |
4633 * producedAt is later than thisUpdate and thisUpdate is recent. | 4573 * producedAt is later than thisUpdate and thisUpdate is recent. |
4634 * Oh, and any responder is "authorized" to say that a cert is unknown to it. | 4574 * Oh, and any responder is "authorized" to say that a cert is unknown to it. |
4635 * | 4575 * |
4636 * If any of those checks fail, SECFailure is returned and an error is set: | 4576 * If any of those checks fail, SECFailure is returned and an error is set: |
4637 * SEC_ERROR_OCSP_FUTURE_RESPONSE | 4577 * SEC_ERROR_OCSP_FUTURE_RESPONSE |
4638 * SEC_ERROR_OCSP_OLD_RESPONSE | 4578 * SEC_ERROR_OCSP_OLD_RESPONSE |
4639 * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE | 4579 * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE |
4640 * Other errors are low-level problems (no memory, bad database, etc.). | 4580 * Other errors are low-level problems (no memory, bad database, etc.). |
4641 */ | 4581 */ |
4642 static SECStatus | 4582 static SECStatus |
4643 ocsp_VerifySingleResponse(CERTOCSPSingleResponse *single, | 4583 ocsp_VerifySingleResponse(CERTOCSPSingleResponse *single, |
4644 » » » CERTCertDBHandle *handle, | 4584 CERTCertDBHandle *handle, |
4645 » » » CERTCertificate *signerCert, | 4585 CERTCertificate *signerCert, |
4646 » » » PRTime producedAt) | 4586 PRTime producedAt) |
4647 { | 4587 { |
4648 CERTOCSPCertID *certID = single->certID; | 4588 CERTOCSPCertID *certID = single->certID; |
4649 PRTime now, thisUpdate, nextUpdate, tmstamp, tmp; | 4589 PRTime now, thisUpdate, nextUpdate, tmstamp, tmp; |
4650 SECStatus rv; | 4590 SECStatus rv; |
4651 | 4591 |
4652 OCSP_TRACE(("OCSP ocsp_VerifySingleResponse, nextUpdate: %d\n", | 4592 OCSP_TRACE(("OCSP ocsp_VerifySingleResponse, nextUpdate: %d\n", |
4653 ((single->nextUpdate) != 0))); | 4593 ((single->nextUpdate) != 0))); |
4654 /* | 4594 /* |
4655 * If all the responder said was that the given cert was unknown to it, | 4595 * If all the responder said was that the given cert was unknown to it, |
4656 * that is a valid response. Not very interesting to us, of course, | 4596 * that is a valid response. Not very interesting to us, of course, |
4657 * but all this function is concerned with is validity of the response, | 4597 * but all this function is concerned with is validity of the response, |
4658 * not the status of the cert. | 4598 * not the status of the cert. |
4659 */ | 4599 */ |
4660 PORT_Assert(single->certStatus != NULL); | 4600 PORT_Assert(single->certStatus != NULL); |
4661 if (single->certStatus->certStatusType == ocspCertStatus_unknown) | 4601 if (single->certStatus->certStatusType == ocspCertStatus_unknown) |
4662 » return SECSuccess; | 4602 return SECSuccess; |
4663 | 4603 |
4664 /* | 4604 /* |
4665 * We need to extract "thisUpdate" for use below and to pass along | 4605 * We need to extract "thisUpdate" for use below and to pass along |
4666 * to AuthorizedResponderForCertID in case it needs it for doing an | 4606 * to AuthorizedResponderForCertID in case it needs it for doing an |
4667 * issuer look-up. | 4607 * issuer look-up. |
4668 */ | 4608 */ |
4669 rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate); | 4609 rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate); |
4670 if (rv != SECSuccess) | 4610 if (rv != SECSuccess) |
4671 » return rv; | 4611 return rv; |
4672 | 4612 |
4673 /* | 4613 /* |
4674 * First confirm that signerCert is authorized to give this status. | 4614 * First confirm that signerCert is authorized to give this status. |
4675 */ | 4615 */ |
4676 if (ocsp_AuthorizedResponderForCertID(handle, signerCert, certID, | 4616 if (ocsp_AuthorizedResponderForCertID(handle, signerCert, certID, |
4677 » » » » » thisUpdate) != PR_TRUE) | 4617 thisUpdate) != PR_TRUE) |
4678 » return SECFailure; | 4618 return SECFailure; |
4679 | 4619 |
4680 /* | 4620 /* |
4681 * Now check the time stuff, as described above. | 4621 * Now check the time stuff, as described above. |
4682 */ | 4622 */ |
4683 now = PR_Now(); | 4623 now = PR_Now(); |
4684 /* allow slop time for future response */ | 4624 /* allow slop time for future response */ |
4685 LL_UI2L(tmstamp, ocspsloptime); /* get slop time in seconds */ | 4625 LL_UI2L(tmstamp, ocspsloptime); /* get slop time in seconds */ |
4686 LL_UI2L(tmp, PR_USEC_PER_SEC); | 4626 LL_UI2L(tmp, PR_USEC_PER_SEC); |
4687 LL_MUL(tmp, tmstamp, tmp); /* convert the slop time to PRTime */ | 4627 LL_MUL(tmp, tmstamp, tmp); /* convert the slop time to PRTime */ |
4688 LL_ADD(tmstamp, tmp, now); /* add current time to it */ | 4628 LL_ADD(tmstamp, tmp, now); /* add current time to it */ |
4689 | 4629 |
4690 if (LL_CMP(thisUpdate, >, tmstamp) || LL_CMP(producedAt, <, thisUpdate)) { | 4630 if (LL_CMP(thisUpdate, >, tmstamp) || LL_CMP(producedAt, <, thisUpdate)) { |
4691 » PORT_SetError(SEC_ERROR_OCSP_FUTURE_RESPONSE); | 4631 PORT_SetError(SEC_ERROR_OCSP_FUTURE_RESPONSE); |
4692 » return SECFailure; | 4632 return SECFailure; |
4693 } | 4633 } |
4694 if (single->nextUpdate != NULL) { | 4634 if (single->nextUpdate != NULL) { |
4695 » rv = DER_GeneralizedTimeToTime(&nextUpdate, single->nextUpdate); | 4635 rv = DER_GeneralizedTimeToTime(&nextUpdate, single->nextUpdate); |
4696 » if (rv != SECSuccess) | 4636 if (rv != SECSuccess) |
4697 » return rv; | 4637 return rv; |
4698 | 4638 |
4699 » LL_ADD(tmp, tmp, nextUpdate); | 4639 LL_ADD(tmp, tmp, nextUpdate); |
4700 » if (LL_CMP(tmp, <, now) || LL_CMP(producedAt, >, nextUpdate)) | 4640 if (LL_CMP(tmp, <, now) || LL_CMP(producedAt, >, nextUpdate)) |
4701 » return ocsp_HandleOldSingleResponse(single, now); | 4641 return ocsp_HandleOldSingleResponse(single, now); |
4702 } else if (ocsp_TimeIsRecent(thisUpdate) != PR_TRUE) { | 4642 } else if (ocsp_TimeIsRecent(thisUpdate) != PR_TRUE) { |
4703 » return ocsp_HandleOldSingleResponse(single, now); | 4643 return ocsp_HandleOldSingleResponse(single, now); |
4704 } | 4644 } |
4705 | 4645 |
4706 return SECSuccess; | 4646 return SECSuccess; |
4707 } | 4647 } |
4708 | 4648 |
4709 | |
4710 /* | 4649 /* |
4711 * FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation | 4650 * FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation |
4712 * Get the value of the URI of the OCSP responder for the given cert. | 4651 * Get the value of the URI of the OCSP responder for the given cert. |
4713 * This is found in the (optional) Authority Information Access extension | 4652 * This is found in the (optional) Authority Information Access extension |
4714 * in the cert. | 4653 * in the cert. |
4715 * INPUTS: | 4654 * INPUTS: |
4716 * CERTCertificate *cert | 4655 * CERTCertificate *cert |
4717 * The certificate being examined. | 4656 * The certificate being examined. |
4718 * RETURN: | 4657 * RETURN: |
4719 * char * | 4658 * char * |
4720 * A copy of the URI for the OCSP method, if found. If either the | 4659 * A copy of the URI for the OCSP method, if found. If either the |
4721 * extension is not present or it does not contain an entry for OCSP, | 4660 * extension is not present or it does not contain an entry for OCSP, |
4722 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION will be set and a NULL returned. | 4661 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION will be set and a NULL returned. |
4723 * Any other error will also result in a NULL being returned. | 4662 * Any other error will also result in a NULL being returned. |
4724 * | 4663 * |
4725 * This result should be freed (via PORT_Free) when no longer in use. | 4664 * This result should be freed (via PORT_Free) when no longer in use. |
4726 */ | 4665 */ |
4727 char * | 4666 char * |
4728 CERT_GetOCSPAuthorityInfoAccessLocation(const CERTCertificate *cert) | 4667 CERT_GetOCSPAuthorityInfoAccessLocation(const CERTCertificate *cert) |
4729 { | 4668 { |
4730 CERTGeneralName *locname = NULL; | 4669 CERTGeneralName *locname = NULL; |
4731 SECItem *location = NULL; | 4670 SECItem *location = NULL; |
4732 SECItem *encodedAuthInfoAccess = NULL; | 4671 SECItem *encodedAuthInfoAccess = NULL; |
4733 CERTAuthInfoAccess **authInfoAccess = NULL; | 4672 CERTAuthInfoAccess **authInfoAccess = NULL; |
4734 char *locURI = NULL; | 4673 char *locURI = NULL; |
4735 PLArenaPool *arena = NULL; | 4674 PLArenaPool *arena = NULL; |
4736 SECStatus rv; | 4675 SECStatus rv; |
4737 int i; | 4676 int i; |
4738 | 4677 |
4739 /* | 4678 /* |
4740 * Allocate this one from the heap because it will get filled in | 4679 * Allocate this one from the heap because it will get filled in |
4741 * by CERT_FindCertExtension which will also allocate from the heap, | 4680 * by CERT_FindCertExtension which will also allocate from the heap, |
4742 * and we can free the entire thing on our way out. | 4681 * and we can free the entire thing on our way out. |
4743 */ | 4682 */ |
4744 encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0); | 4683 encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0); |
4745 if (encodedAuthInfoAccess == NULL) | 4684 if (encodedAuthInfoAccess == NULL) |
4746 » goto loser; | 4685 goto loser; |
4747 | 4686 |
4748 rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS, | 4687 rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS, |
4749 » » » » encodedAuthInfoAccess); | 4688 encodedAuthInfoAccess); |
4750 if (rv == SECFailure) { | 4689 if (rv == SECFailure) { |
4751 » PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); | 4690 PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); |
4752 » goto loser; | 4691 goto loser; |
4753 } | 4692 } |
4754 | 4693 |
4755 /* | 4694 /* |
4756 * The rest of the things allocated in the routine will come out of | 4695 * The rest of the things allocated in the routine will come out of |
4757 * this arena, which is temporary just for us to decode and get at the | 4696 * this arena, which is temporary just for us to decode and get at the |
4758 * AIA extension. The whole thing will be destroyed on our way out, | 4697 * AIA extension. The whole thing will be destroyed on our way out, |
4759 * after we have copied the location string (url) itself (if found). | 4698 * after we have copied the location string (url) itself (if found). |
4760 */ | 4699 */ |
4761 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 4700 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
4762 if (arena == NULL) | 4701 if (arena == NULL) |
4763 » goto loser; | 4702 goto loser; |
4764 | 4703 |
4765 authInfoAccess = CERT_DecodeAuthInfoAccessExtension(arena, | 4704 authInfoAccess = CERT_DecodeAuthInfoAccessExtension(arena, |
4766 » » » » » » » encodedAuthInfoAccess); | 4705 encodedAuthInfoAccess); |
4767 if (authInfoAccess == NULL) | 4706 if (authInfoAccess == NULL) |
4768 » goto loser; | 4707 goto loser; |
4769 | 4708 |
4770 for (i = 0; authInfoAccess[i] != NULL; i++) { | 4709 for (i = 0; authInfoAccess[i] != NULL; i++) { |
4771 » if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == SEC_OID_PKIX_OCSP) | 4710 if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == SEC_OID_PKIX_OCSP) |
4772 » locname = authInfoAccess[i]->location; | 4711 locname = authInfoAccess[i]->location; |
4773 } | 4712 } |
4774 | 4713 |
4775 /* | 4714 /* |
4776 * If we found an AIA extension, but it did not include an OCSP method, | 4715 * If we found an AIA extension, but it did not include an OCSP method, |
4777 * that should look to our caller as if we did not find the extension | 4716 * that should look to our caller as if we did not find the extension |
4778 * at all, because it is only an OCSP method that we care about. | 4717 * at all, because it is only an OCSP method that we care about. |
4779 * So set the same error that would be set if the AIA extension was | 4718 * So set the same error that would be set if the AIA extension was |
4780 * not there at all. | 4719 * not there at all. |
4781 */ | 4720 */ |
4782 if (locname == NULL) { | 4721 if (locname == NULL) { |
4783 » PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); | 4722 PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); |
4784 » goto loser; | 4723 goto loser; |
4785 } | 4724 } |
4786 | 4725 |
4787 /* | 4726 /* |
4788 * The following is just a pointer back into locname (i.e. not a copy); | 4727 * The following is just a pointer back into locname (i.e. not a copy); |
4789 * thus it should not be freed. | 4728 * thus it should not be freed. |
4790 */ | 4729 */ |
4791 location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE); | 4730 location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE); |
4792 if (location == NULL) { | 4731 if (location == NULL) { |
4793 » /* | 4732 /* |
4794 » * XXX Appears that CERT_GetGeneralNameByType does not set an | 4733 » * XXX Appears that CERT_GetGeneralNameByType does not set an |
4795 » * error if there is no name by that type. For lack of anything | 4734 » * error if there is no name by that type. For lack of anything |
4796 » * better, act as if the extension was not found. In the future | 4735 » * better, act as if the extension was not found. In the future |
4797 » * this should probably be something more like the extension was | 4736 » * this should probably be something more like the extension was |
4798 » * badly formed. | 4737 » * badly formed. |
4799 » */ | 4738 » */ |
4800 » PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); | 4739 PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); |
4801 » goto loser; | 4740 goto loser; |
4802 } | 4741 } |
4803 | 4742 |
4804 /* | 4743 /* |
4805 * That location is really a string, but it has a specified length | 4744 * That location is really a string, but it has a specified length |
4806 * without a null-terminator. We need a real string that does have | 4745 * without a null-terminator. We need a real string that does have |
4807 * a null-terminator, and we need a copy of it anyway to return to | 4746 * a null-terminator, and we need a copy of it anyway to return to |
4808 * our caller -- so allocate and copy. | 4747 * our caller -- so allocate and copy. |
4809 */ | 4748 */ |
4810 locURI = PORT_Alloc(location->len + 1); | 4749 locURI = PORT_Alloc(location->len + 1); |
4811 if (locURI == NULL) { | 4750 if (locURI == NULL) { |
4812 » goto loser; | 4751 goto loser; |
4813 } | 4752 } |
4814 PORT_Memcpy(locURI, location->data, location->len); | 4753 PORT_Memcpy(locURI, location->data, location->len); |
4815 locURI[location->len] = '\0'; | 4754 locURI[location->len] = '\0'; |
4816 | 4755 |
4817 loser: | 4756 loser: |
4818 if (arena != NULL) | 4757 if (arena != NULL) |
4819 » PORT_FreeArena(arena, PR_FALSE); | 4758 PORT_FreeArena(arena, PR_FALSE); |
4820 | 4759 |
4821 if (encodedAuthInfoAccess != NULL) | 4760 if (encodedAuthInfoAccess != NULL) |
4822 » SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE); | 4761 SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE); |
4823 | 4762 |
4824 return locURI; | 4763 return locURI; |
4825 } | 4764 } |
4826 | 4765 |
4827 | |
4828 /* | 4766 /* |
4829 * Figure out where we should go to find out the status of the given cert | 4767 * Figure out where we should go to find out the status of the given cert |
4830 * via OCSP. If allowed to use a default responder uri and a default | 4768 * via OCSP. If allowed to use a default responder uri and a default |
4831 * responder is set up, then that is our answer. | 4769 * responder is set up, then that is our answer. |
4832 * If not, see if the certificate has an Authority Information Access (AIA) | 4770 * If not, see if the certificate has an Authority Information Access (AIA) |
4833 * extension for OCSP, and return the value of that. Otherwise return NULL. | 4771 * extension for OCSP, and return the value of that. Otherwise return NULL. |
4834 * We also let our caller know whether or not the responder chosen was | 4772 * We also let our caller know whether or not the responder chosen was |
4835 * a default responder or not through the output variable isDefault; | 4773 * a default responder or not through the output variable isDefault; |
4836 * its value has no meaning unless a good (non-null) value is returned | 4774 * its value has no meaning unless a good (non-null) value is returned |
4837 * for the location. | 4775 * for the location. |
4838 * | 4776 * |
4839 * The result needs to be freed (PORT_Free) when no longer in use. | 4777 * The result needs to be freed (PORT_Free) when no longer in use. |
4840 */ | 4778 */ |
4841 char * | 4779 char * |
4842 ocsp_GetResponderLocation(CERTCertDBHandle *handle, CERTCertificate *cert, | 4780 ocsp_GetResponderLocation(CERTCertDBHandle *handle, CERTCertificate *cert, |
4843 » » » PRBool canUseDefault, PRBool *isDefault) | 4781 PRBool canUseDefault, PRBool *isDefault) |
4844 { | 4782 { |
4845 ocspCheckingContext *ocspcx = NULL; | 4783 ocspCheckingContext *ocspcx = NULL; |
4846 char *ocspUrl = NULL; | 4784 char *ocspUrl = NULL; |
4847 | 4785 |
4848 if (canUseDefault) { | 4786 if (canUseDefault) { |
4849 ocspcx = ocsp_GetCheckingContext(handle); | 4787 ocspcx = ocsp_GetCheckingContext(handle); |
4850 } | 4788 } |
4851 if (ocspcx != NULL && ocspcx->useDefaultResponder) { | 4789 if (ocspcx != NULL && ocspcx->useDefaultResponder) { |
4852 » /* | 4790 /* |
4853 » * A default responder wins out, if specified. | 4791 » * A default responder wins out, if specified. |
4854 » * XXX Someday this may be a more complicated determination based | 4792 » * XXX Someday this may be a more complicated determination based |
4855 » * on the cert's issuer. (That is, we could have different default | 4793 » * on the cert's issuer. (That is, we could have different default |
4856 » * responders configured for different issuers.) | 4794 » * responders configured for different issuers.) |
4857 » */ | 4795 » */ |
4858 » PORT_Assert(ocspcx->defaultResponderURI != NULL); | 4796 PORT_Assert(ocspcx->defaultResponderURI != NULL); |
4859 » *isDefault = PR_TRUE; | 4797 *isDefault = PR_TRUE; |
4860 » return (PORT_Strdup(ocspcx->defaultResponderURI)); | 4798 return (PORT_Strdup(ocspcx->defaultResponderURI)); |
4861 } | 4799 } |
4862 | 4800 |
4863 /* | 4801 /* |
4864 * No default responder set up, so go see if we can find an AIA | 4802 * No default responder set up, so go see if we can find an AIA |
4865 * extension that has a value for OCSP, and get the url from that. | 4803 * extension that has a value for OCSP, and get the url from that. |
4866 */ | 4804 */ |
4867 *isDefault = PR_FALSE; | 4805 *isDefault = PR_FALSE; |
4868 ocspUrl = CERT_GetOCSPAuthorityInfoAccessLocation(cert); | 4806 ocspUrl = CERT_GetOCSPAuthorityInfoAccessLocation(cert); |
4869 if (!ocspUrl) { | 4807 if (!ocspUrl) { |
4870 » CERT_StringFromCertFcn altFcn; | 4808 CERT_StringFromCertFcn altFcn; |
4871 | 4809 |
4872 » PR_EnterMonitor(OCSP_Global.monitor); | 4810 PR_EnterMonitor(OCSP_Global.monitor); |
4873 » altFcn = OCSP_Global.alternateOCSPAIAFcn; | 4811 altFcn = OCSP_Global.alternateOCSPAIAFcn; |
4874 » PR_ExitMonitor(OCSP_Global.monitor); | 4812 PR_ExitMonitor(OCSP_Global.monitor); |
4875 » if (altFcn) { | 4813 if (altFcn) { |
4876 » ocspUrl = (*altFcn)(cert); | 4814 ocspUrl = (*altFcn)(cert); |
4877 » if (ocspUrl) | 4815 if (ocspUrl) |
4878 » » *isDefault = PR_TRUE; | 4816 *isDefault = PR_TRUE; |
4879 » } | 4817 } |
4880 } | 4818 } |
4881 return ocspUrl; | 4819 return ocspUrl; |
4882 } | 4820 } |
4883 | 4821 |
4884 /* | 4822 /* |
4885 * Return SECSuccess if the cert was revoked *after* "time", | 4823 * Return SECSuccess if the cert was revoked *after* "time", |
4886 * SECFailure otherwise. | 4824 * SECFailure otherwise. |
4887 */ | 4825 */ |
4888 static SECStatus | 4826 static SECStatus |
4889 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time) | 4827 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time) |
4890 { | 4828 { |
4891 PRTime revokedTime; | 4829 PRTime revokedTime; |
4892 SECStatus rv; | 4830 SECStatus rv; |
4893 | 4831 |
4894 rv = DER_GeneralizedTimeToTime(&revokedTime, &revokedInfo->revocationTime); | 4832 rv = DER_GeneralizedTimeToTime(&revokedTime, &revokedInfo->revocationTime); |
4895 if (rv != SECSuccess) | 4833 if (rv != SECSuccess) |
4896 » return rv; | 4834 return rv; |
4897 | 4835 |
4898 /* | 4836 /* |
4899 * Set the error even if we will return success; someone might care. | 4837 * Set the error even if we will return success; someone might care. |
4900 */ | 4838 */ |
4901 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); | 4839 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); |
4902 | 4840 |
4903 if (LL_CMP(revokedTime, >, time)) | 4841 if (LL_CMP(revokedTime, >, time)) |
4904 » return SECSuccess; | 4842 return SECSuccess; |
4905 | 4843 |
4906 return SECFailure; | 4844 return SECFailure; |
4907 } | 4845 } |
4908 | 4846 |
4909 /* | 4847 /* |
4910 * See if the cert represented in the single response had a good status | 4848 * See if the cert represented in the single response had a good status |
4911 * at the specified time. | 4849 * at the specified time. |
4912 */ | 4850 */ |
4913 SECStatus | 4851 SECStatus |
4914 ocsp_CertHasGoodStatus(ocspCertStatus *status, PRTime time) | 4852 ocsp_CertHasGoodStatus(ocspCertStatus *status, PRTime time) |
4915 { | 4853 { |
4916 SECStatus rv; | 4854 SECStatus rv; |
4917 switch (status->certStatusType) { | 4855 switch (status->certStatusType) { |
4918 case ocspCertStatus_good: | 4856 case ocspCertStatus_good: |
4919 rv = SECSuccess; | 4857 rv = SECSuccess; |
4920 break; | 4858 break; |
4921 case ocspCertStatus_revoked: | 4859 case ocspCertStatus_revoked: |
4922 rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time); | 4860 rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time)
; |
4923 break; | 4861 break; |
4924 case ocspCertStatus_unknown: | 4862 case ocspCertStatus_unknown: |
4925 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT); | 4863 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT); |
4926 rv = SECFailure; | 4864 rv = SECFailure; |
4927 break; | 4865 break; |
4928 case ocspCertStatus_other: | 4866 case ocspCertStatus_other: |
4929 default: | 4867 default: |
4930 PORT_Assert(0); | 4868 PORT_Assert(0); |
4931 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); | 4869 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); |
4932 rv = SECFailure; | 4870 rv = SECFailure; |
4933 break; | 4871 break; |
4934 } | 4872 } |
4935 return rv; | 4873 return rv; |
4936 } | 4874 } |
4937 | 4875 |
4938 static SECStatus | 4876 static SECStatus |
4939 ocsp_SingleResponseCertHasGoodStatus(CERTOCSPSingleResponse *single, | 4877 ocsp_SingleResponseCertHasGoodStatus(CERTOCSPSingleResponse *single, |
4940 PRTime time) | 4878 PRTime time) |
4941 { | 4879 { |
4942 return ocsp_CertHasGoodStatus(single->certStatus, time); | 4880 return ocsp_CertHasGoodStatus(single->certStatus, time); |
4943 } | 4881 } |
4944 | 4882 |
4945 /* SECFailure means the arguments were invalid. | 4883 /* SECFailure means the arguments were invalid. |
4946 * On SECSuccess, the out parameters contain the OCSP status. | 4884 * On SECSuccess, the out parameters contain the OCSP status. |
4947 * rvOcsp contains the overall result of the OCSP operation. | 4885 * rvOcsp contains the overall result of the OCSP operation. |
4948 * Depending on input parameter ignoreGlobalOcspFailureSetting, | 4886 * Depending on input parameter ignoreGlobalOcspFailureSetting, |
4949 * a soft failure might be converted into *rvOcsp=SECSuccess. | 4887 * a soft failure might be converted into *rvOcsp=SECSuccess. |
4950 * If the cached attempt to obtain OCSP information had resulted | 4888 * If the cached attempt to obtain OCSP information had resulted |
4951 * in a failure, missingResponseError shows the error code of | 4889 * in a failure, missingResponseError shows the error code of |
4952 * that failure. | 4890 * that failure. |
4953 * cacheFreshness is ocspMissing if no entry was found, | 4891 * cacheFreshness is ocspMissing if no entry was found, |
4954 * ocspFresh if a fresh entry was found, or | 4892 * ocspFresh if a fresh entry was found, or |
4955 * ocspStale if a stale entry was found. | 4893 * ocspStale if a stale entry was found. |
4956 */ | 4894 */ |
4957 SECStatus | 4895 SECStatus |
4958 ocsp_GetCachedOCSPResponseStatus(CERTOCSPCertID *certID, | 4896 ocsp_GetCachedOCSPResponseStatus(CERTOCSPCertID *certID, |
4959 PRTime time, | 4897 PRTime time, |
4960 PRBool ignoreGlobalOcspFailureSetting, | 4898 PRBool ignoreGlobalOcspFailureSetting, |
4961 SECStatus *rvOcsp, | 4899 SECStatus *rvOcsp, |
4962 SECErrorCodes *missingResponseError, | 4900 SECErrorCodes *missingResponseError, |
4963 OCSPFreshness *cacheFreshness) | 4901 OCSPFreshness *cacheFreshness) |
4964 { | 4902 { |
4965 OCSPCacheItem *cacheItem = NULL; | 4903 OCSPCacheItem *cacheItem = NULL; |
4966 | 4904 |
4967 if (!certID || !missingResponseError || !rvOcsp || !cacheFreshness) { | 4905 if (!certID || !missingResponseError || !rvOcsp || !cacheFreshness) { |
4968 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 4906 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
4969 return SECFailure; | 4907 return SECFailure; |
4970 } | 4908 } |
4971 *rvOcsp = SECFailure; | 4909 *rvOcsp = SECFailure; |
4972 *missingResponseError = 0; | 4910 *missingResponseError = 0; |
4973 *cacheFreshness = ocspMissing; | 4911 *cacheFreshness = ocspMissing; |
4974 | 4912 |
4975 PR_EnterMonitor(OCSP_Global.monitor); | 4913 PR_EnterMonitor(OCSP_Global.monitor); |
4976 cacheItem = ocsp_FindCacheEntry(&OCSP_Global.cache, certID); | 4914 cacheItem = ocsp_FindCacheEntry(&OCSP_Global.cache, certID); |
4977 if (cacheItem) { | 4915 if (cacheItem) { |
4978 *cacheFreshness = ocsp_IsCacheItemFresh(cacheItem) ? ocspFresh | 4916 *cacheFreshness = ocsp_IsCacheItemFresh(cacheItem) ? ocspFresh |
4979 : ocspStale; | 4917 : ocspStale; |
4980 /* having an arena means, we have a cached certStatus */ | 4918 /* having an arena means, we have a cached certStatus */ |
4981 if (cacheItem->certStatusArena) { | 4919 if (cacheItem->certStatusArena) { |
4982 *rvOcsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time); | 4920 *rvOcsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time); |
4983 if (*rvOcsp != SECSuccess) { | 4921 if (*rvOcsp != SECSuccess) { |
4984 *missingResponseError = PORT_GetError(); | 4922 *missingResponseError = PORT_GetError(); |
4985 } | 4923 } |
4986 } else { | 4924 } else { |
4987 /* | 4925 /* |
4988 * No status cached, the previous attempt failed. | 4926 * No status cached, the previous attempt failed. |
4989 * If OCSP is required, we never decide based on a failed attempt | 4927 * If OCSP is required, we never decide based on a failed attempt |
4990 * However, if OCSP is optional, a recent OCSP failure is | 4928 * However, if OCSP is optional, a recent OCSP failure is |
4991 * an allowed good state. | 4929 * an allowed good state. |
4992 */ | 4930 */ |
4993 if (*cacheFreshness == ocspFresh && | 4931 if (*cacheFreshness == ocspFresh && |
4994 !ignoreGlobalOcspFailureSetting && | 4932 !ignoreGlobalOcspFailureSetting && |
4995 OCSP_Global.ocspFailureMode == | 4933 OCSP_Global.ocspFailureMode == |
4996 ocspMode_FailureIsNotAVerificationFailure) { | 4934 ocspMode_FailureIsNotAVerificationFailure) { |
4997 *rvOcsp = SECSuccess; | 4935 *rvOcsp = SECSuccess; |
4998 } | 4936 } |
4999 *missingResponseError = cacheItem->missingResponseError; | 4937 *missingResponseError = cacheItem->missingResponseError; |
5000 } | 4938 } |
5001 } | 4939 } |
5002 PR_ExitMonitor(OCSP_Global.monitor); | 4940 PR_ExitMonitor(OCSP_Global.monitor); |
5003 return SECSuccess; | 4941 return SECSuccess; |
5004 } | 4942 } |
5005 | 4943 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5057 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION | 4995 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION |
5058 * SEC_ERROR_INVALID_TIME | 4996 * SEC_ERROR_INVALID_TIME |
5059 * SEC_ERROR_REVOKED_CERTIFICATE | 4997 * SEC_ERROR_REVOKED_CERTIFICATE |
5060 * SEC_ERROR_UNKNOWN_ISSUER | 4998 * SEC_ERROR_UNKNOWN_ISSUER |
5061 * SEC_ERROR_UNKNOWN_SIGNER | 4999 * SEC_ERROR_UNKNOWN_SIGNER |
5062 * | 5000 * |
5063 * Other errors are any of the many possible failures in cert verification | 5001 * Other errors are any of the many possible failures in cert verification |
5064 * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when | 5002 * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when |
5065 * verifying the signer's cert, or low-level problems (error allocating | 5003 * verifying the signer's cert, or low-level problems (error allocating |
5066 * memory, error performing ASN.1 decoding, etc.). | 5004 * memory, error performing ASN.1 decoding, etc.). |
5067 */ | 5005 */ |
5068 SECStatus | 5006 SECStatus |
5069 CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, | 5007 CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, |
5070 » » PRTime time, void *pwArg) | 5008 PRTime time, void *pwArg) |
5071 { | 5009 { |
5072 CERTOCSPCertID *certID; | 5010 CERTOCSPCertID *certID; |
5073 PRBool certIDWasConsumed = PR_FALSE; | 5011 PRBool certIDWasConsumed = PR_FALSE; |
5074 SECStatus rv; | 5012 SECStatus rv; |
5075 SECStatus rvOcsp; | 5013 SECStatus rvOcsp; |
5076 SECErrorCodes cachedErrorCode; | 5014 SECErrorCodes cachedErrorCode; |
5077 OCSPFreshness cachedResponseFreshness; | 5015 OCSPFreshness cachedResponseFreshness; |
5078 | 5016 |
5079 OCSP_TRACE_CERT(cert); | 5017 OCSP_TRACE_CERT(cert); |
5080 OCSP_TRACE_TIME("## requested validity time:", time); | 5018 OCSP_TRACE_TIME("## requested validity time:", time); |
5081 | 5019 |
5082 certID = CERT_CreateOCSPCertID(cert, time); | 5020 certID = CERT_CreateOCSPCertID(cert, time); |
5083 if (!certID) | 5021 if (!certID) |
5084 return SECFailure; | 5022 return SECFailure; |
5085 rv = ocsp_GetCachedOCSPResponseStatus( | 5023 rv = ocsp_GetCachedOCSPResponseStatus( |
5086 certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */ | 5024 certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */ |
5087 &rvOcsp, &cachedErrorCode, &cachedResponseFreshness); | 5025 &rvOcsp, &cachedErrorCode, &cachedResponseFreshness); |
5088 if (rv != SECSuccess) { | 5026 if (rv != SECSuccess) { |
5089 CERT_DestroyOCSPCertID(certID); | 5027 CERT_DestroyOCSPCertID(certID); |
5090 return SECFailure; | 5028 return SECFailure; |
5091 } | 5029 } |
5092 if (cachedResponseFreshness == ocspFresh) { | 5030 if (cachedResponseFreshness == ocspFresh) { |
5093 CERT_DestroyOCSPCertID(certID); | 5031 CERT_DestroyOCSPCertID(certID); |
5094 if (rvOcsp != SECSuccess) { | 5032 if (rvOcsp != SECSuccess) { |
5095 PORT_SetError(cachedErrorCode); | 5033 PORT_SetError(cachedErrorCode); |
5096 } | 5034 } |
5097 return rvOcsp; | 5035 return rvOcsp; |
5098 } | 5036 } |
5099 | 5037 |
5100 rv = ocsp_GetOCSPStatusFromNetwork(handle, certID, cert, time, pwArg, | 5038 rv = ocsp_GetOCSPStatusFromNetwork(handle, certID, cert, time, pwArg, |
5101 &certIDWasConsumed, | 5039 &certIDWasConsumed, |
5102 &rvOcsp); | 5040 &rvOcsp); |
5103 if (rv != SECSuccess) { | 5041 if (rv != SECSuccess) { |
5104 PRErrorCode err = PORT_GetError(); | 5042 PRErrorCode err = PORT_GetError(); |
5105 if (ocsp_FetchingFailureIsVerificationFailure()) { | 5043 if (ocsp_FetchingFailureIsVerificationFailure()) { |
5106 PORT_SetError(err); | 5044 PORT_SetError(err); |
5107 rvOcsp = SECFailure; | 5045 rvOcsp = SECFailure; |
5108 } else if (cachedResponseFreshness == ocspStale && | 5046 } else if (cachedResponseFreshness == ocspStale && |
5109 (cachedErrorCode == SEC_ERROR_OCSP_UNKNOWN_CERT || | 5047 (cachedErrorCode == SEC_ERROR_OCSP_UNKNOWN_CERT || |
5110 cachedErrorCode == SEC_ERROR_REVOKED_CERTIFICATE)) { | 5048 cachedErrorCode == SEC_ERROR_REVOKED_CERTIFICATE)) { |
5111 /* If we couldn't get a response for a certificate that the OCSP | 5049 /* If we couldn't get a response for a certificate that the OCSP |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5150 * SECItem *encodedResponse | 5088 * SECItem *encodedResponse |
5151 * the DER encoded bytes of the OCSP response | 5089 * the DER encoded bytes of the OCSP response |
5152 * void *pwArg | 5090 * void *pwArg |
5153 * argument for password prompting, if needed | 5091 * argument for password prompting, if needed |
5154 * RETURN: | 5092 * RETURN: |
5155 * SECSuccess if the cert was found in the cache, or if the OCSP response was | 5093 * SECSuccess if the cert was found in the cache, or if the OCSP response was |
5156 * found to be valid and inserted into the cache. SECFailure otherwise. | 5094 * found to be valid and inserted into the cache. SECFailure otherwise. |
5157 */ | 5095 */ |
5158 SECStatus | 5096 SECStatus |
5159 CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle, | 5097 CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle, |
5160 » » » » CERTCertificate *cert, | 5098 CERTCertificate *cert, |
5161 » » » » PRTime time, | 5099 PRTime time, |
5162 » » » » const SECItem *encodedResponse, | 5100 const SECItem *encodedResponse, |
5163 » » » » void *pwArg) | 5101 void *pwArg) |
5164 { | 5102 { |
5165 CERTOCSPCertID *certID = NULL; | 5103 CERTOCSPCertID *certID = NULL; |
5166 PRBool certIDWasConsumed = PR_FALSE; | 5104 PRBool certIDWasConsumed = PR_FALSE; |
5167 SECStatus rv = SECFailure; | 5105 SECStatus rv = SECFailure; |
5168 SECStatus rvOcsp = SECFailure; | 5106 SECStatus rvOcsp = SECFailure; |
5169 SECErrorCodes dummy_error_code; /* we ignore this */ | 5107 SECErrorCodes dummy_error_code; /* we ignore this */ |
5170 CERTOCSPResponse *decodedResponse = NULL; | 5108 CERTOCSPResponse *decodedResponse = NULL; |
5171 CERTOCSPSingleResponse *singleResponse = NULL; | 5109 CERTOCSPSingleResponse *singleResponse = NULL; |
5172 OCSPFreshness freshness; | 5110 OCSPFreshness freshness; |
5173 | 5111 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5228 /* The cached value is good. We don't want to waste time validating | 5166 /* The cached value is good. We don't want to waste time validating |
5229 * this OCSP response. This is the first column in the table above. */ | 5167 * this OCSP response. This is the first column in the table above. */ |
5230 CERT_DestroyOCSPCertID(certID); | 5168 CERT_DestroyOCSPCertID(certID); |
5231 return rv; | 5169 return rv; |
5232 } | 5170 } |
5233 | 5171 |
5234 /* The logic for caching the more recent response is handled in | 5172 /* The logic for caching the more recent response is handled in |
5235 * ocsp_CacheSingleResponse. */ | 5173 * ocsp_CacheSingleResponse. */ |
5236 | 5174 |
5237 rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert, | 5175 rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert, |
5238 » » » » » » time, pwArg, | 5176 time, pwArg, |
5239 » » » » » » encodedResponse, | 5177 encodedResponse, |
5240 » » » » » » &decodedResponse, | 5178 &decodedResponse, |
5241 » » » » » » &singleResponse); | 5179 &singleResponse); |
5242 if (rv == SECSuccess) { | 5180 if (rv == SECSuccess) { |
5243 » rvOcsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse, time); | 5181 rvOcsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse, time); |
5244 » /* Cache any valid singleResponse, regardless of status. */ | 5182 /* Cache any valid singleResponse, regardless of status. */ |
5245 » ocsp_CacheSingleResponse(certID, singleResponse, &certIDWasConsumed); | 5183 ocsp_CacheSingleResponse(certID, singleResponse, &certIDWasConsumed); |
5246 } | 5184 } |
5247 if (decodedResponse) { | 5185 if (decodedResponse) { |
5248 » CERT_DestroyOCSPResponse(decodedResponse); | 5186 CERT_DestroyOCSPResponse(decodedResponse); |
5249 } | 5187 } |
5250 if (!certIDWasConsumed) { | 5188 if (!certIDWasConsumed) { |
5251 CERT_DestroyOCSPCertID(certID); | 5189 CERT_DestroyOCSPCertID(certID); |
5252 } | 5190 } |
5253 return rv == SECSuccess ? rvOcsp : rv; | 5191 return rv == SECSuccess ? rvOcsp : rv; |
5254 } | 5192 } |
5255 | 5193 |
5256 /* | 5194 /* |
5257 * Status in *certIDWasConsumed will always be correct, regardless of | 5195 * Status in *certIDWasConsumed will always be correct, regardless of |
5258 * return value. | 5196 * return value. |
5259 */ | 5197 */ |
5260 static SECStatus | 5198 static SECStatus |
5261 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, | 5199 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, |
5262 CERTOCSPCertID *certID, | 5200 CERTOCSPCertID *certID, |
5263 CERTCertificate *cert, | 5201 CERTCertificate *cert, |
5264 PRTime time, | 5202 PRTime time, |
5265 void *pwArg, | 5203 void *pwArg, |
5266 PRBool *certIDWasConsumed, | 5204 PRBool *certIDWasConsumed, |
5267 SECStatus *rv_ocsp) | 5205 SECStatus *rv_ocsp) |
5268 { | 5206 { |
5269 char *location = NULL; | 5207 char *location = NULL; |
5270 PRBool locationIsDefault; | 5208 PRBool locationIsDefault; |
5271 SECItem *encodedResponse = NULL; | 5209 SECItem *encodedResponse = NULL; |
5272 CERTOCSPRequest *request = NULL; | 5210 CERTOCSPRequest *request = NULL; |
5273 SECStatus rv = SECFailure; | 5211 SECStatus rv = SECFailure; |
5274 | 5212 |
5275 CERTOCSPResponse *decodedResponse = NULL; | 5213 CERTOCSPResponse *decodedResponse = NULL; |
5276 CERTOCSPSingleResponse *singleResponse = NULL; | 5214 CERTOCSPSingleResponse *singleResponse = NULL; |
5277 enum { stageGET, stagePOST } currentStage; | 5215 enum { stageGET, |
| 5216 stagePOST } currentStage; |
5278 PRBool retry = PR_FALSE; | 5217 PRBool retry = PR_FALSE; |
5279 | 5218 |
5280 if (!certIDWasConsumed || !rv_ocsp) { | 5219 if (!certIDWasConsumed || !rv_ocsp) { |
5281 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 5220 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
5282 return SECFailure; | 5221 return SECFailure; |
5283 } | 5222 } |
5284 *certIDWasConsumed = PR_FALSE; | 5223 *certIDWasConsumed = PR_FALSE; |
5285 *rv_ocsp = SECFailure; | 5224 *rv_ocsp = SECFailure; |
5286 | 5225 |
5287 if (!OCSP_Global.monitor) { | 5226 if (!OCSP_Global.monitor) { |
(...skipping 15 matching lines...) Expand all Loading... |
5303 * If we have no such location, then this cert does not "deserve" to | 5242 * If we have no such location, then this cert does not "deserve" to |
5304 * be checked -- that is, we consider it a success and just return. | 5243 * be checked -- that is, we consider it a success and just return. |
5305 * The way we tell that is by looking at the error number to see if | 5244 * The way we tell that is by looking at the error number to see if |
5306 * the problem was no AIA extension was found; any other error was | 5245 * the problem was no AIA extension was found; any other error was |
5307 * a true failure that we unfortunately have to treat as an overall | 5246 * a true failure that we unfortunately have to treat as an overall |
5308 * failure here. | 5247 * failure here. |
5309 */ | 5248 */ |
5310 location = ocsp_GetResponderLocation(handle, cert, PR_TRUE, | 5249 location = ocsp_GetResponderLocation(handle, cert, PR_TRUE, |
5311 &locationIsDefault); | 5250 &locationIsDefault); |
5312 if (location == NULL) { | 5251 if (location == NULL) { |
5313 int err = PORT_GetError(); | 5252 int err = PORT_GetError(); |
5314 if (err == SEC_ERROR_EXTENSION_NOT_FOUND || | 5253 if (err == SEC_ERROR_EXTENSION_NOT_FOUND || |
5315 err == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) { | 5254 err == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) { |
5316 PORT_SetError(0); | 5255 PORT_SetError(0); |
5317 *rv_ocsp = SECSuccess; | 5256 *rv_ocsp = SECSuccess; |
5318 return SECSuccess; | 5257 return SECSuccess; |
5319 } | 5258 } |
5320 return SECFailure; | 5259 return SECFailure; |
5321 } | 5260 } |
5322 | 5261 |
5323 /* | 5262 /* |
5324 * XXX In the fullness of time, we will want/need to handle a | 5263 * XXX In the fullness of time, we will want/need to handle a |
5325 * certificate chain. This will be done either when a new parameter | 5264 * certificate chain. This will be done either when a new parameter |
5326 * tells us to, or some configuration variable tells us to. In any | 5265 * tells us to, or some configuration variable tells us to. In any |
5327 * case, handling it is complicated because we may need to send as | 5266 * case, handling it is complicated because we may need to send as |
5328 * many requests (and receive as many responses) as we have certs | 5267 * many requests (and receive as many responses) as we have certs |
5329 * in the chain. If we are going to talk to a default responder, | 5268 * in the chain. If we are going to talk to a default responder, |
5330 * and we only support one default responder, we can put all of the | 5269 * and we only support one default responder, we can put all of the |
5331 * certs together into one request. Otherwise, we must break them up | 5270 * certs together into one request. Otherwise, we must break them up |
5332 * into multiple requests. (Even if all of the requests will go to | 5271 * into multiple requests. (Even if all of the requests will go to |
5333 * the same location, the signature on each response will be different, | 5272 * the same location, the signature on each response will be different, |
5334 * because each issuer is different. Carefully read the OCSP spec | 5273 * because each issuer is different. Carefully read the OCSP spec |
5335 * if you do not understand this.) | 5274 * if you do not understand this.) |
5336 */ | 5275 */ |
5337 | 5276 |
5338 /* | 5277 /* |
5339 * XXX If/when signing of requests is supported, that second NULL | 5278 * XXX If/when signing of requests is supported, that second NULL |
5340 * should be changed to be the signer certificate. Not sure if that | 5279 * should be changed to be the signer certificate. Not sure if that |
5341 * should be passed into this function or retrieved via some operation | 5280 * should be passed into this function or retrieved via some operation |
5342 * on the handle/context. | 5281 * on the handle/context. |
5343 */ | 5282 */ |
5344 | 5283 |
5345 do { | 5284 do { |
5346 » const char *method; | 5285 const char *method; |
5347 » PRBool validResponseWithAccurateInfo = PR_FALSE; | 5286 PRBool validResponseWithAccurateInfo = PR_FALSE; |
5348 » retry = PR_FALSE; | 5287 retry = PR_FALSE; |
5349 » *rv_ocsp = SECFailure; | 5288 *rv_ocsp = SECFailure; |
5350 | 5289 |
5351 » if (currentStage == stageGET) { | 5290 if (currentStage == stageGET) { |
5352 » method = "GET"; | 5291 method = "GET"; |
5353 » } else { | 5292 } else { |
5354 » PORT_Assert(currentStage == stagePOST); | 5293 PORT_Assert(currentStage == stagePOST); |
5355 » method = "POST"; | 5294 method = "POST"; |
5356 » } | 5295 } |
5357 | 5296 |
5358 » encodedResponse = | 5297 encodedResponse = |
5359 » ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert, | 5298 ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert, |
5360 » » » » » » location, method, | 5299 location, method, |
5361 » » » » » » time, locationIsDefault, | 5300 time, locationIsDefault, |
5362 » » » » » » pwArg, &request); | 5301 pwArg, &request); |
5363 | 5302 |
5364 » if (encodedResponse) { | 5303 if (encodedResponse) { |
5365 » rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert
, | 5304 rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert
, |
5366 » » » » » » » time, pwArg, | 5305 time, pwArg, |
5367 » » » » » » » encodedResponse, | 5306 encodedResponse, |
5368 » » » » » » » &decodedResponse, | 5307 &decodedResponse, |
5369 » » » » » » » &singleResponse); | 5308 &singleResponse); |
5370 » if (rv == SECSuccess) { | 5309 if (rv == SECSuccess) { |
5371 » » switch (singleResponse->certStatus->certStatusType) { | 5310 switch (singleResponse->certStatus->certStatusType) { |
5372 » » case ocspCertStatus_good: | 5311 case ocspCertStatus_good: |
5373 » » case ocspCertStatus_revoked: | 5312 case ocspCertStatus_revoked: |
5374 » » » validResponseWithAccurateInfo = PR_TRUE; | 5313 validResponseWithAccurateInfo = PR_TRUE; |
5375 » » » break; | 5314 break; |
5376 » » default: | 5315 default: |
5377 » » » break; | 5316 break; |
5378 » » } | 5317 } |
5379 » » *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse,
time); | 5318 *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse,
time); |
5380 » } | 5319 } |
5381 » } | 5320 } |
5382 | 5321 |
5383 » if (currentStage == stageGET) { | 5322 if (currentStage == stageGET) { |
5384 » /* only accept GET response if good or revoked */ | 5323 /* only accept GET response if good or revoked */ |
5385 » if (validResponseWithAccurateInfo) { | 5324 if (validResponseWithAccurateInfo) { |
5386 » » ocsp_CacheSingleResponse(certID, singleResponse, | 5325 ocsp_CacheSingleResponse(certID, singleResponse, |
5387 » » » » » certIDWasConsumed); | 5326 certIDWasConsumed); |
5388 » } else { | 5327 } else { |
5389 » » retry = PR_TRUE; | 5328 retry = PR_TRUE; |
5390 » » currentStage = stagePOST; | 5329 currentStage = stagePOST; |
5391 » } | 5330 } |
5392 » } else { | 5331 } else { |
5393 » /* cache the POST respone, regardless of status */ | 5332 /* cache the POST respone, regardless of status */ |
5394 » if (!singleResponse) { | 5333 if (!singleResponse) { |
5395 » » cert_RememberOCSPProcessingFailure(certID, certIDWasConsumed); | 5334 cert_RememberOCSPProcessingFailure(certID, certIDWasConsumed); |
5396 » } else { | 5335 } else { |
5397 » » ocsp_CacheSingleResponse(certID, singleResponse, | 5336 ocsp_CacheSingleResponse(certID, singleResponse, |
5398 » » » » » certIDWasConsumed); | 5337 certIDWasConsumed); |
5399 » } | 5338 } |
5400 » } | 5339 } |
5401 | 5340 |
5402 » if (encodedResponse) { | 5341 if (encodedResponse) { |
5403 » SECITEM_FreeItem(encodedResponse, PR_TRUE); | 5342 SECITEM_FreeItem(encodedResponse, PR_TRUE); |
5404 » encodedResponse = NULL; | 5343 encodedResponse = NULL; |
5405 » } | 5344 } |
5406 » if (request) { | 5345 if (request) { |
5407 » CERT_DestroyOCSPRequest(request); | 5346 CERT_DestroyOCSPRequest(request); |
5408 » request = NULL; | 5347 request = NULL; |
5409 » } | 5348 } |
5410 » if (decodedResponse) { | 5349 if (decodedResponse) { |
5411 » CERT_DestroyOCSPResponse(decodedResponse); | 5350 CERT_DestroyOCSPResponse(decodedResponse); |
5412 » decodedResponse = NULL; | 5351 decodedResponse = NULL; |
5413 » } | 5352 } |
5414 » singleResponse = NULL; | 5353 singleResponse = NULL; |
5415 | 5354 |
5416 } while (retry); | 5355 } while (retry); |
5417 | 5356 |
5418 PORT_Free(location); | 5357 PORT_Free(location); |
5419 return rv; | 5358 return rv; |
5420 } | 5359 } |
5421 | 5360 |
5422 /* | 5361 /* |
5423 * FUNCTION: ocsp_GetDecodedVerifiedSingleResponseForID | 5362 * FUNCTION: ocsp_GetDecodedVerifiedSingleResponseForID |
5424 * This function decodes an OCSP response and checks for a valid response | 5363 * This function decodes an OCSP response and checks for a valid response |
(...skipping 22 matching lines...) Expand all Loading... |
5447 * and if it's non-null, must destroy it using CERT_DestroyOCSPResponse. | 5386 * and if it's non-null, must destroy it using CERT_DestroyOCSPResponse. |
5448 * CERTOCSPSingleResponse **pSingle | 5387 * CERTOCSPSingleResponse **pSingle |
5449 * (output) on success, this points to the single response that corresponds | 5388 * (output) on success, this points to the single response that corresponds |
5450 * to the certID parameter. Points to the inside of pDecodedResponse. | 5389 * to the certID parameter. Points to the inside of pDecodedResponse. |
5451 * It isn't a copy, don't free it. | 5390 * It isn't a copy, don't free it. |
5452 * RETURN: | 5391 * RETURN: |
5453 * SECSuccess iff the response is valid. | 5392 * SECSuccess iff the response is valid. |
5454 */ | 5393 */ |
5455 static SECStatus | 5394 static SECStatus |
5456 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle, | 5395 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle, |
5457 » » » » » CERTOCSPCertID *certID, | 5396 CERTOCSPCertID *certID, |
5458 » » » » » CERTCertificate *cert, | 5397 CERTCertificate *cert, |
5459 » » » » » PRTime time, | 5398 PRTime time, |
5460 » » » » » void *pwArg, | 5399 void *pwArg, |
5461 » » » » » const SECItem *encodedResponse, | 5400 const SECItem *encodedResponse, |
5462 » » » » » CERTOCSPResponse **pDecodedResponse, | 5401 CERTOCSPResponse **pDecodedResponse, |
5463 » » » » » CERTOCSPSingleResponse **pSingle) | 5402 CERTOCSPSingleResponse **pSingle) |
5464 { | 5403 { |
5465 CERTCertificate *signerCert = NULL; | 5404 CERTCertificate *signerCert = NULL; |
5466 CERTCertificate *issuerCert = NULL; | 5405 CERTCertificate *issuerCert = NULL; |
5467 SECStatus rv = SECFailure; | 5406 SECStatus rv = SECFailure; |
5468 | 5407 |
5469 if (!pSingle || !pDecodedResponse) { | 5408 if (!pSingle || !pDecodedResponse) { |
5470 » return SECFailure; | 5409 return SECFailure; |
5471 } | 5410 } |
5472 *pSingle = NULL; | 5411 *pSingle = NULL; |
5473 *pDecodedResponse = CERT_DecodeOCSPResponse(encodedResponse); | 5412 *pDecodedResponse = CERT_DecodeOCSPResponse(encodedResponse); |
5474 if (!*pDecodedResponse) { | 5413 if (!*pDecodedResponse) { |
5475 » return SECFailure; | 5414 return SECFailure; |
5476 } | 5415 } |
5477 | 5416 |
5478 /* | 5417 /* |
5479 * Okay, we at least have a response that *looks* like a response! | 5418 * Okay, we at least have a response that *looks* like a response! |
5480 * Now see if the overall response status value is good or not. | 5419 * Now see if the overall response status value is good or not. |
5481 * If not, we set an error and give up. (It means that either the | 5420 * If not, we set an error and give up. (It means that either the |
5482 * server had a problem, or it didn't like something about our | 5421 * server had a problem, or it didn't like something about our |
5483 * request. Either way there is nothing to do but give up.) | 5422 * request. Either way there is nothing to do but give up.) |
5484 * Otherwise, we continue to find the actual per-cert status | 5423 * Otherwise, we continue to find the actual per-cert status |
5485 * in the response. | 5424 * in the response. |
5486 */ | 5425 */ |
5487 if (CERT_GetOCSPResponseStatus(*pDecodedResponse) != SECSuccess) { | 5426 if (CERT_GetOCSPResponseStatus(*pDecodedResponse) != SECSuccess) { |
5488 » goto loser; | 5427 goto loser; |
5489 } | 5428 } |
5490 | 5429 |
5491 /* | 5430 /* |
5492 * If we've made it this far, we expect a response with a good signature. | 5431 * If we've made it this far, we expect a response with a good signature. |
5493 * So, check for that. | 5432 * So, check for that. |
5494 */ | 5433 */ |
5495 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); | 5434 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); |
5496 rv = CERT_VerifyOCSPResponseSignature(*pDecodedResponse, handle, pwArg, | 5435 rv = CERT_VerifyOCSPResponseSignature(*pDecodedResponse, handle, pwArg, |
5497 &signerCert, issuerCert); | 5436 &signerCert, issuerCert); |
5498 if (rv != SECSuccess) { | 5437 if (rv != SECSuccess) { |
5499 » goto loser; | 5438 goto loser; |
5500 } | 5439 } |
5501 | 5440 |
5502 PORT_Assert(signerCert != NULL);» /* internal consistency check */ | 5441 PORT_Assert(signerCert != NULL); /* internal consistency check */ |
5503 /* XXX probably should set error, return failure if signerCert is null */ | 5442 /* XXX probably should set error, return failure if signerCert is null */ |
5504 | 5443 |
5505 /* | 5444 /* |
5506 * Again, we are only doing one request for one cert. | 5445 * Again, we are only doing one request for one cert. |
5507 * XXX When we handle cert chains, the following code will obviously | 5446 * XXX When we handle cert chains, the following code will obviously |
5508 * have to be modified, in coordation with the code above that will | 5447 * have to be modified, in coordation with the code above that will |
5509 * have to determine how to make multiple requests, etc. | 5448 * have to determine how to make multiple requests, etc. |
5510 */ | 5449 */ |
5511 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, *pDecodedResponse, cert
ID, | 5450 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, *pDecodedResponse, cert
ID, |
5512 signerCert, time, pSingle); | 5451 signerCert, time, pSingle); |
5513 loser: | 5452 loser: |
5514 if (issuerCert != NULL) | 5453 if (issuerCert != NULL) |
5515 » CERT_DestroyCertificate(issuerCert); | 5454 CERT_DestroyCertificate(issuerCert); |
5516 if (signerCert != NULL) | 5455 if (signerCert != NULL) |
5517 » CERT_DestroyCertificate(signerCert); | 5456 CERT_DestroyCertificate(signerCert); |
5518 return rv; | 5457 return rv; |
5519 } | 5458 } |
5520 | 5459 |
5521 /* | 5460 /* |
5522 * FUNCTION: ocsp_CacheSingleResponse | 5461 * FUNCTION: ocsp_CacheSingleResponse |
5523 * This function requires that the caller has checked that the response | 5462 * This function requires that the caller has checked that the response |
5524 * is valid and verified. | 5463 * is valid and verified. |
5525 * The (positive or negative) valid response will be used to update the cache. | 5464 * The (positive or negative) valid response will be used to update the cache. |
5526 * INPUTS: | 5465 * INPUTS: |
5527 * CERTOCSPCertID *certID | 5466 * CERTOCSPCertID *certID |
5528 * the cert ID corresponding to |cert| | 5467 * the cert ID corresponding to |cert| |
5529 * PRBool *certIDWasConsumed | 5468 * PRBool *certIDWasConsumed |
5530 * (output) on return, this is true iff |certID| was consumed by this | 5469 * (output) on return, this is true iff |certID| was consumed by this |
5531 * function. | 5470 * function. |
5532 */ | 5471 */ |
5533 void | 5472 void |
5534 ocsp_CacheSingleResponse(CERTOCSPCertID *certID, | 5473 ocsp_CacheSingleResponse(CERTOCSPCertID *certID, |
5535 » » » CERTOCSPSingleResponse *single, | 5474 CERTOCSPSingleResponse *single, |
5536 » » » PRBool *certIDWasConsumed) | 5475 PRBool *certIDWasConsumed) |
5537 { | 5476 { |
5538 if (single != NULL) { | 5477 if (single != NULL) { |
5539 » PR_EnterMonitor(OCSP_Global.monitor); | 5478 PR_EnterMonitor(OCSP_Global.monitor); |
5540 » if (OCSP_Global.maxCacheEntries >= 0) { | 5479 if (OCSP_Global.maxCacheEntries >= 0) { |
5541 » ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, | 5480 ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, |
5542 » » » » » certIDWasConsumed); | 5481 certIDWasConsumed); |
5543 » /* ignore cache update failures */ | 5482 /* ignore cache update failures */ |
5544 » } | 5483 } |
5545 » PR_ExitMonitor(OCSP_Global.monitor); | 5484 PR_ExitMonitor(OCSP_Global.monitor); |
5546 } | 5485 } |
5547 } | 5486 } |
5548 | 5487 |
5549 SECStatus | 5488 SECStatus |
5550 ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle, | 5489 ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle, |
5551 CERTOCSPResponse *response, | 5490 CERTOCSPResponse *response, |
5552 CERTOCSPCertID *certID, | 5491 CERTOCSPCertID *certID, |
5553 CERTCertificate *signerCert, | 5492 CERTCertificate *signerCert, |
5554 PRTime time, | 5493 PRTime time, |
5555 CERTOCSPSingleResponse | 5494 CERTOCSPSingleResponse |
5556 **pSingleResponse) | 5495 **pSingleResponse) |
5557 { | 5496 { |
5558 SECStatus rv; | 5497 SECStatus rv; |
5559 ocspResponseData *responseData; | 5498 ocspResponseData *responseData; |
5560 PRTime producedAt; | 5499 PRTime producedAt; |
5561 CERTOCSPSingleResponse *single; | 5500 CERTOCSPSingleResponse *single; |
5562 | 5501 |
5563 /* | 5502 /* |
5564 * The ResponseData part is the real guts of the response. | 5503 * The ResponseData part is the real guts of the response. |
5565 */ | 5504 */ |
(...skipping 23 matching lines...) Expand all Loading... |
5589 rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt); | 5528 rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt); |
5590 if (rv != SECSuccess) | 5529 if (rv != SECSuccess) |
5591 goto loser; | 5530 goto loser; |
5592 *pSingleResponse = single; | 5531 *pSingleResponse = single; |
5593 | 5532 |
5594 loser: | 5533 loser: |
5595 return rv; | 5534 return rv; |
5596 } | 5535 } |
5597 | 5536 |
5598 SECStatus | 5537 SECStatus |
5599 CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle, | 5538 CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle, |
5600 CERTOCSPResponse *response, | 5539 CERTOCSPResponse *response, |
5601 CERTOCSPCertID *certID, | 5540 CERTOCSPCertID *certID, |
5602 CERTCertificate *signerCert, | 5541 CERTCertificate *signerCert, |
5603 PRTime time) | 5542 PRTime time) |
5604 { | 5543 { |
5605 /* | 5544 /* |
5606 * We do not update the cache, because: | 5545 * We do not update the cache, because: |
5607 * | 5546 * |
5608 * CERT_GetOCSPStatusForCertID is an old exported API that was introduced | 5547 * CERT_GetOCSPStatusForCertID is an old exported API that was introduced |
5609 * before the OCSP cache got implemented. | 5548 * before the OCSP cache got implemented. |
5610 * | 5549 * |
5611 * The implementation of helper function cert_ProcessOCSPResponse | 5550 * The implementation of helper function cert_ProcessOCSPResponse |
5612 * requires the ability to transfer ownership of the the given certID to | 5551 * requires the ability to transfer ownership of the the given certID to |
5613 * the cache. The external API doesn't allow us to prevent the caller from | 5552 * the cache. The external API doesn't allow us to prevent the caller from |
5614 * destroying the certID. We don't have the original certificate available, | 5553 * destroying the certID. We don't have the original certificate available, |
5615 * therefore we are unable to produce another certID object (that could | 5554 * therefore we are unable to produce another certID object (that could |
5616 * be stored in the cache). | 5555 * be stored in the cache). |
5617 * | 5556 * |
5618 * Should we ever implement code to produce a deep copy of certID, | 5557 * Should we ever implement code to produce a deep copy of certID, |
5619 * then this could be changed to allow updating the cache. | 5558 * then this could be changed to allow updating the cache. |
5620 * The duplication would have to be done in | 5559 * The duplication would have to be done in |
5621 * cert_ProcessOCSPResponse, if the out parameter to indicate | 5560 * cert_ProcessOCSPResponse, if the out parameter to indicate |
5622 * a transfer of ownership is NULL. | 5561 * a transfer of ownership is NULL. |
5623 */ | 5562 */ |
5624 return cert_ProcessOCSPResponse(handle, response, certID, | 5563 return cert_ProcessOCSPResponse(handle, response, certID, |
5625 signerCert, time, | 5564 signerCert, time, |
5626 NULL, NULL); | 5565 NULL, NULL); |
5627 } | 5566 } |
5628 | 5567 |
5629 /* | 5568 /* |
5630 * The first 5 parameters match the definition of CERT_GetOCSPStatusForCertID. | 5569 * The first 5 parameters match the definition of CERT_GetOCSPStatusForCertID. |
5631 */ | 5570 */ |
5632 SECStatus | 5571 SECStatus |
5633 cert_ProcessOCSPResponse(CERTCertDBHandle *handle, | 5572 cert_ProcessOCSPResponse(CERTCertDBHandle *handle, |
5634 CERTOCSPResponse *response, | 5573 CERTOCSPResponse *response, |
5635 CERTOCSPCertID *certID, | 5574 CERTOCSPCertID *certID, |
5636 CERTCertificate *signerCert, | 5575 CERTCertificate *signerCert, |
5637 PRTime time, | 5576 PRTime time, |
5638 PRBool *certIDWasConsumed, | 5577 PRBool *certIDWasConsumed, |
5639 SECStatus *cacheUpdateStatus) | 5578 SECStatus *cacheUpdateStatus) |
5640 { | 5579 { |
5641 SECStatus rv; | 5580 SECStatus rv; |
5642 SECStatus rv_cache = SECSuccess; | 5581 SECStatus rv_cache = SECSuccess; |
5643 CERTOCSPSingleResponse *single = NULL; | 5582 CERTOCSPSingleResponse *single = NULL; |
5644 | 5583 |
5645 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, | 5584 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, |
5646 signerCert, time, &single); | 5585 signerCert, time, &single); |
5647 if (rv == SECSuccess) { | 5586 if (rv == SECSuccess) { |
5648 /* | 5587 /* |
5649 * Check whether the status says revoked, and if so | 5588 * Check whether the status says revoked, and if so |
5650 * how that compares to the time value passed into this routine. | 5589 * how that compares to the time value passed into this routine. |
5651 */ | 5590 */ |
5652 rv = ocsp_SingleResponseCertHasGoodStatus(single, time); | 5591 rv = ocsp_SingleResponseCertHasGoodStatus(single, time); |
5653 } | 5592 } |
5654 | 5593 |
5655 if (certIDWasConsumed) { | 5594 if (certIDWasConsumed) { |
5656 /* | 5595 /* |
5657 * We don't have copy-of-certid implemented. In order to update | 5596 * We don't have copy-of-certid implemented. In order to update |
5658 * the cache, the caller must supply an out variable | 5597 * the cache, the caller must supply an out variable |
5659 * certIDWasConsumed, allowing us to return ownership status. | 5598 * certIDWasConsumed, allowing us to return ownership status. |
5660 */ | 5599 */ |
5661 | 5600 |
5662 PR_EnterMonitor(OCSP_Global.monitor); | 5601 PR_EnterMonitor(OCSP_Global.monitor); |
5663 if (OCSP_Global.maxCacheEntries >= 0) { | 5602 if (OCSP_Global.maxCacheEntries >= 0) { |
5664 /* single == NULL means: remember response failure */ | 5603 /* single == NULL means: remember response failure */ |
5665 rv_cache = | 5604 rv_cache = |
5666 ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, | 5605 ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, |
5667 single, certIDWasConsumed); | 5606 single, certIDWasConsumed); |
5668 } | 5607 } |
5669 PR_ExitMonitor(OCSP_Global.monitor); | 5608 PR_ExitMonitor(OCSP_Global.monitor); |
5670 if (cacheUpdateStatus) { | 5609 if (cacheUpdateStatus) { |
5671 *cacheUpdateStatus = rv_cache; | 5610 *cacheUpdateStatus = rv_cache; |
5672 } | 5611 } |
5673 } | 5612 } |
5674 | 5613 |
5675 return rv; | 5614 return rv; |
5676 } | 5615 } |
5677 | 5616 |
5678 SECStatus | 5617 SECStatus |
5679 cert_RememberOCSPProcessingFailure(CERTOCSPCertID *certID, | 5618 cert_RememberOCSPProcessingFailure(CERTOCSPCertID *certID, |
5680 PRBool *certIDWasConsumed) | 5619 PRBool *certIDWasConsumed) |
5681 { | 5620 { |
5682 SECStatus rv = SECSuccess; | 5621 SECStatus rv = SECSuccess; |
5683 PR_EnterMonitor(OCSP_Global.monitor); | 5622 PR_EnterMonitor(OCSP_Global.monitor); |
5684 if (OCSP_Global.maxCacheEntries >= 0) { | 5623 if (OCSP_Global.maxCacheEntries >= 0) { |
5685 rv = ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, NULL, | 5624 rv = ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, NULL, |
5686 certIDWasConsumed); | 5625 certIDWasConsumed); |
5687 } | 5626 } |
5688 PR_ExitMonitor(OCSP_Global.monitor); | 5627 PR_ExitMonitor(OCSP_Global.monitor); |
5689 return rv; | 5628 return rv; |
5690 } | 5629 } |
5691 | 5630 |
5692 /* | 5631 /* |
5693 * Disable status checking and destroy related structures/data. | 5632 * Disable status checking and destroy related structures/data. |
5694 */ | 5633 */ |
5695 static SECStatus | 5634 static SECStatus |
5696 ocsp_DestroyStatusChecking(CERTStatusConfig *statusConfig) | 5635 ocsp_DestroyStatusChecking(CERTStatusConfig *statusConfig) |
5697 { | 5636 { |
5698 ocspCheckingContext *statusContext; | 5637 ocspCheckingContext *statusContext; |
5699 | 5638 |
5700 /* | 5639 /* |
5701 * Disable OCSP checking | 5640 * Disable OCSP checking |
5702 */ | 5641 */ |
5703 statusConfig->statusChecker = NULL; | 5642 statusConfig->statusChecker = NULL; |
5704 | 5643 |
5705 statusContext = statusConfig->statusContext; | 5644 statusContext = statusConfig->statusContext; |
5706 PORT_Assert(statusContext != NULL); | 5645 PORT_Assert(statusContext != NULL); |
5707 if (statusContext == NULL) | 5646 if (statusContext == NULL) |
5708 » return SECFailure; | 5647 return SECFailure; |
5709 | 5648 |
5710 if (statusContext->defaultResponderURI != NULL) | 5649 if (statusContext->defaultResponderURI != NULL) |
5711 » PORT_Free(statusContext->defaultResponderURI); | 5650 PORT_Free(statusContext->defaultResponderURI); |
5712 if (statusContext->defaultResponderNickname != NULL) | 5651 if (statusContext->defaultResponderNickname != NULL) |
5713 » PORT_Free(statusContext->defaultResponderNickname); | 5652 PORT_Free(statusContext->defaultResponderNickname); |
5714 | 5653 |
5715 PORT_Free(statusContext); | 5654 PORT_Free(statusContext); |
5716 statusConfig->statusContext = NULL; | 5655 statusConfig->statusContext = NULL; |
5717 | 5656 |
5718 PORT_Free(statusConfig); | 5657 PORT_Free(statusConfig); |
5719 | 5658 |
5720 return SECSuccess; | 5659 return SECSuccess; |
5721 } | 5660 } |
5722 | 5661 |
5723 | |
5724 /* | 5662 /* |
5725 * FUNCTION: CERT_DisableOCSPChecking | 5663 * FUNCTION: CERT_DisableOCSPChecking |
5726 * Turns off OCSP checking for the given certificate database. | 5664 * Turns off OCSP checking for the given certificate database. |
5727 * This routine disables OCSP checking. Though it will return | 5665 * This routine disables OCSP checking. Though it will return |
5728 * SECFailure if OCSP checking is not enabled, it is "safe" to | 5666 * SECFailure if OCSP checking is not enabled, it is "safe" to |
5729 * call it that way and just ignore the return value, if it is | 5667 * call it that way and just ignore the return value, if it is |
5730 * easier to just call it than to "remember" whether it is enabled. | 5668 * easier to just call it than to "remember" whether it is enabled. |
5731 * INPUTS: | 5669 * INPUTS: |
5732 * CERTCertDBHandle *handle | 5670 * CERTCertDBHandle *handle |
5733 * Certificate database for which OCSP checking will be disabled. | 5671 * Certificate database for which OCSP checking will be disabled. |
5734 * RETURN: | 5672 * RETURN: |
5735 * Returns SECFailure if an error occurred (usually means that OCSP | 5673 * Returns SECFailure if an error occurred (usually means that OCSP |
5736 * checking was not enabled or status contexts were not initialized -- | 5674 * checking was not enabled or status contexts were not initialized -- |
5737 * error set will be SEC_ERROR_OCSP_NOT_ENABLED); SECSuccess otherwise. | 5675 * error set will be SEC_ERROR_OCSP_NOT_ENABLED); SECSuccess otherwise. |
5738 */ | 5676 */ |
5739 SECStatus | 5677 SECStatus |
5740 CERT_DisableOCSPChecking(CERTCertDBHandle *handle) | 5678 CERT_DisableOCSPChecking(CERTCertDBHandle *handle) |
5741 { | 5679 { |
5742 CERTStatusConfig *statusConfig; | 5680 CERTStatusConfig *statusConfig; |
5743 ocspCheckingContext *statusContext; | 5681 ocspCheckingContext *statusContext; |
5744 | 5682 |
5745 if (handle == NULL) { | 5683 if (handle == NULL) { |
5746 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 5684 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
5747 » return SECFailure; | 5685 return SECFailure; |
5748 } | 5686 } |
5749 | 5687 |
5750 statusConfig = CERT_GetStatusConfig(handle); | 5688 statusConfig = CERT_GetStatusConfig(handle); |
5751 statusContext = ocsp_GetCheckingContext(handle); | 5689 statusContext = ocsp_GetCheckingContext(handle); |
5752 if (statusContext == NULL) | 5690 if (statusContext == NULL) |
5753 » return SECFailure; | 5691 return SECFailure; |
5754 | 5692 |
5755 if (statusConfig->statusChecker != CERT_CheckOCSPStatus) { | 5693 if (statusConfig->statusChecker != CERT_CheckOCSPStatus) { |
5756 » /* | 5694 /* |
5757 » * Status configuration is present, but either not currently | 5695 » * Status configuration is present, but either not currently |
5758 » * enabled or not for OCSP. | 5696 » * enabled or not for OCSP. |
5759 » */ | 5697 » */ |
5760 » PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED); | 5698 PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED); |
5761 » return SECFailure; | 5699 return SECFailure; |
5762 } | 5700 } |
5763 | 5701 |
5764 /* cache no longer necessary */ | 5702 /* cache no longer necessary */ |
5765 CERT_ClearOCSPCache(); | 5703 CERT_ClearOCSPCache(); |
5766 | 5704 |
5767 /* | 5705 /* |
5768 * This is how we disable status checking. Everything else remains | 5706 * This is how we disable status checking. Everything else remains |
5769 * in place in case we are enabled again. | 5707 * in place in case we are enabled again. |
5770 */ | 5708 */ |
5771 statusConfig->statusChecker = NULL; | 5709 statusConfig->statusChecker = NULL; |
5772 | 5710 |
5773 return SECSuccess; | 5711 return SECSuccess; |
5774 } | 5712 } |
5775 | 5713 |
5776 /* | 5714 /* |
5777 * Allocate and initialize the informational structures for status checking. | 5715 * Allocate and initialize the informational structures for status checking. |
5778 * This is done when some configuration of OCSP is being done or when OCSP | 5716 * This is done when some configuration of OCSP is being done or when OCSP |
5779 * checking is being turned on, whichever comes first. | 5717 * checking is being turned on, whichever comes first. |
5780 */ | 5718 */ |
5781 static SECStatus | 5719 static SECStatus |
5782 ocsp_InitStatusChecking(CERTCertDBHandle *handle) | 5720 ocsp_InitStatusChecking(CERTCertDBHandle *handle) |
5783 { | 5721 { |
5784 CERTStatusConfig *statusConfig = NULL; | 5722 CERTStatusConfig *statusConfig = NULL; |
5785 ocspCheckingContext *statusContext = NULL; | 5723 ocspCheckingContext *statusContext = NULL; |
5786 | 5724 |
5787 PORT_Assert(CERT_GetStatusConfig(handle) == NULL); | 5725 PORT_Assert(CERT_GetStatusConfig(handle) == NULL); |
5788 if (CERT_GetStatusConfig(handle) != NULL) { | 5726 if (CERT_GetStatusConfig(handle) != NULL) { |
5789 » /* XXX or call statusConfig->statusDestroy and continue? */ | 5727 /* XXX or call statusConfig->statusDestroy and continue? */ |
5790 » return SECFailure; | 5728 return SECFailure; |
5791 } | 5729 } |
5792 | 5730 |
5793 statusConfig = PORT_ZNew(CERTStatusConfig); | 5731 statusConfig = PORT_ZNew(CERTStatusConfig); |
5794 if (statusConfig == NULL) | 5732 if (statusConfig == NULL) |
5795 » goto loser; | 5733 goto loser; |
5796 | 5734 |
5797 statusContext = PORT_ZNew(ocspCheckingContext); | 5735 statusContext = PORT_ZNew(ocspCheckingContext); |
5798 if (statusContext == NULL) | 5736 if (statusContext == NULL) |
5799 » goto loser; | 5737 goto loser; |
5800 | 5738 |
5801 statusConfig->statusDestroy = ocsp_DestroyStatusChecking; | 5739 statusConfig->statusDestroy = ocsp_DestroyStatusChecking; |
5802 statusConfig->statusContext = statusContext; | 5740 statusConfig->statusContext = statusContext; |
5803 | 5741 |
5804 CERT_SetStatusConfig(handle, statusConfig); | 5742 CERT_SetStatusConfig(handle, statusConfig); |
5805 | 5743 |
5806 return SECSuccess; | 5744 return SECSuccess; |
5807 | 5745 |
5808 loser: | 5746 loser: |
5809 if (statusConfig != NULL) | 5747 if (statusConfig != NULL) |
5810 » PORT_Free(statusConfig); | 5748 PORT_Free(statusConfig); |
5811 return SECFailure; | 5749 return SECFailure; |
5812 } | 5750 } |
5813 | 5751 |
5814 | |
5815 /* | 5752 /* |
5816 * FUNCTION: CERT_EnableOCSPChecking | 5753 * FUNCTION: CERT_EnableOCSPChecking |
5817 * Turns on OCSP checking for the given certificate database. | 5754 * Turns on OCSP checking for the given certificate database. |
5818 * INPUTS: | 5755 * INPUTS: |
5819 * CERTCertDBHandle *handle | 5756 * CERTCertDBHandle *handle |
5820 * Certificate database for which OCSP checking will be enabled. | 5757 * Certificate database for which OCSP checking will be enabled. |
5821 * RETURN: | 5758 * RETURN: |
5822 * Returns SECFailure if an error occurred (likely only problem | 5759 * Returns SECFailure if an error occurred (likely only problem |
5823 * allocating memory); SECSuccess otherwise. | 5760 * allocating memory); SECSuccess otherwise. |
5824 */ | 5761 */ |
5825 SECStatus | 5762 SECStatus |
5826 CERT_EnableOCSPChecking(CERTCertDBHandle *handle) | 5763 CERT_EnableOCSPChecking(CERTCertDBHandle *handle) |
5827 { | 5764 { |
5828 CERTStatusConfig *statusConfig; | 5765 CERTStatusConfig *statusConfig; |
5829 | 5766 |
5830 SECStatus rv; | 5767 SECStatus rv; |
5831 | 5768 |
5832 if (handle == NULL) { | 5769 if (handle == NULL) { |
5833 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 5770 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
5834 » return SECFailure; | 5771 return SECFailure; |
5835 } | 5772 } |
5836 | 5773 |
5837 statusConfig = CERT_GetStatusConfig(handle); | 5774 statusConfig = CERT_GetStatusConfig(handle); |
5838 if (statusConfig == NULL) { | 5775 if (statusConfig == NULL) { |
5839 » rv = ocsp_InitStatusChecking(handle); | 5776 rv = ocsp_InitStatusChecking(handle); |
5840 » if (rv != SECSuccess) | 5777 if (rv != SECSuccess) |
5841 » return rv; | 5778 return rv; |
5842 | 5779 |
5843 » /* Get newly established value */ | 5780 /* Get newly established value */ |
5844 » statusConfig = CERT_GetStatusConfig(handle); | 5781 statusConfig = CERT_GetStatusConfig(handle); |
5845 » PORT_Assert(statusConfig != NULL); | 5782 PORT_Assert(statusConfig != NULL); |
5846 } | 5783 } |
5847 | 5784 |
5848 /* | 5785 /* |
5849 * Setting the checker function is what really enables the checking | 5786 * Setting the checker function is what really enables the checking |
5850 * when each cert verification is done. | 5787 * when each cert verification is done. |
5851 */ | 5788 */ |
5852 statusConfig->statusChecker = CERT_CheckOCSPStatus; | 5789 statusConfig->statusChecker = CERT_CheckOCSPStatus; |
5853 | 5790 |
5854 return SECSuccess; | 5791 return SECSuccess; |
5855 } | 5792 } |
5856 | 5793 |
5857 | |
5858 /* | 5794 /* |
5859 * FUNCTION: CERT_SetOCSPDefaultResponder | 5795 * FUNCTION: CERT_SetOCSPDefaultResponder |
5860 * Specify the location and cert of the default responder. | 5796 * Specify the location and cert of the default responder. |
5861 * If OCSP checking is already enabled *and* use of a default responder | 5797 * If OCSP checking is already enabled *and* use of a default responder |
5862 * is also already enabled, all OCSP checking from now on will go directly | 5798 * is also already enabled, all OCSP checking from now on will go directly |
5863 * to the specified responder. If OCSP checking is not enabled, or if | 5799 * to the specified responder. If OCSP checking is not enabled, or if |
5864 * it is but use of a default responder is not enabled, the information | 5800 * it is but use of a default responder is not enabled, the information |
5865 * will be recorded and take effect whenever both are enabled. | 5801 * will be recorded and take effect whenever both are enabled. |
5866 * INPUTS: | 5802 * INPUTS: |
5867 * CERTCertDBHandle *handle | 5803 * CERTCertDBHandle *handle |
5868 * Cert database on which OCSP checking should use the default responder. | 5804 * Cert database on which OCSP checking should use the default responder. |
5869 * char *url | 5805 * char *url |
5870 * The location of the default responder (e.g. "http://foo.com:80/ocsp") | 5806 * The location of the default responder (e.g. "http://foo.com:80/ocsp") |
5871 * Note that the location will not be tested until the first attempt | 5807 * Note that the location will not be tested until the first attempt |
5872 * to send a request there. | 5808 * to send a request there. |
5873 * char *name | 5809 * char *name |
5874 * The nickname of the cert to trust (expected) to sign the OCSP responses. | 5810 * The nickname of the cert to trust (expected) to sign the OCSP responses. |
5875 * If the corresponding cert cannot be found, SECFailure is returned. | 5811 * If the corresponding cert cannot be found, SECFailure is returned. |
5876 * RETURN: | 5812 * RETURN: |
5877 * Returns SECFailure if an error occurred; SECSuccess otherwise. | 5813 * Returns SECFailure if an error occurred; SECSuccess otherwise. |
5878 * The most likely error is that the cert for "name" could not be found | 5814 * The most likely error is that the cert for "name" could not be found |
5879 * (probably SEC_ERROR_UNKNOWN_CERT). Other errors are low-level (no memory, | 5815 * (probably SEC_ERROR_UNKNOWN_CERT). Other errors are low-level (no memory, |
5880 * bad database, etc.). | 5816 * bad database, etc.). |
5881 */ | 5817 */ |
5882 SECStatus | 5818 SECStatus |
5883 CERT_SetOCSPDefaultResponder(CERTCertDBHandle *handle, | 5819 CERT_SetOCSPDefaultResponder(CERTCertDBHandle *handle, |
5884 » » » const char *url, const char *name) | 5820 const char *url, const char *name) |
5885 { | 5821 { |
5886 CERTCertificate *cert; | 5822 CERTCertificate *cert; |
5887 ocspCheckingContext *statusContext; | 5823 ocspCheckingContext *statusContext; |
5888 char *url_copy = NULL; | 5824 char *url_copy = NULL; |
5889 char *name_copy = NULL; | 5825 char *name_copy = NULL; |
5890 SECStatus rv; | 5826 SECStatus rv; |
5891 | 5827 |
5892 if (handle == NULL || url == NULL || name == NULL) { | 5828 if (handle == NULL || url == NULL || name == NULL) { |
5893 » /* | 5829 /* |
5894 » * XXX When interface is exported, probably want better errors; | 5830 » * XXX When interface is exported, probably want better errors; |
5895 » * perhaps different one for each parameter. | 5831 » * perhaps different one for each parameter. |
5896 » */ | 5832 » */ |
5897 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 5833 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
5898 » return SECFailure; | 5834 return SECFailure; |
5899 } | 5835 } |
5900 | 5836 |
5901 /* | 5837 /* |
5902 * Find the certificate for the specified nickname. Do this first | 5838 * Find the certificate for the specified nickname. Do this first |
5903 * because it seems the most likely to fail. | 5839 * because it seems the most likely to fail. |
5904 * | 5840 * |
5905 * XXX Shouldn't need that cast if the FindCertByNickname interface | 5841 * XXX Shouldn't need that cast if the FindCertByNickname interface |
5906 * used const to convey that it does not modify the name. Maybe someday. | 5842 * used const to convey that it does not modify the name. Maybe someday. |
5907 */ | 5843 */ |
5908 cert = CERT_FindCertByNickname(handle, (char *) name); | 5844 cert = CERT_FindCertByNickname(handle, (char *)name); |
5909 if (cert == NULL) { | 5845 if (cert == NULL) { |
5910 /* | 5846 /* |
5911 * look for the cert on an external token. | 5847 * look for the cert on an external token. |
5912 */ | 5848 */ |
5913 cert = PK11_FindCertFromNickname((char *)name, NULL); | 5849 cert = PK11_FindCertFromNickname((char *)name, NULL); |
5914 } | 5850 } |
5915 if (cert == NULL) | 5851 if (cert == NULL) |
5916 » return SECFailure; | 5852 return SECFailure; |
5917 | 5853 |
5918 /* | 5854 /* |
5919 * Make a copy of the url and nickname. | 5855 * Make a copy of the url and nickname. |
5920 */ | 5856 */ |
5921 url_copy = PORT_Strdup(url); | 5857 url_copy = PORT_Strdup(url); |
5922 name_copy = PORT_Strdup(name); | 5858 name_copy = PORT_Strdup(name); |
5923 if (url_copy == NULL || name_copy == NULL) { | 5859 if (url_copy == NULL || name_copy == NULL) { |
5924 » rv = SECFailure; | 5860 rv = SECFailure; |
5925 » goto loser; | 5861 goto loser; |
5926 } | 5862 } |
5927 | 5863 |
5928 statusContext = ocsp_GetCheckingContext(handle); | 5864 statusContext = ocsp_GetCheckingContext(handle); |
5929 | 5865 |
5930 /* | 5866 /* |
5931 * Allocate and init the context if it doesn't already exist. | 5867 * Allocate and init the context if it doesn't already exist. |
5932 */ | 5868 */ |
5933 if (statusContext == NULL) { | 5869 if (statusContext == NULL) { |
5934 » rv = ocsp_InitStatusChecking(handle); | 5870 rv = ocsp_InitStatusChecking(handle); |
5935 » if (rv != SECSuccess) | 5871 if (rv != SECSuccess) |
5936 » goto loser; | 5872 goto loser; |
5937 | 5873 |
5938 » statusContext = ocsp_GetCheckingContext(handle); | 5874 statusContext = ocsp_GetCheckingContext(handle); |
5939 » PORT_Assert(statusContext != NULL);» /* extreme paranoia */ | 5875 PORT_Assert(statusContext != NULL); /* extreme paranoia */ |
5940 } | 5876 } |
5941 | 5877 |
5942 /* | 5878 /* |
5943 * Note -- we do not touch the status context until after all of | 5879 * Note -- we do not touch the status context until after all of |
5944 * the steps which could cause errors. If something goes wrong, | 5880 * the steps which could cause errors. If something goes wrong, |
5945 * we want to leave things as they were. | 5881 * we want to leave things as they were. |
5946 */ | 5882 */ |
5947 | 5883 |
5948 /* | 5884 /* |
5949 * Get rid of old url and name if there. | 5885 * Get rid of old url and name if there. |
5950 */ | 5886 */ |
5951 if (statusContext->defaultResponderNickname != NULL) | 5887 if (statusContext->defaultResponderNickname != NULL) |
5952 » PORT_Free(statusContext->defaultResponderNickname); | 5888 PORT_Free(statusContext->defaultResponderNickname); |
5953 if (statusContext->defaultResponderURI != NULL) | 5889 if (statusContext->defaultResponderURI != NULL) |
5954 » PORT_Free(statusContext->defaultResponderURI); | 5890 PORT_Free(statusContext->defaultResponderURI); |
5955 | 5891 |
5956 /* | 5892 /* |
5957 * And replace them with the new ones. | 5893 * And replace them with the new ones. |
5958 */ | 5894 */ |
5959 statusContext->defaultResponderURI = url_copy; | 5895 statusContext->defaultResponderURI = url_copy; |
5960 statusContext->defaultResponderNickname = name_copy; | 5896 statusContext->defaultResponderNickname = name_copy; |
5961 | 5897 |
5962 /* | 5898 /* |
5963 * If there was already a cert in place, get rid of it and replace it. | 5899 * If there was already a cert in place, get rid of it and replace it. |
5964 * Otherwise, we are not currently enabled, so we don't want to save it; | 5900 * Otherwise, we are not currently enabled, so we don't want to save it; |
5965 * it will get re-found and set whenever use of a default responder is | 5901 * it will get re-found and set whenever use of a default responder is |
5966 * enabled. | 5902 * enabled. |
5967 */ | 5903 */ |
5968 if (statusContext->defaultResponderCert != NULL) { | 5904 if (statusContext->defaultResponderCert != NULL) { |
5969 » CERT_DestroyCertificate(statusContext->defaultResponderCert); | 5905 CERT_DestroyCertificate(statusContext->defaultResponderCert); |
5970 » statusContext->defaultResponderCert = cert; | 5906 statusContext->defaultResponderCert = cert; |
5971 /*OCSP enabled, switching responder: clear cache*/ | 5907 /*OCSP enabled, switching responder: clear cache*/ |
5972 CERT_ClearOCSPCache(); | 5908 CERT_ClearOCSPCache(); |
5973 } else { | 5909 } else { |
5974 » PORT_Assert(statusContext->useDefaultResponder == PR_FALSE); | 5910 PORT_Assert(statusContext->useDefaultResponder == PR_FALSE); |
5975 » CERT_DestroyCertificate(cert); | 5911 CERT_DestroyCertificate(cert); |
5976 /*OCSP currently not enabled, no need to clear cache*/ | 5912 /*OCSP currently not enabled, no need to clear cache*/ |
5977 } | 5913 } |
5978 | 5914 |
5979 return SECSuccess; | 5915 return SECSuccess; |
5980 | 5916 |
5981 loser: | 5917 loser: |
5982 CERT_DestroyCertificate(cert); | 5918 CERT_DestroyCertificate(cert); |
5983 if (url_copy != NULL) | 5919 if (url_copy != NULL) |
5984 » PORT_Free(url_copy); | 5920 PORT_Free(url_copy); |
5985 if (name_copy != NULL) | 5921 if (name_copy != NULL) |
5986 » PORT_Free(name_copy); | 5922 PORT_Free(name_copy); |
5987 return rv; | 5923 return rv; |
5988 } | 5924 } |
5989 | 5925 |
5990 | |
5991 /* | 5926 /* |
5992 * FUNCTION: CERT_EnableOCSPDefaultResponder | 5927 * FUNCTION: CERT_EnableOCSPDefaultResponder |
5993 * Turns on use of a default responder when OCSP checking. | 5928 * Turns on use of a default responder when OCSP checking. |
5994 * If OCSP checking is already enabled, this will make subsequent checks | 5929 * If OCSP checking is already enabled, this will make subsequent checks |
5995 * go directly to the default responder. (The location of the responder | 5930 * go directly to the default responder. (The location of the responder |
5996 * and the nickname of the responder cert must already be specified.) | 5931 * and the nickname of the responder cert must already be specified.) |
5997 * If OCSP checking is not enabled, this will be recorded and take effect | 5932 * If OCSP checking is not enabled, this will be recorded and take effect |
5998 * whenever it is enabled. | 5933 * whenever it is enabled. |
5999 * INPUTS: | 5934 * INPUTS: |
6000 * CERTCertDBHandle *handle | 5935 * CERTCertDBHandle *handle |
6001 * Cert database on which OCSP checking should use the default responder. | 5936 * Cert database on which OCSP checking should use the default responder. |
6002 * RETURN: | 5937 * RETURN: |
6003 * Returns SECFailure if an error occurred; SECSuccess otherwise. | 5938 * Returns SECFailure if an error occurred; SECSuccess otherwise. |
6004 * No errors are especially likely unless the caller did not previously | 5939 * No errors are especially likely unless the caller did not previously |
6005 * perform a successful call to SetOCSPDefaultResponder (in which case | 5940 * perform a successful call to SetOCSPDefaultResponder (in which case |
6006 * the error set will be SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER). | 5941 * the error set will be SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER). |
6007 */ | 5942 */ |
6008 SECStatus | 5943 SECStatus |
6009 CERT_EnableOCSPDefaultResponder(CERTCertDBHandle *handle) | 5944 CERT_EnableOCSPDefaultResponder(CERTCertDBHandle *handle) |
6010 { | 5945 { |
6011 ocspCheckingContext *statusContext; | 5946 ocspCheckingContext *statusContext; |
6012 CERTCertificate *cert; | 5947 CERTCertificate *cert; |
6013 SECStatus rv; | 5948 SECStatus rv; |
6014 SECCertificateUsage usage; | 5949 SECCertificateUsage usage; |
6015 | 5950 |
6016 if (handle == NULL) { | 5951 if (handle == NULL) { |
6017 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 5952 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
6018 » return SECFailure; | 5953 return SECFailure; |
6019 } | 5954 } |
6020 | 5955 |
6021 statusContext = ocsp_GetCheckingContext(handle); | 5956 statusContext = ocsp_GetCheckingContext(handle); |
6022 | 5957 |
6023 if (statusContext == NULL) { | 5958 if (statusContext == NULL) { |
6024 » /* | 5959 /* |
6025 » * Strictly speaking, the error already set is "correct", | 5960 » * Strictly speaking, the error already set is "correct", |
6026 » * but cover over it with one more helpful in this context. | 5961 » * but cover over it with one more helpful in this context. |
6027 » */ | 5962 » */ |
6028 » PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER); | 5963 PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER); |
6029 » return SECFailure; | 5964 return SECFailure; |
6030 } | 5965 } |
6031 | 5966 |
6032 if (statusContext->defaultResponderURI == NULL) { | 5967 if (statusContext->defaultResponderURI == NULL) { |
6033 » PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER); | 5968 PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER); |
6034 » return SECFailure; | 5969 return SECFailure; |
6035 } | 5970 } |
6036 | 5971 |
6037 if (statusContext->defaultResponderNickname == NULL) { | 5972 if (statusContext->defaultResponderNickname == NULL) { |
6038 » PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER); | 5973 PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER); |
6039 » return SECFailure; | 5974 return SECFailure; |
6040 } | 5975 } |
6041 | 5976 |
6042 /* | 5977 /* |
6043 * Find the cert for the nickname. | 5978 * Find the cert for the nickname. |
6044 */ | 5979 */ |
6045 cert = CERT_FindCertByNickname(handle, | 5980 cert = CERT_FindCertByNickname(handle, |
6046 » » » » statusContext->defaultResponderNickname); | 5981 statusContext->defaultResponderNickname); |
6047 if (cert == NULL) { | 5982 if (cert == NULL) { |
6048 cert = PK11_FindCertFromNickname(statusContext->defaultResponderNickname
, | 5983 cert = PK11_FindCertFromNickname(statusContext->defaultResponderNickname
, |
6049 NULL); | 5984 NULL); |
6050 } | 5985 } |
6051 /* | 5986 /* |
6052 * We should never have trouble finding the cert, because its | 5987 * We should never have trouble finding the cert, because its |
6053 * existence should have been proven by SetOCSPDefaultResponder. | 5988 * existence should have been proven by SetOCSPDefaultResponder. |
6054 */ | 5989 */ |
6055 PORT_Assert(cert != NULL); | 5990 PORT_Assert(cert != NULL); |
6056 if (cert == NULL) | 5991 if (cert == NULL) |
6057 » return SECFailure; | 5992 return SECFailure; |
6058 | 5993 |
6059 /* | 5994 /* |
6060 * Supplied cert should at least have a signing capability in order for us | 5995 * Supplied cert should at least have a signing capability in order for us |
6061 * to use it as a trusted responder cert. Ability to sign is guaranteed if | 5996 * to use it as a trusted responder cert. Ability to sign is guaranteed if |
6062 * cert is validated to have any set of the usages below. | 5997 * cert is validated to have any set of the usages below. |
6063 */ | 5998 */ |
6064 rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE, | 5999 rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE, |
6065 certificateUsageCheckAllUsages, | 6000 certificateUsageCheckAllUsages, |
6066 NULL, &usage); | 6001 NULL, &usage); |
6067 if (rv != SECSuccess || (usage & (certificateUsageSSLClient | | 6002 if (rv != SECSuccess || (usage & (certificateUsageSSLClient | |
6068 certificateUsageSSLServer | | 6003 certificateUsageSSLServer | |
6069 certificateUsageSSLServerWithStepUp | | 6004 certificateUsageSSLServerWithStepUp | |
6070 certificateUsageEmailSigner | | 6005 certificateUsageEmailSigner | |
6071 certificateUsageObjectSigner | | 6006 certificateUsageObjectSigner | |
6072 certificateUsageStatusResponder | | 6007 certificateUsageStatusResponder | |
6073 certificateUsageSSLCA)) == 0) { | 6008 certificateUsageSSLCA)) == 0) { |
6074 » PORT_SetError(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID); | 6009 PORT_SetError(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID); |
6075 » return SECFailure; | 6010 return SECFailure; |
6076 } | 6011 } |
6077 | 6012 |
6078 /* | 6013 /* |
6079 * And hang onto it. | 6014 * And hang onto it. |
6080 */ | 6015 */ |
6081 statusContext->defaultResponderCert = cert; | 6016 statusContext->defaultResponderCert = cert; |
6082 | 6017 |
6083 /* we don't allow a mix of cache entries from different responders */ | 6018 /* we don't allow a mix of cache entries from different responders */ |
6084 CERT_ClearOCSPCache(); | 6019 CERT_ClearOCSPCache(); |
6085 | 6020 |
6086 /* | 6021 /* |
6087 * Finally, record the fact that we now have a default responder enabled. | 6022 * Finally, record the fact that we now have a default responder enabled. |
6088 */ | 6023 */ |
6089 statusContext->useDefaultResponder = PR_TRUE; | 6024 statusContext->useDefaultResponder = PR_TRUE; |
6090 return SECSuccess; | 6025 return SECSuccess; |
6091 } | 6026 } |
6092 | 6027 |
6093 | |
6094 /* | 6028 /* |
6095 * FUNCTION: CERT_DisableOCSPDefaultResponder | 6029 * FUNCTION: CERT_DisableOCSPDefaultResponder |
6096 * Turns off use of a default responder when OCSP checking. | 6030 * Turns off use of a default responder when OCSP checking. |
6097 * (Does nothing if use of a default responder is not enabled.) | 6031 * (Does nothing if use of a default responder is not enabled.) |
6098 * INPUTS: | 6032 * INPUTS: |
6099 * CERTCertDBHandle *handle | 6033 * CERTCertDBHandle *handle |
6100 * Cert database on which OCSP checking should stop using a default | 6034 * Cert database on which OCSP checking should stop using a default |
6101 * responder. | 6035 * responder. |
6102 * RETURN: | 6036 * RETURN: |
6103 * Returns SECFailure if an error occurred; SECSuccess otherwise. | 6037 * Returns SECFailure if an error occurred; SECSuccess otherwise. |
6104 * Errors very unlikely (like random memory corruption...). | 6038 * Errors very unlikely (like random memory corruption...). |
6105 */ | 6039 */ |
6106 SECStatus | 6040 SECStatus |
6107 CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle) | 6041 CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle) |
6108 { | 6042 { |
6109 CERTStatusConfig *statusConfig; | 6043 CERTStatusConfig *statusConfig; |
6110 ocspCheckingContext *statusContext; | 6044 ocspCheckingContext *statusContext; |
6111 CERTCertificate *tmpCert; | 6045 CERTCertificate *tmpCert; |
6112 | 6046 |
6113 if (handle == NULL) { | 6047 if (handle == NULL) { |
6114 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 6048 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
6115 » return SECFailure; | 6049 return SECFailure; |
6116 } | 6050 } |
6117 | 6051 |
6118 statusConfig = CERT_GetStatusConfig(handle); | 6052 statusConfig = CERT_GetStatusConfig(handle); |
6119 if (statusConfig == NULL) | 6053 if (statusConfig == NULL) |
6120 » return SECSuccess; | 6054 return SECSuccess; |
6121 | 6055 |
6122 statusContext = ocsp_GetCheckingContext(handle); | 6056 statusContext = ocsp_GetCheckingContext(handle); |
6123 PORT_Assert(statusContext != NULL); | 6057 PORT_Assert(statusContext != NULL); |
6124 if (statusContext == NULL) | 6058 if (statusContext == NULL) |
6125 » return SECFailure; | 6059 return SECFailure; |
6126 | 6060 |
6127 tmpCert = statusContext->defaultResponderCert; | 6061 tmpCert = statusContext->defaultResponderCert; |
6128 if (tmpCert) { | 6062 if (tmpCert) { |
6129 » statusContext->defaultResponderCert = NULL; | 6063 statusContext->defaultResponderCert = NULL; |
6130 » CERT_DestroyCertificate(tmpCert); | 6064 CERT_DestroyCertificate(tmpCert); |
6131 /* we don't allow a mix of cache entries from different responders */ | 6065 /* we don't allow a mix of cache entries from different responders */ |
6132 CERT_ClearOCSPCache(); | 6066 CERT_ClearOCSPCache(); |
6133 } | 6067 } |
6134 | 6068 |
6135 /* | 6069 /* |
6136 * Finally, record the fact. | 6070 * Finally, record the fact. |
6137 */ | 6071 */ |
6138 statusContext->useDefaultResponder = PR_FALSE; | 6072 statusContext->useDefaultResponder = PR_FALSE; |
6139 return SECSuccess; | 6073 return SECSuccess; |
6140 } | 6074 } |
(...skipping 11 matching lines...) Expand all Loading... |
6152 PR_ExitMonitor(OCSP_Global.monitor); | 6086 PR_ExitMonitor(OCSP_Global.monitor); |
6153 | 6087 |
6154 return SECSuccess; | 6088 return SECSuccess; |
6155 } | 6089 } |
6156 | 6090 |
6157 SECStatus | 6091 SECStatus |
6158 CERT_GetOCSPResponseStatus(CERTOCSPResponse *response) | 6092 CERT_GetOCSPResponseStatus(CERTOCSPResponse *response) |
6159 { | 6093 { |
6160 PORT_Assert(response); | 6094 PORT_Assert(response); |
6161 if (response->statusValue == ocspResponse_successful) | 6095 if (response->statusValue == ocspResponse_successful) |
6162 » return SECSuccess; | 6096 return SECSuccess; |
6163 | 6097 |
6164 switch (response->statusValue) { | 6098 switch (response->statusValue) { |
6165 case ocspResponse_malformedRequest: | 6099 case ocspResponse_malformedRequest: |
6166 » PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST); | 6100 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST); |
6167 » break; | 6101 break; |
6168 case ocspResponse_internalError: | 6102 case ocspResponse_internalError: |
6169 » PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); | 6103 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); |
6170 » break; | 6104 break; |
6171 case ocspResponse_tryLater: | 6105 case ocspResponse_tryLater: |
6172 » PORT_SetError(SEC_ERROR_OCSP_TRY_SERVER_LATER); | 6106 PORT_SetError(SEC_ERROR_OCSP_TRY_SERVER_LATER); |
6173 » break; | 6107 break; |
6174 case ocspResponse_sigRequired: | 6108 case ocspResponse_sigRequired: |
6175 » /* XXX We *should* retry with a signature, if possible. */ | 6109 /* XXX We *should* retry with a signature, if possible. */ |
6176 » PORT_SetError(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG); | 6110 PORT_SetError(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG); |
6177 » break; | 6111 break; |
6178 case ocspResponse_unauthorized: | 6112 case ocspResponse_unauthorized: |
6179 » PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST); | 6113 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST); |
6180 » break; | 6114 break; |
6181 case ocspResponse_unused: | 6115 case ocspResponse_unused: |
6182 default: | 6116 default: |
6183 » PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS); | 6117 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS); |
6184 » break; | 6118 break; |
6185 } | 6119 } |
6186 return SECFailure; | 6120 return SECFailure; |
6187 } | 6121 } |
OLD | NEW |