| 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 |