| 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 #include "nspr.h" | 4 #include "nspr.h" |
| 5 #include "secerr.h" | 5 #include "secerr.h" |
| 6 #include "secport.h" | 6 #include "secport.h" |
| 7 #include "seccomon.h" | 7 #include "seccomon.h" |
| 8 #include "secoid.h" | 8 #include "secoid.h" |
| 9 #include "genname.h" | 9 #include "genname.h" |
| 10 #include "keyhi.h" | 10 #include "keyhi.h" |
| 11 #include "cert.h" | 11 #include "cert.h" |
| 12 #include "certdb.h" | 12 #include "certdb.h" |
| 13 #include "certi.h" | 13 #include "certi.h" |
| 14 #include "cryptohi.h" | 14 #include "cryptohi.h" |
| 15 #ifndef NSS_DISABLE_LIBPKIX | 15 #ifndef NSS_DISABLE_LIBPKIX |
| 16 #include "pkix.h" | 16 #include "pkix.h" |
| 17 /*#include "pkix_sample_modules.h" */ | 17 /*#include "pkix_sample_modules.h" */ |
| 18 #include "pkix_pl_cert.h" | 18 #include "pkix_pl_cert.h" |
| 19 #endif /* NSS_DISABLE_LIBPKIX */ | 19 #endif /* NSS_DISABLE_LIBPKIX */ |
| 20 | 20 |
| 21 | |
| 22 #include "nsspki.h" | 21 #include "nsspki.h" |
| 23 #include "pkitm.h" | 22 #include "pkitm.h" |
| 24 #include "pkim.h" | 23 #include "pkim.h" |
| 25 #include "pki3hack.h" | 24 #include "pki3hack.h" |
| 26 #include "base.h" | 25 #include "base.h" |
| 27 #include "keyhi.h" | 26 #include "keyhi.h" |
| 28 | 27 |
| 29 #ifdef NSS_DISABLE_LIBPKIX | 28 #ifdef NSS_DISABLE_LIBPKIX |
| 30 SECStatus | 29 SECStatus |
| 31 cert_VerifyCertChainPkix( | 30 cert_VerifyCertChainPkix( |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 /* | 69 /* |
| 71 * Check the validity times of a certificate | 70 * Check the validity times of a certificate |
| 72 */ | 71 */ |
| 73 SECStatus | 72 SECStatus |
| 74 CERT_CertTimesValid(CERTCertificate *c) | 73 CERT_CertTimesValid(CERTCertificate *c) |
| 75 { | 74 { |
| 76 SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE); | 75 SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE); |
| 77 return (valid == secCertTimeValid) ? SECSuccess : SECFailure; | 76 return (valid == secCertTimeValid) ? SECSuccess : SECFailure; |
| 78 } | 77 } |
| 79 | 78 |
| 80 SECStatus checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicK
ey *key) | 79 SECStatus |
| 80 checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key) |
| 81 { | 81 { |
| 82 SECStatus rv; | 82 SECStatus rv; |
| 83 SECOidTag sigAlg; | 83 SECOidTag sigAlg; |
| 84 SECOidTag curve; | 84 SECOidTag curve; |
| 85 PRUint32 policyFlags = 0; | 85 PRUint32 policyFlags = 0; |
| 86 PRInt32 minLen, len; | 86 PRInt32 minLen, len; |
| 87 | 87 |
| 88 sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm); | 88 sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm); |
| 89 | 89 |
| 90 switch(sigAlg) { | 90 switch (sigAlg) { |
| 91 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: | 91 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: |
| 92 » case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: | 92 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: |
| 93 » case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: | 93 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: |
| 94 » case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: | 94 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: |
| 95 » case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: | 95 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: |
| 96 » if (key->keyType != ecKey) { | 96 if (key->keyType != ecKey) { |
| 97 » » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 97 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
| 98 » » return SECFailure; | 98 return SECFailure; |
| 99 » } | 99 } |
| 100 | 100 |
| 101 curve = SECKEY_GetECCOid(&key->u.ec.DEREncodedParams); | 101 curve = SECKEY_GetECCOid(&key->u.ec.DEREncodedParams); |
| 102 » if (curve != 0) { | 102 if (curve != 0) { |
| 103 » if (NSS_GetAlgorithmPolicy(curve, &policyFlags) == SECFailure || | 103 if (NSS_GetAlgorithmPolicy(curve, &policyFlags) == SECFailure || |
| 104 » !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { | 104 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { |
| 105 » PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); | 105 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); |
| 106 » » return SECFailure; | 106 return SECFailure; |
| 107 » » } else { | 107 } else { |
| 108 » » return SECSuccess; | 108 return SECSuccess; |
| 109 } | 109 } |
| 110 } else { | 110 } else { |
| 111 » » PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); | 111 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); |
| 112 » » return SECFailure; | 112 return SECFailure; |
| 113 » } | 113 } |
| 114 return SECSuccess; | 114 return SECSuccess; |
| 115 » case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: | 115 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: |
| 116 » case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: | 116 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: |
| 117 » case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: | 117 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: |
| 118 » case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: | 118 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: |
| 119 » case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: | 119 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: |
| 120 » case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: | 120 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: |
| 121 » case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: | 121 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: |
| 122 » case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE: | 122 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE: |
| 123 » if (key->keyType != rsaKey && key->keyType != rsaPssKey) { | 123 if (key->keyType != rsaKey && key->keyType != rsaPssKey) { |
| 124 » » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 124 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
| 125 » » return SECFailure; | 125 return SECFailure; |
| 126 » } | 126 } |
| 127 | 127 |
| 128 len = 8 * key->u.rsa.modulus.len; | 128 len = 8 * key->u.rsa.modulus.len; |
| 129 | 129 |
| 130 rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minLen); | 130 rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minLen); |
| 131 if (rv != SECSuccess) { | 131 if (rv != SECSuccess) { |
| 132 return SECFailure; | 132 return SECFailure; |
| 133 » } | 133 } |
| 134 | 134 |
| 135 if (len < minLen) { | 135 if (len < minLen) { |
| 136 return SECFailure; | 136 return SECFailure; |
| 137 » } | 137 } |
| 138 | 138 |
| 139 return SECSuccess; | 139 return SECSuccess; |
| 140 » case SEC_OID_ANSIX9_DSA_SIGNATURE: | 140 case SEC_OID_ANSIX9_DSA_SIGNATURE: |
| 141 » case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: | 141 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: |
| 142 » case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: | 142 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: |
| 143 » case SEC_OID_SDN702_DSA_SIGNATURE: | 143 case SEC_OID_SDN702_DSA_SIGNATURE: |
| 144 » case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST: | 144 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST: |
| 145 » case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST: | 145 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST: |
| 146 » if (key->keyType != dsaKey) { | 146 if (key->keyType != dsaKey) { |
| 147 » » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 147 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
| 148 » » return SECFailure; | 148 return SECFailure; |
| 149 » } | 149 } |
| 150 | 150 |
| 151 len = 8 * key->u.dsa.params.prime.len; | 151 len = 8 * key->u.dsa.params.prime.len; |
| 152 | 152 |
| 153 rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minLen); | 153 rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minLen); |
| 154 if (rv != SECSuccess) { | 154 if (rv != SECSuccess) { |
| 155 return SECFailure; | 155 return SECFailure; |
| 156 » } | 156 } |
| 157 | 157 |
| 158 if (len < minLen) { | 158 if (len < minLen) { |
| 159 return SECFailure; | 159 return SECFailure; |
| 160 » } | 160 } |
| 161 | 161 |
| 162 return SECSuccess; | 162 return SECSuccess; |
| 163 » default: | 163 default: |
| 164 » return SECSuccess; | 164 return SECSuccess; |
| 165 } | 165 } |
| 166 } | 166 } |
| 167 | 167 |
| 168 /* | 168 /* |
| 169 * verify the signature of a signed data object with the given DER publickey | 169 * verify the signature of a signed data object with the given DER publickey |
| 170 */ | 170 */ |
| 171 SECStatus | 171 SECStatus |
| 172 CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd, | 172 CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd, |
| 173 SECKEYPublicKey *pubKey, | 173 SECKEYPublicKey *pubKey, |
| 174 » » void *wincx) | 174 void *wincx) |
| 175 { | 175 { |
| 176 SECStatus rv; | 176 SECStatus rv; |
| 177 SECItem sig; | 177 SECItem sig; |
| 178 SECOidTag hashAlg = SEC_OID_UNKNOWN; | 178 SECOidTag hashAlg = SEC_OID_UNKNOWN; |
| 179 | 179 |
| 180 if ( !pubKey || !sd ) { | 180 if (!pubKey || !sd) { |
| 181 » PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | 181 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
| 182 » return SECFailure; | 182 return SECFailure; |
| 183 } | 183 } |
| 184 /* check the signature */ | 184 /* check the signature */ |
| 185 sig = sd->signature; | 185 sig = sd->signature; |
| 186 /* convert sig->len from bit counts to byte count. */ | 186 /* convert sig->len from bit counts to byte count. */ |
| 187 DER_ConvertBitString(&sig); | 187 DER_ConvertBitString(&sig); |
| 188 | 188 |
| 189 rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey, | 189 rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey, |
| 190 » » » &sig, &sd->signatureAlgorithm, &hashAlg, wincx); | 190 &sig, &sd->signatureAlgorithm, &hashAlg,
wincx); |
| 191 if (rv == SECSuccess) { | 191 if (rv == SECSuccess) { |
| 192 /* Are we honoring signatures for this algorithm? */ | 192 /* Are we honoring signatures for this algorithm? */ |
| 193 » PRUint32 policyFlags = 0; | 193 PRUint32 policyFlags = 0; |
| 194 » rv = checkKeyParams(&sd->signatureAlgorithm, pubKey); | 194 rv = checkKeyParams(&sd->signatureAlgorithm, pubKey); |
| 195 » if (rv != SECSuccess) { | 195 if (rv != SECSuccess) { |
| 196 » PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); | 196 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); |
| 197 » return SECFailure; | 197 return SECFailure; |
| 198 » } | 198 } |
| 199 | 199 |
| 200 » rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags); | 200 rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags); |
| 201 » if (rv == SECSuccess && | 201 if (rv == SECSuccess && |
| 202 » !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { | 202 !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { |
| 203 » PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); | 203 PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); |
| 204 » return SECFailure; | 204 return SECFailure; |
| 205 » } | 205 } |
| 206 } | 206 } |
| 207 return rv; | 207 return rv; |
| 208 } | 208 } |
| 209 | 209 |
| 210 /* | 210 /* |
| 211 * verify the signature of a signed data object with the given DER publickey | 211 * verify the signature of a signed data object with the given DER publickey |
| 212 */ | 212 */ |
| 213 SECStatus | 213 SECStatus |
| 214 CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd, | 214 CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd, |
| 215 CERTSubjectPublicKeyInfo *pubKeyInfo, | 215 CERTSubjectPublicKeyInfo *pubKeyInfo, |
| 216 » » void *wincx) | 216 void *wincx) |
| 217 { | 217 { |
| 218 SECKEYPublicKey *pubKey; | 218 SECKEYPublicKey *pubKey; |
| 219 SECStatus rv»» = SECFailure; | 219 SECStatus rv = SECFailure; |
| 220 | 220 |
| 221 /* get cert's public key */ | 221 /* get cert's public key */ |
| 222 pubKey = SECKEY_ExtractPublicKey(pubKeyInfo); | 222 pubKey = SECKEY_ExtractPublicKey(pubKeyInfo); |
| 223 if (pubKey) { | 223 if (pubKey) { |
| 224 » rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); | 224 rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); |
| 225 » SECKEY_DestroyPublicKey(pubKey); | 225 SECKEY_DestroyPublicKey(pubKey); |
| 226 } | 226 } |
| 227 return rv; | 227 return rv; |
| 228 } | 228 } |
| 229 | 229 |
| 230 /* | 230 /* |
| 231 * verify the signature of a signed data object with the given certificate | 231 * verify the signature of a signed data object with the given certificate |
| 232 */ | 232 */ |
| 233 SECStatus | 233 SECStatus |
| 234 CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert, | 234 CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert, |
| 235 » » PRTime t, void *wincx) | 235 PRTime t, void *wincx) |
| 236 { | 236 { |
| 237 SECKEYPublicKey *pubKey = 0; | 237 SECKEYPublicKey *pubKey = 0; |
| 238 SECStatus rv = SECFailure; | 238 SECStatus rv = SECFailure; |
| 239 SECCertTimeValidity validity; | 239 SECCertTimeValidity validity; |
| 240 | 240 |
| 241 /* check the certificate's validity */ | 241 /* check the certificate's validity */ |
| 242 validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE); | 242 validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE); |
| 243 if ( validity != secCertTimeValid ) { | 243 if (validity != secCertTimeValid) { |
| 244 » return rv; | 244 return rv; |
| 245 } | 245 } |
| 246 | 246 |
| 247 /* get cert's public key */ | 247 /* get cert's public key */ |
| 248 pubKey = CERT_ExtractPublicKey(cert); | 248 pubKey = CERT_ExtractPublicKey(cert); |
| 249 if (pubKey) { | 249 if (pubKey) { |
| 250 » rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); | 250 rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx); |
| 251 » SECKEY_DestroyPublicKey(pubKey); | 251 SECKEY_DestroyPublicKey(pubKey); |
| 252 } | 252 } |
| 253 return rv; | 253 return rv; |
| 254 } | 254 } |
| 255 | 255 |
| 256 | |
| 257 SECStatus | 256 SECStatus |
| 258 SEC_CheckCRL(CERTCertDBHandle *handle,CERTCertificate *cert, | 257 SEC_CheckCRL(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 259 » CERTCertificate *caCert, PRTime t, void * wincx) | 258 CERTCertificate *caCert, PRTime t, void *wincx) |
| 260 { | 259 { |
| 261 return CERT_CheckCRL(cert, caCert, NULL, t, wincx); | 260 return CERT_CheckCRL(cert, caCert, NULL, t, wincx); |
| 262 } | 261 } |
| 263 | 262 |
| 264 /* | 263 /* |
| 265 * Find the issuer of a cert. Use the authorityKeyID if it exists. | 264 * Find the issuer of a cert. Use the authorityKeyID if it exists. |
| 266 */ | 265 */ |
| 267 CERTCertificate * | 266 CERTCertificate * |
| 268 CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage) | 267 CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage) |
| 269 { | 268 { |
| 270 NSSCertificate *me; | 269 NSSCertificate *me; |
| 271 NSSTime *nssTime; | 270 NSSTime *nssTime; |
| 272 NSSTrustDomain *td; | 271 NSSTrustDomain *td; |
| 273 NSSCryptoContext *cc; | 272 NSSCryptoContext *cc; |
| 274 NSSCertificate *chain[3]; | 273 NSSCertificate *chain[3]; |
| 275 NSSUsage nssUsage; | 274 NSSUsage nssUsage; |
| 276 PRStatus status; | 275 PRStatus status; |
| 277 | 276 |
| 278 me = STAN_GetNSSCertificate(cert); | 277 me = STAN_GetNSSCertificate(cert); |
| 279 if (!me) { | 278 if (!me) { |
| 280 PORT_SetError(SEC_ERROR_NO_MEMORY); | 279 PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 281 » return NULL; | 280 return NULL; |
| 282 } | 281 } |
| 283 nssTime = NSSTime_SetPRTime(NULL, validTime); | 282 nssTime = NSSTime_SetPRTime(NULL, validTime); |
| 284 nssUsage.anyUsage = PR_FALSE; | 283 nssUsage.anyUsage = PR_FALSE; |
| 285 nssUsage.nss3usage = usage; | 284 nssUsage.nss3usage = usage; |
| 286 nssUsage.nss3lookingForCA = PR_TRUE; | 285 nssUsage.nss3lookingForCA = PR_TRUE; |
| 287 memset(chain, 0, 3*sizeof(NSSCertificate *)); | 286 memset(chain, 0, 3 * sizeof(NSSCertificate *)); |
| 288 td = STAN_GetDefaultTrustDomain(); | 287 td = STAN_GetDefaultTrustDomain(); |
| 289 cc = STAN_GetDefaultCryptoContext(); | 288 cc = STAN_GetDefaultCryptoContext(); |
| 290 (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL, | 289 (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL, |
| 291 chain, 2, NULL, &status, td, cc); | 290 chain, 2, NULL, &status, td, cc); |
| 292 nss_ZFreeIf(nssTime); | 291 nss_ZFreeIf(nssTime); |
| 293 if (status == PR_SUCCESS) { | 292 if (status == PR_SUCCESS) { |
| 294 » PORT_Assert(me == chain[0]); | 293 PORT_Assert(me == chain[0]); |
| 295 » /* if it's a root, the chain will only have one cert */ | 294 /* if it's a root, the chain will only have one cert */ |
| 296 » if (!chain[1]) { | 295 if (!chain[1]) { |
| 297 » /* already has a reference from the call to BuildChain */ | 296 /* already has a reference from the call to BuildChain */ |
| 298 » return cert; | 297 return cert; |
| 299 » } | 298 } |
| 300 » NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */ | 299 NSSCertificate_Destroy(chain[0]); /* the first cert in the chain
*/ |
| 301 » return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */ | 300 return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */ |
| 302 } | 301 } |
| 303 if (chain[0]) { | 302 if (chain[0]) { |
| 304 » PORT_Assert(me == chain[0]); | 303 PORT_Assert(me == chain[0]); |
| 305 » NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */ | 304 NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */ |
| 306 } | 305 } |
| 307 PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER); | 306 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
| 308 return NULL; | 307 return NULL; |
| 309 } | 308 } |
| 310 | 309 |
| 311 /* | 310 /* |
| 312 * return required trust flags for various cert usages for CAs | 311 * return required trust flags for various cert usages for CAs |
| 313 */ | 312 */ |
| 314 SECStatus | 313 SECStatus |
| 315 CERT_TrustFlagsForCACertUsage(SECCertUsage usage, | 314 CERT_TrustFlagsForCACertUsage(SECCertUsage usage, |
| 316 » » » unsigned int *retFlags, | 315 unsigned int *retFlags, |
| 317 » » » SECTrustType *retTrustType) | 316 SECTrustType *retTrustType) |
| 318 { | 317 { |
| 319 unsigned int requiredFlags; | 318 unsigned int requiredFlags; |
| 320 SECTrustType trustType; | 319 SECTrustType trustType; |
| 321 | 320 |
| 322 switch ( usage ) { | 321 switch (usage) { |
| 323 case certUsageSSLClient: | 322 case certUsageSSLClient: |
| 324 » requiredFlags = CERTDB_TRUSTED_CLIENT_CA; | 323 requiredFlags = CERTDB_TRUSTED_CLIENT_CA; |
| 325 » trustType = trustSSL; | 324 trustType = trustSSL; |
| 326 break; | 325 break; |
| 327 case certUsageSSLServer: | 326 case certUsageSSLServer: |
| 328 case certUsageSSLCA: | 327 case certUsageSSLCA: |
| 329 » requiredFlags = CERTDB_TRUSTED_CA; | 328 requiredFlags = CERTDB_TRUSTED_CA; |
| 330 » trustType = trustSSL; | 329 trustType = trustSSL; |
| 331 break; | 330 break; |
| 332 case certUsageSSLServerWithStepUp: | 331 case certUsageSSLServerWithStepUp: |
| 333 » requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA; | 332 requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA; |
| 334 » trustType = trustSSL; | 333 trustType = trustSSL; |
| 335 break; | 334 break; |
| 336 case certUsageEmailSigner: | 335 case certUsageEmailSigner: |
| 337 case certUsageEmailRecipient: | 336 case certUsageEmailRecipient: |
| 338 » requiredFlags = CERTDB_TRUSTED_CA; | 337 requiredFlags = CERTDB_TRUSTED_CA; |
| 339 » trustType = trustEmail; | 338 trustType = trustEmail; |
| 340 » break; | 339 break; |
| 341 case certUsageObjectSigner: | 340 case certUsageObjectSigner: |
| 342 » requiredFlags = CERTDB_TRUSTED_CA; | 341 requiredFlags = CERTDB_TRUSTED_CA; |
| 343 » trustType = trustObjectSigning; | 342 trustType = trustObjectSigning; |
| 344 » break; | 343 break; |
| 345 case certUsageVerifyCA: | 344 case certUsageVerifyCA: |
| 346 case certUsageAnyCA: | 345 case certUsageAnyCA: |
| 347 case certUsageStatusResponder: | 346 case certUsageStatusResponder: |
| 348 » requiredFlags = CERTDB_TRUSTED_CA; | 347 requiredFlags = CERTDB_TRUSTED_CA; |
| 349 » trustType = trustTypeNone; | 348 trustType = trustTypeNone; |
| 350 » break; | 349 break; |
| 351 default: | 350 default: |
| 352 » PORT_Assert(0); | 351 PORT_Assert(0); |
| 353 » goto loser; | 352 goto loser; |
| 354 } | 353 } |
| 355 if ( retFlags != NULL ) { | 354 if (retFlags != NULL) { |
| 356 » *retFlags = requiredFlags; | 355 *retFlags = requiredFlags; |
| 357 } | 356 } |
| 358 if ( retTrustType != NULL ) { | 357 if (retTrustType != NULL) { |
| 359 » *retTrustType = trustType; | 358 *retTrustType = trustType; |
| 360 } | 359 } |
| 361 | 360 |
| 362 return(SECSuccess); | 361 return (SECSuccess); |
| 363 loser: | 362 loser: |
| 364 return(SECFailure); | 363 return (SECFailure); |
| 365 } | 364 } |
| 366 | 365 |
| 367 void | 366 void |
| 368 cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error, | 367 cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error, |
| 369 » unsigned int depth, void *arg) | 368 unsigned int depth, void *arg) |
| 370 { | 369 { |
| 371 CERTVerifyLogNode *node, *tnode; | 370 CERTVerifyLogNode *node, *tnode; |
| 372 | 371 |
| 373 PORT_Assert(log != NULL); | 372 PORT_Assert(log != NULL); |
| 374 | 373 |
| 375 node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena, | 374 node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena, |
| 376 » » » » » » sizeof(CERTVerifyLogNode)); | 375 sizeof(CERTVerifyLogNode)); |
| 377 if ( node != NULL ) { | 376 if (node != NULL) { |
| 378 » node->cert = CERT_DupCertificate(cert); | 377 node->cert = CERT_DupCertificate(cert); |
| 379 » node->error = error; | 378 node->error = error; |
| 380 » node->depth = depth; | 379 node->depth = depth; |
| 381 » node->arg = arg; | 380 node->arg = arg; |
| 382 » | |
| 383 » if ( log->tail == NULL ) { | |
| 384 » /* empty list */ | |
| 385 » log->head = log->tail = node; | |
| 386 » node->prev = NULL; | |
| 387 » node->next = NULL; | |
| 388 » } else if ( depth >= log->tail->depth ) { | |
| 389 » /* add to tail */ | |
| 390 » node->prev = log->tail; | |
| 391 » log->tail->next = node; | |
| 392 » log->tail = node; | |
| 393 » node->next = NULL; | |
| 394 » } else if ( depth < log->head->depth ) { | |
| 395 » /* add at head */ | |
| 396 » node->prev = NULL; | |
| 397 » node->next = log->head; | |
| 398 » log->head->prev = node; | |
| 399 » log->head = node; | |
| 400 » } else { | |
| 401 » /* add in middle */ | |
| 402 » tnode = log->tail; | |
| 403 » while ( tnode != NULL ) { | |
| 404 » » if ( depth >= tnode->depth ) { | |
| 405 » » /* insert after tnode */ | |
| 406 » » node->prev = tnode; | |
| 407 » » node->next = tnode->next; | |
| 408 » » tnode->next->prev = node; | |
| 409 » » tnode->next = node; | |
| 410 » » break; | |
| 411 » » } | |
| 412 | 381 |
| 413 » » tnode = tnode->prev; | 382 if (log->tail == NULL) { |
| 414 » } | 383 /* empty list */ |
| 415 » } | 384 log->head = log->tail = node; |
| 385 node->prev = NULL; |
| 386 node->next = NULL; |
| 387 } else if (depth >= log->tail->depth) { |
| 388 /* add to tail */ |
| 389 node->prev = log->tail; |
| 390 log->tail->next = node; |
| 391 log->tail = node; |
| 392 node->next = NULL; |
| 393 } else if (depth < log->head->depth) { |
| 394 /* add at head */ |
| 395 node->prev = NULL; |
| 396 node->next = log->head; |
| 397 log->head->prev = node; |
| 398 log->head = node; |
| 399 } else { |
| 400 /* add in middle */ |
| 401 tnode = log->tail; |
| 402 while (tnode != NULL) { |
| 403 if (depth >= tnode->depth) { |
| 404 /* insert after tnode */ |
| 405 node->prev = tnode; |
| 406 node->next = tnode->next; |
| 407 tnode->next->prev = node; |
| 408 tnode->next = node; |
| 409 break; |
| 410 } |
| 416 | 411 |
| 417 » log->count++; | 412 tnode = tnode->prev; |
| 413 } |
| 414 } |
| 415 |
| 416 log->count++; |
| 418 } | 417 } |
| 419 return; | 418 return; |
| 420 } | 419 } |
| 421 | 420 |
| 422 #define EXIT_IF_NOT_LOGGING(log) \ | 421 #define EXIT_IF_NOT_LOGGING(log) \ |
| 423 if ( log == NULL ) { \ | 422 if (log == NULL) { \ |
| 424 » goto loser; \ | 423 goto loser; \ |
| 425 } | 424 } |
| 426 | 425 |
| 427 #define LOG_ERROR_OR_EXIT(log,cert,depth,arg) \ | 426 #define LOG_ERROR_OR_EXIT(log, cert, depth, arg) \ |
| 428 if ( log != NULL ) { \ | 427 if (log != NULL) { \ |
| 429 » cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ | 428 cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ |
| 430 » » » (void *)(PRWord)arg); \ | 429 (void *)(PRWord)arg); \ |
| 431 } else { \ | 430 } else { \ |
| 432 » goto loser; \ | 431 goto loser; \ |
| 433 } | 432 } |
| 434 | 433 |
| 435 #define LOG_ERROR(log,cert,depth,arg) \ | 434 #define LOG_ERROR(log, cert, depth, arg) \ |
| 436 if ( log != NULL ) { \ | 435 if (log != NULL) { \ |
| 437 » cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ | 436 cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \ |
| 438 » » » (void *)(PRWord)arg); \ | 437 (void *)(PRWord)arg); \ |
| 439 } | 438 } |
| 440 | 439 |
| 441 static SECStatus | 440 static SECStatus |
| 442 cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert, | 441 cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 443 » » PRBool checkSig, PRBool* sigerror, | 442 PRBool checkSig, PRBool *sigerror, |
| 444 SECCertUsage certUsage, PRTime t, void *wincx, | 443 SECCertUsage certUsage, PRTime t, void *wincx, |
| 445 CERTVerifyLog *log, PRBool* revoked) | 444 CERTVerifyLog *log, PRBool *revoked) |
| 446 { | 445 { |
| 447 SECTrustType trustType; | 446 SECTrustType trustType; |
| 448 CERTBasicConstraints basicConstraint; | 447 CERTBasicConstraints basicConstraint; |
| 449 CERTCertificate *issuerCert = NULL; | 448 CERTCertificate *issuerCert = NULL; |
| 450 CERTCertificate *subjectCert = NULL; | 449 CERTCertificate *subjectCert = NULL; |
| 451 CERTCertificate *badCert = NULL; | 450 CERTCertificate *badCert = NULL; |
| 452 PRBool isca; | 451 PRBool isca; |
| 453 SECStatus rv; | 452 SECStatus rv; |
| 454 SECStatus rvFinal = SECSuccess; | 453 SECStatus rvFinal = SECSuccess; |
| 455 int count; | 454 int count; |
| 456 int currentPathLen = 0; | 455 int currentPathLen = 0; |
| 457 int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; | 456 int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; |
| 458 unsigned int caCertType; | 457 unsigned int caCertType; |
| 459 unsigned int requiredCAKeyUsage; | 458 unsigned int requiredCAKeyUsage; |
| 460 unsigned int requiredFlags; | 459 unsigned int requiredFlags; |
| 461 PLArenaPool *arena = NULL; | 460 PLArenaPool *arena = NULL; |
| 462 CERTGeneralName *namesList = NULL; | 461 CERTGeneralName *namesList = NULL; |
| 463 CERTCertificate **certsList = NULL; | 462 CERTCertificate **certsList = NULL; |
| 464 int certsListLen = 16; | 463 int certsListLen = 16; |
| 465 int namesCount = 0; | 464 int namesCount = 0; |
| 466 PRBool subjectCertIsSelfIssued; | 465 PRBool subjectCertIsSelfIssued; |
| 467 CERTCertTrust issuerTrust; | 466 CERTCertTrust issuerTrust; |
| 468 | 467 |
| 469 if (revoked) { | 468 if (revoked) { |
| 470 *revoked = PR_FALSE; | 469 *revoked = PR_FALSE; |
| 471 } | 470 } |
| 472 | 471 |
| 473 if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, | 472 if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, |
| 474 » » » » » &requiredCAKeyUsage, | 473 &requiredCAKeyUsage, |
| 475 » » » » » &caCertType) | 474 &caCertType) != |
| 476 » != SECSuccess ) { | 475 SECSuccess) { |
| 477 » PORT_Assert(0); | 476 PORT_Assert(0); |
| 478 » EXIT_IF_NOT_LOGGING(log); | 477 EXIT_IF_NOT_LOGGING(log); |
| 479 » requiredCAKeyUsage = 0; | 478 requiredCAKeyUsage = 0; |
| 480 » caCertType = 0; | 479 caCertType = 0; |
| 481 } | 480 } |
| 482 | 481 |
| 483 switch ( certUsage ) { | 482 switch (certUsage) { |
| 484 case certUsageSSLClient: | 483 case certUsageSSLClient: |
| 485 case certUsageSSLServer: | 484 case certUsageSSLServer: |
| 486 case certUsageSSLCA: | 485 case certUsageSSLCA: |
| 487 case certUsageSSLServerWithStepUp: | 486 case certUsageSSLServerWithStepUp: |
| 488 case certUsageEmailSigner: | 487 case certUsageEmailSigner: |
| 489 case certUsageEmailRecipient: | 488 case certUsageEmailRecipient: |
| 490 case certUsageObjectSigner: | 489 case certUsageObjectSigner: |
| 491 case certUsageVerifyCA: | 490 case certUsageVerifyCA: |
| 492 case certUsageAnyCA: | 491 case certUsageAnyCA: |
| 493 case certUsageStatusResponder: | 492 case certUsageStatusResponder: |
| 494 » if ( CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, | 493 if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, |
| 495 » » » » » &trustType) != SECSuccess ) { | 494 &trustType) != SECSuccess) { |
| 496 » PORT_Assert(0); | 495 PORT_Assert(0); |
| 497 » EXIT_IF_NOT_LOGGING(log); | 496 EXIT_IF_NOT_LOGGING(log); |
| 498 » /* XXX continuing with requiredFlags = 0 seems wrong. It'll | 497 /* XXX continuing with requiredFlags = 0 seems wrong. It'll |
| 499 » * cause the following test to be true incorrectly: | 498 * cause the following test to be true incorrectly: |
| 500 » * flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType); | 499 * flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType); |
| 501 » * if (( flags & requiredFlags ) == requiredFlags) { | 500 * if (( flags & requiredFlags ) == requiredFlags) { |
| 502 » * rv = rvFinal; | 501 * rv = rvFinal; |
| 503 » * goto done; | 502 * goto done; |
| 504 » * } | 503 * } |
| 505 » * There are three other instances of this problem. | 504 * There are three other instances of this problem. |
| 506 » */ | 505 */ |
| 507 » requiredFlags = 0; | 506 requiredFlags = 0; |
| 508 » trustType = trustSSL; | 507 trustType = trustSSL; |
| 509 » } | 508 } |
| 510 » break; | 509 break; |
| 511 default: | 510 default: |
| 512 » PORT_Assert(0); | 511 PORT_Assert(0); |
| 513 » EXIT_IF_NOT_LOGGING(log); | 512 EXIT_IF_NOT_LOGGING(log); |
| 514 » requiredFlags = 0; | 513 requiredFlags = 0; |
| 515 » trustType = trustSSL;/* This used to be 0, but we need something | 514 trustType = trustSSL; /* This used to be 0, but we need something |
| 516 » » » * that matches the enumeration type. | 515 * that matches the enumeration type. |
| 517 » » » */ | 516 */ |
| 518 » caCertType = 0; | 517 caCertType = 0; |
| 519 } | 518 } |
| 520 | 519 |
| 521 subjectCert = CERT_DupCertificate(cert); | 520 subjectCert = CERT_DupCertificate(cert); |
| 522 if ( subjectCert == NULL ) { | 521 if (subjectCert == NULL) { |
| 523 » goto loser; | 522 goto loser; |
| 524 } | 523 } |
| 525 | 524 |
| 526 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 525 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 527 if (arena == NULL) { | 526 if (arena == NULL) { |
| 528 » goto loser; | 527 goto loser; |
| 529 } | 528 } |
| 530 | 529 |
| 531 certsList = PORT_ZNewArray(CERTCertificate *, certsListLen); | 530 certsList = PORT_ZNewArray(CERTCertificate *, certsListLen); |
| 532 if (certsList == NULL) | 531 if (certsList == NULL) |
| 533 » goto loser; | 532 goto loser; |
| 534 | 533 |
| 535 /* RFC 3280 says that the name constraints will apply to the names | 534 /* RFC 3280 says that the name constraints will apply to the names |
| 536 ** in the leaf (EE) cert, whether it is self issued or not, so | 535 ** in the leaf (EE) cert, whether it is self issued or not, so |
| 537 ** we pretend that it is not. | 536 ** we pretend that it is not. |
| 538 */ | 537 */ |
| 539 subjectCertIsSelfIssued = PR_FALSE; | 538 subjectCertIsSelfIssued = PR_FALSE; |
| 540 for ( count = 0; count < CERT_MAX_CERT_CHAIN; count++ ) { | 539 for (count = 0; count < CERT_MAX_CERT_CHAIN; count++) { |
| 541 » PRBool validCAOverride = PR_FALSE; | 540 PRBool validCAOverride = PR_FALSE; |
| 542 | 541 |
| 543 » /* Construct a list of names for the current and all previous | 542 /* Construct a list of names for the current and all previous |
| 544 » * certifcates (except leaf (EE) certs, root CAs, and self-issued | 543 * certifcates (except leaf (EE) certs, root CAs, and self-issued |
| 545 » * intermediate CAs) to be verified against the name constraints | 544 * intermediate CAs) to be verified against the name constraints |
| 546 » * extension of the issuer certificate. | 545 * extension of the issuer certificate. |
| 547 » */ | 546 */ |
| 548 » if (subjectCertIsSelfIssued == PR_FALSE) { | 547 if (subjectCertIsSelfIssued == PR_FALSE) { |
| 549 » CERTGeneralName *subjectNameList; | 548 CERTGeneralName *subjectNameList; |
| 550 » int subjectNameListLen; | 549 int subjectNameListLen; |
| 551 » int i; | 550 int i; |
| 552 » PRBool getSubjectCN = (!count && certUsage == certUsageSSLServer); | 551 PRBool getSubjectCN = (!count && certUsage == certUsageSSLServer); |
| 553 » subjectNameList = | 552 subjectNameList = |
| 554 » » CERT_GetConstrainedCertificateNames(subjectCert, arena, | 553 CERT_GetConstrainedCertificateNames(subjectCert, arena, |
| 555 » » getSubjectCN); | 554 getSubjectCN); |
| 556 » if (!subjectNameList) | 555 if (!subjectNameList) |
| 557 » » goto loser; | 556 goto loser; |
| 558 » subjectNameListLen = CERT_GetNamesLength(subjectNameList); | 557 subjectNameListLen = CERT_GetNamesLength(subjectNameList); |
| 559 » if (!subjectNameListLen) | 558 if (!subjectNameListLen) |
| 560 » » goto loser; | 559 goto loser; |
| 561 » if (certsListLen <= namesCount + subjectNameListLen) { | 560 if (certsListLen <= namesCount + subjectNameListLen) { |
| 562 » » CERTCertificate **tmpCertsList; | 561 CERTCertificate **tmpCertsList; |
| 563 » » certsListLen = (namesCount + subjectNameListLen) * 2; | 562 certsListLen = (namesCount + subjectNameListLen) * 2; |
| 564 » » tmpCertsList = | 563 tmpCertsList = |
| 565 » » (CERTCertificate **)PORT_Realloc(certsList, | 564 (CERTCertificate **)PORT_Realloc(certsList, |
| 566 » certsListLen * sizeof(CERTCertificate *)); | 565 certsListLen * |
| 567 » » if (tmpCertsList == NULL) { | 566 sizeof(CERTCertificate
*)); |
| 568 » » goto loser; | 567 if (tmpCertsList == NULL) { |
| 569 » » } | 568 goto loser; |
| 570 » » certsList = tmpCertsList; | 569 } |
| 571 » } | 570 certsList = tmpCertsList; |
| 572 » for (i = 0; i < subjectNameListLen; i++) { | 571 } |
| 573 » » certsList[namesCount + i] = subjectCert; | 572 for (i = 0; i < subjectNameListLen; i++) { |
| 574 » } | 573 certsList[namesCount + i] = subjectCert; |
| 575 » namesCount += subjectNameListLen; | 574 } |
| 576 » namesList = cert_CombineNamesLists(namesList, subjectNameList); | 575 namesCount += subjectNameListLen; |
| 577 » } | 576 namesList = cert_CombineNamesLists(namesList, subjectNameList); |
| 577 } |
| 578 | 578 |
| 579 /* check if the cert has an unsupported critical extension */ | 579 /* check if the cert has an unsupported critical extension */ |
| 580 » if ( subjectCert->options.bits.hasUnsupportedCriticalExt ) { | 580 if (subjectCert->options.bits.hasUnsupportedCriticalExt) { |
| 581 » PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); | 581 PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION); |
| 582 » LOG_ERROR_OR_EXIT(log,subjectCert,count,0); | 582 LOG_ERROR_OR_EXIT(log, subjectCert, count, 0); |
| 583 » } | 583 } |
| 584 | 584 |
| 585 » /* find the certificate of the issuer */ | 585 /* find the certificate of the issuer */ |
| 586 » issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage); | 586 issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage); |
| 587 » if ( ! issuerCert ) { | 587 if (!issuerCert) { |
| 588 » PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); | 588 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
| 589 » LOG_ERROR(log,subjectCert,count,0); | 589 LOG_ERROR(log, subjectCert, count, 0); |
| 590 » goto loser; | 590 goto loser; |
| 591 » } | 591 } |
| 592 | 592 |
| 593 » /* verify the signature on the cert */ | 593 /* verify the signature on the cert */ |
| 594 » if ( checkSig ) { | 594 if (checkSig) { |
| 595 » rv = CERT_VerifySignedData(&subjectCert->signatureWrap, | 595 rv = CERT_VerifySignedData(&subjectCert->signatureWrap, |
| 596 » » » » issuerCert, t, wincx); | 596 issuerCert, t, wincx); |
| 597 | 597 |
| 598 » if ( rv != SECSuccess ) { | 598 if (rv != SECSuccess) { |
| 599 if (sigerror) { | 599 if (sigerror) { |
| 600 *sigerror = PR_TRUE; | 600 *sigerror = PR_TRUE; |
| 601 } | 601 } |
| 602 » » if ( PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE ) { | 602 if (PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE) { |
| 603 » » PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE); | 603 PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE); |
| 604 » » LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0); | 604 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); |
| 605 » » } else { | 605 } else { |
| 606 » » if (PORT_GetError() != | 606 if (PORT_GetError() != |
| 607 » » » SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) { | 607 SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) { |
| 608 » » » PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | 608 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
| 609 » » } | 609 } |
| 610 » » LOG_ERROR_OR_EXIT(log,subjectCert,count,0); | 610 LOG_ERROR_OR_EXIT(log, subjectCert, count, 0); |
| 611 » » } | 611 } |
| 612 » } | 612 } |
| 613 » } | 613 } |
| 614 | 614 |
| 615 » /* If the basicConstraint extension is included in an immediate CA | 615 /* If the basicConstraint extension is included in an immediate CA |
| 616 » * certificate, make sure that the isCA flag is on. If the | 616 * certificate, make sure that the isCA flag is on. If the |
| 617 » * pathLenConstraint component exists, it must be greater than the | 617 * pathLenConstraint component exists, it must be greater than the |
| 618 » * number of CA certificates we have seen so far. If the extension | 618 * number of CA certificates we have seen so far. If the extension |
| 619 » * is omitted, we will assume that this is a CA certificate with | 619 * is omitted, we will assume that this is a CA certificate with |
| 620 » * an unlimited pathLenConstraint (since it already passes the | 620 * an unlimited pathLenConstraint (since it already passes the |
| 621 » * netscape-cert-type extension checking). | 621 * netscape-cert-type extension checking). |
| 622 » */ | 622 */ |
| 623 | 623 |
| 624 » rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint); | 624 rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint); |
| 625 » if ( rv != SECSuccess ) { | 625 if (rv != SECSuccess) { |
| 626 » if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { | 626 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { |
| 627 » » LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0); | 627 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); |
| 628 » } | 628 } |
| 629 » pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; | 629 pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT; |
| 630 » /* no basic constraints found, we aren't (yet) a CA. */ | 630 /* no basic constraints found, we aren't (yet) a CA. */ |
| 631 » isca = PR_FALSE; | 631 isca = PR_FALSE; |
| 632 » } else { | 632 } else { |
| 633 » if ( basicConstraint.isCA == PR_FALSE ) { | 633 if (basicConstraint.isCA == PR_FALSE) { |
| 634 » » PORT_SetError (SEC_ERROR_CA_CERT_INVALID); | 634 PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
| 635 » » LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0); | 635 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); |
| 636 » } | 636 } |
| 637 » pathLengthLimit = basicConstraint.pathLenConstraint; | 637 pathLengthLimit = basicConstraint.pathLenConstraint; |
| 638 » isca = PR_TRUE; | 638 isca = PR_TRUE; |
| 639 » } | 639 } |
| 640 » /* make sure that the path len constraint is properly set.*/ | 640 /* make sure that the path len constraint is properly set.*/ |
| 641 » if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) { | 641 if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) { |
| 642 » PORT_SetError (SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID); | 642 PORT_SetError(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID); |
| 643 » LOG_ERROR_OR_EXIT(log, issuerCert, count+1, pathLengthLimit); | 643 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, pathLengthLimit); |
| 644 » } | 644 } |
| 645 | 645 |
| 646 /* make sure that the entire chain is within the name space of the | 646 /* make sure that the entire chain is within the name space of the |
| 647 * current issuer certificate. | 647 * current issuer certificate. |
| 648 */ | 648 */ |
| 649 rv = CERT_CompareNameSpace(issuerCert, namesList, certsList, | 649 rv = CERT_CompareNameSpace(issuerCert, namesList, certsList, |
| 650 arena, &badCert); | 650 arena, &badCert); |
| 651 if (rv != SECSuccess || badCert != NULL) { | 651 if (rv != SECSuccess || badCert != NULL) { |
| 652 PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE); | 652 PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE); |
| 653 LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0); | 653 LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0); |
| 654 goto loser; | 654 goto loser; |
| 655 } | 655 } |
| 656 | 656 |
| 657 » /* XXX - the error logging may need to go down into CRL stuff at some | 657 /* XXX - the error logging may need to go down into CRL stuff at some |
| 658 » * point | 658 * point |
| 659 » */ | 659 */ |
| 660 » /* check revoked list (issuer) */ | 660 /* check revoked list (issuer) */ |
| 661 rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx); | 661 rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx); |
| 662 if (rv == SECFailure) { | 662 if (rv == SECFailure) { |
| 663 if (revoked) { | 663 if (revoked) { |
| 664 *revoked = PR_TRUE; | 664 *revoked = PR_TRUE; |
| 665 } | 665 } |
| 666 LOG_ERROR_OR_EXIT(log,subjectCert,count,0); | 666 LOG_ERROR_OR_EXIT(log, subjectCert, count, 0); |
| 667 } else if (rv == SECWouldBlock) { | 667 } else if (rv == SECWouldBlock) { |
| 668 /* We found something fishy, so we intend to issue an | 668 /* We found something fishy, so we intend to issue an |
| 669 * error to the user, but the user may wish to continue | 669 * error to the user, but the user may wish to continue |
| 670 * processing, in which case we better make sure nothing | 670 * processing, in which case we better make sure nothing |
| 671 * worse has happened... so keep cranking the loop */ | 671 * worse has happened... so keep cranking the loop */ |
| 672 rvFinal = SECFailure; | 672 rvFinal = SECFailure; |
| 673 if (revoked) { | 673 if (revoked) { |
| 674 *revoked = PR_TRUE; | 674 *revoked = PR_TRUE; |
| 675 } | 675 } |
| 676 LOG_ERROR(log,subjectCert,count,0); | 676 LOG_ERROR(log, subjectCert, count, 0); |
| 677 } | 677 } |
| 678 | 678 |
| 679 » if ( CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) { | 679 if (CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) { |
| 680 » /* we have some trust info, but this does NOT imply that this | 680 /* we have some trust info, but this does NOT imply that this |
| 681 » * cert is actually trusted for any purpose. The cert may be | 681 * cert is actually trusted for any purpose. The cert may be |
| 682 » * explicitly UNtrusted. We won't know until we examine the | 682 * explicitly UNtrusted. We won't know until we examine the |
| 683 » * trust bits. | 683 * trust bits. |
| 684 » */ | 684 */ |
| 685 » unsigned int flags; | 685 unsigned int flags; |
| 686 | 686 |
| 687 » if (certUsage != certUsageAnyCA && | 687 if (certUsage != certUsageAnyCA && |
| 688 » certUsage != certUsageStatusResponder) { | 688 certUsage != certUsageStatusResponder) { |
| 689 | 689 |
| 690 » /* | 690 /* |
| 691 » * XXX This choice of trustType seems arbitrary. | 691 * XXX This choice of trustType seems arbitrary. |
| 692 » */ | 692 */ |
| 693 » if ( certUsage == certUsageVerifyCA ) { | 693 if (certUsage == certUsageVerifyCA) { |
| 694 » if ( subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA ) { | 694 if (subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) { |
| 695 » trustType = trustEmail; | 695 trustType = trustEmail; |
| 696 » } else if ( subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA )
{ | 696 } else if (subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA) { |
| 697 » trustType = trustSSL; | 697 trustType = trustSSL; |
| 698 » } else { | 698 } else { |
| 699 » trustType = trustObjectSigning; | 699 trustType = trustObjectSigning; |
| 700 » } | 700 } |
| 701 » } | 701 } |
| 702 | 702 |
| 703 » flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); | 703 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); |
| 704 » if (( flags & requiredFlags ) == requiredFlags) { | 704 if ((flags & requiredFlags) == requiredFlags) { |
| 705 » /* we found a trusted one, so return */ | 705 /* we found a trusted one, so return */ |
| 706 » rv = rvFinal; | 706 rv = rvFinal; |
| 707 » goto done; | 707 goto done; |
| 708 » } | 708 } |
| 709 » if (flags & CERTDB_VALID_CA) { | 709 if (flags & CERTDB_VALID_CA) { |
| 710 » validCAOverride = PR_TRUE; | 710 validCAOverride = PR_TRUE; |
| 711 » } | 711 } |
| 712 » » /* is it explicitly distrusted? */ | 712 /* is it explicitly distrusted? */ |
| 713 » » if ((flags & CERTDB_TERMINAL_RECORD) && | 713 if ((flags & CERTDB_TERMINAL_RECORD) && |
| 714 » » » ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0)) { | 714 ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) { |
| 715 » » /* untrusted -- the cert is explicitly untrusted, not | 715 /* untrusted -- the cert is explicitly untrusted, not |
| 716 » » * just that it doesn't chain to a trusted cert */ | 716 * just that it doesn't chain to a trusted cert */ |
| 717 » » PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); | 717 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
| 718 » » LOG_ERROR_OR_EXIT(log,issuerCert,count+1,flags); | 718 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags); |
| 719 » » } | 719 } |
| 720 » } else { | 720 } else { |
| 721 /* Check if we have any valid trust when cheching for | 721 /* Check if we have any valid trust when cheching for |
| 722 * certUsageAnyCA or certUsageStatusResponder. */ | 722 * certUsageAnyCA or certUsageStatusResponder. */ |
| 723 for (trustType = trustSSL; trustType < trustTypeNone; | 723 for (trustType = trustSSL; trustType < trustTypeNone; |
| 724 trustType++) { | 724 trustType++) { |
| 725 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); | 725 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); |
| 726 if ((flags & requiredFlags) == requiredFlags) { | 726 if ((flags & requiredFlags) == requiredFlags) { |
| 727 » rv = rvFinal; | 727 rv = rvFinal; |
| 728 » goto done; | 728 goto done; |
| 729 } | 729 } |
| 730 if (flags & CERTDB_VALID_CA) | 730 if (flags & CERTDB_VALID_CA) |
| 731 validCAOverride = PR_TRUE; | 731 validCAOverride = PR_TRUE; |
| 732 } | 732 } |
| 733 » » /* We have 2 separate loops because we want any single trust | 733 /* We have 2 separate loops because we want any single trust |
| 734 » » * bit to allow this usage to return trusted. Only if none of | 734 * bit to allow this usage to return trusted. Only if none of |
| 735 » » * the trust bits are on do we check to see if the cert is | 735 * the trust bits are on do we check to see if the cert is |
| 736 » » * untrusted */ | 736 * untrusted */ |
| 737 for (trustType = trustSSL; trustType < trustTypeNone; | 737 for (trustType = trustSSL; trustType < trustTypeNone; |
| 738 trustType++) { | 738 trustType++) { |
| 739 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); | 739 flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType); |
| 740 » » /* is it explicitly distrusted? */ | 740 /* is it explicitly distrusted? */ |
| 741 » » if ((flags & CERTDB_TERMINAL_RECORD) && | 741 if ((flags & CERTDB_TERMINAL_RECORD) && |
| 742 » » » ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0)) { | 742 ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) { |
| 743 » » » /* untrusted -- the cert is explicitly untrusted, not | 743 /* untrusted -- the cert is explicitly untrusted, not |
| 744 » » » * just that it doesn't chain to a trusted cert */ | 744 * just that it doesn't chain to a trusted cert */ |
| 745 » » » PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); | 745 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
| 746 » » » LOG_ERROR_OR_EXIT(log,issuerCert,count+1,flags); | 746 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags); |
| 747 » » } | 747 } |
| 748 } | 748 } |
| 749 } | 749 } |
| 750 } | 750 } |
| 751 | 751 |
| 752 » if (!validCAOverride) { | 752 if (!validCAOverride) { |
| 753 » /* | 753 /* |
| 754 » * Make sure that if this is an intermediate CA in the chain that | 754 * Make sure that if this is an intermediate CA in the chain that |
| 755 » * it was given permission by its signer to be a CA. | 755 * it was given permission by its signer to be a CA. |
| 756 » */ | 756 */ |
| 757 » /* | 757 /* |
| 758 » * if basicConstraints says it is a ca, then we check the | 758 * if basicConstraints says it is a ca, then we check the |
| 759 » * nsCertType. If the nsCertType has any CA bits set, then | 759 * nsCertType. If the nsCertType has any CA bits set, then |
| 760 » * it must have the right one. | 760 * it must have the right one. |
| 761 » */ | 761 */ |
| 762 » if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) { | 762 if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) { |
| 763 » » isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALS
E; | 763 isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALS
E; |
| 764 » } | 764 } |
| 765 » | |
| 766 » if ( !isca ) { | |
| 767 » » PORT_SetError(SEC_ERROR_CA_CERT_INVALID); | |
| 768 » » LOG_ERROR_OR_EXIT(log,issuerCert,count+1,0); | |
| 769 » } | |
| 770 | 765 |
| 771 » /* make sure key usage allows cert signing */ | 766 if (!isca) { |
| 772 » if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess
) { | 767 PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
| 773 » » PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); | 768 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0); |
| 774 » » LOG_ERROR_OR_EXIT(log,issuerCert,count+1,requiredCAKeyUsage); | 769 } |
| 775 » } | |
| 776 » } | |
| 777 | 770 |
| 778 » /* make sure that the issuer is not self signed. If it is, then | 771 /* make sure key usage allows cert signing */ |
| 779 » * stop here to prevent looping. | 772 if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess
) { |
| 780 » */ | 773 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
| 781 » if (issuerCert->isRoot) { | 774 LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, requiredCAKeyUsage
); |
| 782 » PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); | 775 } |
| 783 » LOG_ERROR(log, issuerCert, count+1, 0); | 776 } |
| 784 » goto loser; | |
| 785 » } | |
| 786 » /* The issuer cert will be the subject cert in the next loop. | |
| 787 » * A cert is self-issued if its subject and issuer are equal and | |
| 788 » * both are of non-zero length. | |
| 789 » */ | |
| 790 » subjectCertIsSelfIssued = (PRBool) | |
| 791 » SECITEM_ItemsAreEqual(&issuerCert->derIssuer, | |
| 792 » » » » &issuerCert->derSubject) && | |
| 793 » issuerCert->derSubject.len > 0; | |
| 794 » if (subjectCertIsSelfIssued == PR_FALSE) { | |
| 795 » /* RFC 3280 says only non-self-issued intermediate CA certs | |
| 796 » * count in path length. | |
| 797 » */ | |
| 798 » ++currentPathLen; | |
| 799 » } | |
| 800 | 777 |
| 801 » CERT_DestroyCertificate(subjectCert); | 778 /* make sure that the issuer is not self signed. If it is, then |
| 802 » subjectCert = issuerCert; | 779 * stop here to prevent looping. |
| 803 » issuerCert = NULL; | 780 */ |
| 781 if (issuerCert->isRoot) { |
| 782 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
| 783 LOG_ERROR(log, issuerCert, count + 1, 0); |
| 784 goto loser; |
| 785 } |
| 786 /* The issuer cert will be the subject cert in the next loop. |
| 787 * A cert is self-issued if its subject and issuer are equal and |
| 788 * both are of non-zero length. |
| 789 */ |
| 790 subjectCertIsSelfIssued = (PRBool) |
| 791 SECITEM_ItemsAreEqual(&issuerCert->derIssu
er, |
| 792 &issuerCert->derSubj
ect) && |
| 793 issuerCert->derSubject.len > |
| 794 0; |
| 795 if (subjectCertIsSelfIssued == PR_FALSE) { |
| 796 /* RFC 3280 says only non-self-issued intermediate CA certs |
| 797 * count in path length. |
| 798 */ |
| 799 ++currentPathLen; |
| 800 } |
| 801 |
| 802 CERT_DestroyCertificate(subjectCert); |
| 803 subjectCert = issuerCert; |
| 804 issuerCert = NULL; |
| 804 } | 805 } |
| 805 | 806 |
| 806 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); | 807 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
| 807 LOG_ERROR(log,subjectCert,count,0); | 808 LOG_ERROR(log, subjectCert, count, 0); |
| 808 loser: | 809 loser: |
| 809 rv = SECFailure; | 810 rv = SECFailure; |
| 810 done: | 811 done: |
| 811 if (certsList != NULL) { | 812 if (certsList != NULL) { |
| 812 » PORT_Free(certsList); | 813 PORT_Free(certsList); |
| 813 } | 814 } |
| 814 if ( issuerCert ) { | 815 if (issuerCert) { |
| 815 » CERT_DestroyCertificate(issuerCert); | 816 CERT_DestroyCertificate(issuerCert); |
| 816 } | |
| 817 | |
| 818 if ( subjectCert ) { | |
| 819 » CERT_DestroyCertificate(subjectCert); | |
| 820 } | 817 } |
| 821 | 818 |
| 822 if ( arena != NULL ) { | 819 if (subjectCert) { |
| 823 » PORT_FreeArena(arena, PR_FALSE); | 820 CERT_DestroyCertificate(subjectCert); |
| 821 } |
| 822 |
| 823 if (arena != NULL) { |
| 824 PORT_FreeArena(arena, PR_FALSE); |
| 824 } | 825 } |
| 825 return rv; | 826 return rv; |
| 826 } | 827 } |
| 827 | 828 |
| 828 SECStatus | 829 SECStatus |
| 829 cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, | 830 cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 830 PRBool checkSig, PRBool* sigerror, | 831 PRBool checkSig, PRBool *sigerror, |
| 831 SECCertUsage certUsage, PRTime t, void *wincx, | 832 SECCertUsage certUsage, PRTime t, void *wincx, |
| 832 CERTVerifyLog *log, PRBool* revoked) | 833 CERTVerifyLog *log, PRBool *revoked) |
| 833 { | 834 { |
| 834 if (CERT_GetUsePKIXForValidation()) { | 835 if (CERT_GetUsePKIXForValidation()) { |
| 835 return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t, | 836 return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t, |
| 836 wincx, log, sigerror, revoked); | 837 wincx, log, sigerror, revoked); |
| 837 } | 838 } |
| 838 return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror, | 839 return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror, |
| 839 certUsage, t, wincx, log, revoked); | 840 certUsage, t, wincx, log, revoked); |
| 840 } | 841 } |
| 841 | 842 |
| 842 SECStatus | 843 SECStatus |
| 843 CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, | 844 CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 844 » » PRBool checkSig, SECCertUsage certUsage, PRTime t, | 845 PRBool checkSig, SECCertUsage certUsage, PRTime t, |
| 845 » » void *wincx, CERTVerifyLog *log) | 846 void *wincx, CERTVerifyLog *log) |
| 846 { | 847 { |
| 847 return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t, | 848 return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t, |
| 848 » » » wincx, log, NULL); | 849 wincx, log, NULL); |
| 849 } | 850 } |
| 850 | 851 |
| 851 /* | 852 /* |
| 852 * verify that a CA can sign a certificate with the requested usage. | 853 * verify that a CA can sign a certificate with the requested usage. |
| 853 */ | 854 */ |
| 854 SECStatus | 855 SECStatus |
| 855 CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert, | 856 CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 856 » » PRBool checkSig, SECCertUsage certUsage, PRTime t, | 857 PRBool checkSig, SECCertUsage certUsage, PRTime t, |
| 857 » » void *wincx, CERTVerifyLog *log) | 858 void *wincx, CERTVerifyLog *log) |
| 858 { | 859 { |
| 859 SECTrustType trustType; | 860 SECTrustType trustType; |
| 860 CERTBasicConstraints basicConstraint; | 861 CERTBasicConstraints basicConstraint; |
| 861 PRBool isca; | 862 PRBool isca; |
| 862 PRBool validCAOverride = PR_FALSE; | 863 PRBool validCAOverride = PR_FALSE; |
| 863 SECStatus rv; | 864 SECStatus rv; |
| 864 SECStatus rvFinal = SECSuccess; | 865 SECStatus rvFinal = SECSuccess; |
| 865 unsigned int flags; | 866 unsigned int flags; |
| 866 unsigned int caCertType; | 867 unsigned int caCertType; |
| 867 unsigned int requiredCAKeyUsage; | 868 unsigned int requiredCAKeyUsage; |
| 868 unsigned int requiredFlags; | 869 unsigned int requiredFlags; |
| 869 CERTCertificate *issuerCert; | 870 CERTCertificate *issuerCert; |
| 870 CERTCertTrust certTrust; | 871 CERTCertTrust certTrust; |
| 871 | 872 |
| 872 | |
| 873 if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, | 873 if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE, |
| 874 » » » » » &requiredCAKeyUsage, | 874 &requiredCAKeyUsage, |
| 875 » » » » » &caCertType) != SECSuccess ) { | 875 &caCertType) != SECSuccess) { |
| 876 » PORT_Assert(0); | 876 PORT_Assert(0); |
| 877 » EXIT_IF_NOT_LOGGING(log); | 877 EXIT_IF_NOT_LOGGING(log); |
| 878 » requiredCAKeyUsage = 0; | 878 requiredCAKeyUsage = 0; |
| 879 » caCertType = 0; | 879 caCertType = 0; |
| 880 } | 880 } |
| 881 | 881 |
| 882 switch ( certUsage ) { | 882 switch (certUsage) { |
| 883 case certUsageSSLClient: | 883 case certUsageSSLClient: |
| 884 case certUsageSSLServer: | 884 case certUsageSSLServer: |
| 885 case certUsageSSLCA: | 885 case certUsageSSLCA: |
| 886 case certUsageSSLServerWithStepUp: | 886 case certUsageSSLServerWithStepUp: |
| 887 case certUsageEmailSigner: | 887 case certUsageEmailSigner: |
| 888 case certUsageEmailRecipient: | 888 case certUsageEmailRecipient: |
| 889 case certUsageObjectSigner: | 889 case certUsageObjectSigner: |
| 890 case certUsageVerifyCA: | 890 case certUsageVerifyCA: |
| 891 case certUsageStatusResponder: | 891 case certUsageStatusResponder: |
| 892 » if ( CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, | 892 if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, |
| 893 » » » » » &trustType) != SECSuccess ) { | 893 &trustType) != SECSuccess) { |
| 894 » PORT_Assert(0); | 894 PORT_Assert(0); |
| 895 » EXIT_IF_NOT_LOGGING(log); | 895 EXIT_IF_NOT_LOGGING(log); |
| 896 » requiredFlags = 0; | 896 requiredFlags = 0; |
| 897 » trustType = trustSSL; | 897 trustType = trustSSL; |
| 898 » } | 898 } |
| 899 » break; | 899 break; |
| 900 default: | 900 default: |
| 901 » PORT_Assert(0); | 901 PORT_Assert(0); |
| 902 » EXIT_IF_NOT_LOGGING(log); | 902 EXIT_IF_NOT_LOGGING(log); |
| 903 » requiredFlags = 0; | 903 requiredFlags = 0; |
| 904 » trustType = trustSSL;/* This used to be 0, but we need something | 904 trustType = trustSSL; /* This used to be 0, but we need something |
| 905 » » » * that matches the enumeration type. | 905 * that matches the enumeration type. |
| 906 » » » */ | 906 */ |
| 907 » caCertType = 0; | 907 caCertType = 0; |
| 908 } | 908 } |
| 909 | 909 |
| 910 /* If the basicConstraint extension is included in an intermmediate CA | 910 /* If the basicConstraint extension is included in an intermmediate CA |
| 911 * certificate, make sure that the isCA flag is on. If the | 911 * certificate, make sure that the isCA flag is on. If the |
| 912 * pathLenConstraint component exists, it must be greater than the | 912 * pathLenConstraint component exists, it must be greater than the |
| 913 * number of CA certificates we have seen so far. If the extension | 913 * number of CA certificates we have seen so far. If the extension |
| 914 * is omitted, we will assume that this is a CA certificate with | 914 * is omitted, we will assume that this is a CA certificate with |
| 915 * an unlimited pathLenConstraint (since it already passes the | 915 * an unlimited pathLenConstraint (since it already passes the |
| 916 * netscape-cert-type extension checking). | 916 * netscape-cert-type extension checking). |
| 917 */ | 917 */ |
| 918 | 918 |
| 919 rv = CERT_FindBasicConstraintExten(cert, &basicConstraint); | 919 rv = CERT_FindBasicConstraintExten(cert, &basicConstraint); |
| 920 if ( rv != SECSuccess ) { | 920 if (rv != SECSuccess) { |
| 921 » if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { | 921 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { |
| 922 » LOG_ERROR_OR_EXIT(log,cert,0,0); | 922 LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
| 923 » } | 923 } |
| 924 » /* no basic constraints found, we aren't (yet) a CA. */ | 924 /* no basic constraints found, we aren't (yet) a CA. */ |
| 925 » isca = PR_FALSE; | 925 isca = PR_FALSE; |
| 926 } else { | 926 } else { |
| 927 » if ( basicConstraint.isCA == PR_FALSE ) { | 927 if (basicConstraint.isCA == PR_FALSE) { |
| 928 » PORT_SetError (SEC_ERROR_CA_CERT_INVALID); | 928 PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
| 929 » LOG_ERROR_OR_EXIT(log,cert,0,0); | 929 LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
| 930 » } | 930 } |
| 931 | 931 |
| 932 » /* can't check path length if we don't know the previous path */ | 932 /* can't check path length if we don't know the previous path */ |
| 933 » isca = PR_TRUE; | 933 isca = PR_TRUE; |
| 934 } | 934 } |
| 935 » | 935 |
| 936 if ( CERT_GetCertTrust(cert, &certTrust) == SECSuccess ) { | 936 if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) { |
| 937 » /* we have some trust info, but this does NOT imply that this | 937 /* we have some trust info, but this does NOT imply that this |
| 938 » * cert is actually trusted for any purpose. The cert may be | 938 * cert is actually trusted for any purpose. The cert may be |
| 939 » * explicitly UNtrusted. We won't know until we examine the | 939 * explicitly UNtrusted. We won't know until we examine the |
| 940 » * trust bits. | 940 * trust bits. |
| 941 » */ | 941 */ |
| 942 if (certUsage == certUsageStatusResponder) { | 942 if (certUsage == certUsageStatusResponder) { |
| 943 » /* Check the special case of certUsageStatusResponder */ | 943 /* Check the special case of certUsageStatusResponder */ |
| 944 issuerCert = CERT_FindCertIssuer(cert, t, certUsage); | 944 issuerCert = CERT_FindCertIssuer(cert, t, certUsage); |
| 945 if (issuerCert) { | 945 if (issuerCert) { |
| 946 if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) | 946 if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) != |
| 947 » » != SECSuccess) { | 947 SECSuccess) { |
| 948 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); | 948 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); |
| 949 CERT_DestroyCertificate(issuerCert); | 949 CERT_DestroyCertificate(issuerCert); |
| 950 goto loser; | 950 goto loser; |
| 951 } | 951 } |
| 952 CERT_DestroyCertificate(issuerCert); | 952 CERT_DestroyCertificate(issuerCert); |
| 953 } | 953 } |
| 954 » /* XXX We have NOT determined that this cert is trusted. | 954 /* XXX We have NOT determined that this cert is trusted. |
| 955 » * For years, NSS has treated this as trusted, | 955 * For years, NSS has treated this as trusted, |
| 956 » * but it seems incorrect. | 956 * but it seems incorrect. |
| 957 » */ | 957 */ |
| 958 » rv = rvFinal; | 958 rv = rvFinal; |
| 959 » goto done; | 959 goto done; |
| 960 } | 960 } |
| 961 | 961 |
| 962 » /* | 962 /* |
| 963 » * check the trust params of the issuer | 963 * check the trust params of the issuer |
| 964 » */ | 964 */ |
| 965 » flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType); | 965 flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType); |
| 966 » if ( ( flags & requiredFlags ) == requiredFlags) { | 966 if ((flags & requiredFlags) == requiredFlags) { |
| 967 » /* we found a trusted one, so return */ | 967 /* we found a trusted one, so return */ |
| 968 » rv = rvFinal; | 968 rv = rvFinal; |
| 969 » goto done; | 969 goto done; |
| 970 » } | 970 } |
| 971 » if (flags & CERTDB_VALID_CA) { | 971 if (flags & CERTDB_VALID_CA) { |
| 972 » validCAOverride = PR_TRUE; | 972 validCAOverride = PR_TRUE; |
| 973 » } | 973 } |
| 974 » /* is it explicitly distrusted? */ | 974 /* is it explicitly distrusted? */ |
| 975 » if ((flags & CERTDB_TERMINAL_RECORD) && | 975 if ((flags & CERTDB_TERMINAL_RECORD) && |
| 976 » » ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0)) { | 976 ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) { |
| 977 » /* untrusted -- the cert is explicitly untrusted, not | 977 /* untrusted -- the cert is explicitly untrusted, not |
| 978 » * just that it doesn't chain to a trusted cert */ | 978 * just that it doesn't chain to a trusted cert */ |
| 979 » PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); | 979 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); |
| 980 » LOG_ERROR_OR_EXIT(log,cert,0,flags); | 980 LOG_ERROR_OR_EXIT(log, cert, 0, flags); |
| 981 » } | 981 } |
| 982 } | 982 } |
| 983 if (!validCAOverride) { | 983 if (!validCAOverride) { |
| 984 » /* | 984 /* |
| 985 » * Make sure that if this is an intermediate CA in the chain that | 985 * Make sure that if this is an intermediate CA in the chain that |
| 986 » * it was given permission by its signer to be a CA. | 986 * it was given permission by its signer to be a CA. |
| 987 » */ | 987 */ |
| 988 » /* | 988 /* |
| 989 » * if basicConstraints says it is a ca, then we check the | 989 * if basicConstraints says it is a ca, then we check the |
| 990 » * nsCertType. If the nsCertType has any CA bits set, then | 990 * nsCertType. If the nsCertType has any CA bits set, then |
| 991 » * it must have the right one. | 991 * it must have the right one. |
| 992 » */ | 992 */ |
| 993 » if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) { | 993 if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) { |
| 994 » isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE; | 994 isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE; |
| 995 » } | 995 } |
| 996 » | 996 |
| 997 » if (!isca) { | 997 if (!isca) { |
| 998 » PORT_SetError(SEC_ERROR_CA_CERT_INVALID); | 998 PORT_SetError(SEC_ERROR_CA_CERT_INVALID); |
| 999 » LOG_ERROR_OR_EXIT(log,cert,0,0); | 999 LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
| 1000 » } | 1000 } |
| 1001 » | 1001 |
| 1002 » /* make sure key usage allows cert signing */ | 1002 /* make sure key usage allows cert signing */ |
| 1003 » if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) { | 1003 if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) { |
| 1004 » PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); | 1004 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
| 1005 » LOG_ERROR_OR_EXIT(log,cert,0,requiredCAKeyUsage); | 1005 LOG_ERROR_OR_EXIT(log, cert, 0, requiredCAKeyUsage); |
| 1006 » } | 1006 } |
| 1007 } | 1007 } |
| 1008 /* make sure that the issuer is not self signed. If it is, then | 1008 /* make sure that the issuer is not self signed. If it is, then |
| 1009 * stop here to prevent looping. | 1009 * stop here to prevent looping. |
| 1010 */ | 1010 */ |
| 1011 if (cert->isRoot) { | 1011 if (cert->isRoot) { |
| 1012 » PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); | 1012 PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER); |
| 1013 » LOG_ERROR(log, cert, 0, 0); | 1013 LOG_ERROR(log, cert, 0, 0); |
| 1014 » goto loser; | 1014 goto loser; |
| 1015 } | 1015 } |
| 1016 | 1016 |
| 1017 return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t, | 1017 return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t, |
| 1018 » » » » » » » wincx, log); | 1018 wincx, log); |
| 1019 loser: | 1019 loser: |
| 1020 rv = SECFailure; | 1020 rv = SECFailure; |
| 1021 done: | 1021 done: |
| 1022 return rv; | 1022 return rv; |
| 1023 } | 1023 } |
| 1024 | 1024 |
| 1025 #define NEXT_USAGE() { \ | 1025 #define NEXT_USAGE() \ |
| 1026 i*=2; \ | 1026 { \ |
| 1027 certUsage++; \ | 1027 i *= 2; \ |
| 1028 continue; \ | 1028 certUsage++; \ |
| 1029 } | 1029 continue; \ |
| 1030 } |
| 1030 | 1031 |
| 1031 #define VALID_USAGE() { \ | 1032 #define VALID_USAGE() \ |
| 1032 NEXT_USAGE(); \ | 1033 { \ |
| 1033 } | 1034 NEXT_USAGE(); \ |
| 1035 } |
| 1034 | 1036 |
| 1035 #define INVALID_USAGE() { \ | 1037 #define INVALID_USAGE() \ |
| 1036 if (returnedUsages) { \ | 1038 { \ |
| 1037 *returnedUsages &= (~i); \ | 1039 if (returnedUsages) { \ |
| 1038 } \ | 1040 *returnedUsages &= (~i); \ |
| 1039 if (PR_TRUE == requiredUsage) { \ | 1041 } \ |
| 1040 valid = SECFailure; \ | 1042 if (PR_TRUE == requiredUsage) { \ |
| 1041 } \ | 1043 valid = SECFailure; \ |
| 1042 NEXT_USAGE(); \ | 1044 } \ |
| 1043 } | 1045 NEXT_USAGE(); \ |
| 1046 } |
| 1044 | 1047 |
| 1045 /* | 1048 /* |
| 1046 * check the leaf cert against trust and usage. | 1049 * check the leaf cert against trust and usage. |
| 1047 * returns success if the cert is not distrusted. If the cert is | 1050 * returns success if the cert is not distrusted. If the cert is |
| 1048 * trusted, then the trusted bool will be true. | 1051 * trusted, then the trusted bool will be true. |
| 1049 * returns failure if the cert is distrusted. If failure, flags | 1052 * returns failure if the cert is distrusted. If failure, flags |
| 1050 * will return the flag bits that indicated distrust. | 1053 * will return the flag bits that indicated distrust. |
| 1051 */ | 1054 */ |
| 1052 SECStatus | 1055 SECStatus |
| 1053 cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage, | 1056 cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage, |
| 1054 » unsigned int *failedFlags, PRBool *trusted) | 1057 unsigned int *failedFlags, PRBool *trusted) |
| 1055 { | 1058 { |
| 1056 unsigned int flags; | 1059 unsigned int flags; |
| 1057 CERTCertTrust trust; | 1060 CERTCertTrust trust; |
| 1058 | 1061 |
| 1059 *failedFlags = 0; | 1062 *failedFlags = 0; |
| 1060 *trusted = PR_FALSE; | 1063 *trusted = PR_FALSE; |
| 1061 » » » | 1064 |
| 1062 /* check trust flags to see if this cert is directly trusted */ | 1065 /* check trust flags to see if this cert is directly trusted */ |
| 1063 if ( CERT_GetCertTrust(cert, &trust) == SECSuccess ) { | 1066 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) { |
| 1064 » switch ( certUsage ) { | 1067 switch (certUsage) { |
| 1065 » case certUsageSSLClient: | 1068 case certUsageSSLClient: |
| 1066 » case certUsageSSLServer: | 1069 case certUsageSSLServer: |
| 1067 » flags = trust.sslFlags; | 1070 flags = trust.sslFlags; |
| 1068 » | |
| 1069 » /* is the cert directly trusted or not trusted ? */ | |
| 1070 » if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is | |
| 1071 » » » » » » * authoritative */ | |
| 1072 » » if ( flags & CERTDB_TRUSTED ) {»/* trust this cert */ | |
| 1073 » » *trusted = PR_TRUE; | |
| 1074 » » return SECSuccess; | |
| 1075 » » } else { /* don't trust this cert */ | |
| 1076 » » *failedFlags = flags; | |
| 1077 » » return SECFailure; | |
| 1078 » » } | |
| 1079 » } | |
| 1080 » break; | |
| 1081 » case certUsageSSLServerWithStepUp: | |
| 1082 » /* XXX - step up certs can't be directly trusted, only distrust */ | |
| 1083 » flags = trust.sslFlags; | |
| 1084 » if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is | |
| 1085 » » » » » » * authoritative */ | |
| 1086 » » if (( flags & CERTDB_TRUSTED ) == 0) {» | |
| 1087 » » /* don't trust this cert */ | |
| 1088 » » *failedFlags = flags; | |
| 1089 » » return SECFailure; | |
| 1090 » » } | |
| 1091 » } | |
| 1092 » break; | |
| 1093 » case certUsageSSLCA: | |
| 1094 » flags = trust.sslFlags; | |
| 1095 » if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is | |
| 1096 » » » » » » * authoritative */ | |
| 1097 » » if (( flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA) ) == 0) {» | |
| 1098 » » /* don't trust this cert */ | |
| 1099 » » *failedFlags = flags; | |
| 1100 » » return SECFailure; | |
| 1101 » » } | |
| 1102 » } | |
| 1103 » break; | |
| 1104 » case certUsageEmailSigner: | |
| 1105 » case certUsageEmailRecipient: | |
| 1106 » flags = trust.emailFlags; | |
| 1107 » if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is | |
| 1108 » » » » » » * authoritative */ | |
| 1109 » » if ( flags & CERTDB_TRUSTED ) {»/* trust this cert */ | |
| 1110 » » *trusted = PR_TRUE; | |
| 1111 » » return SECSuccess; | |
| 1112 » » } | |
| 1113 » » else { /* don't trust this cert */ | |
| 1114 » » *failedFlags = flags; | |
| 1115 » » return SECFailure; | |
| 1116 » » } | |
| 1117 » } | |
| 1118 » | |
| 1119 » break; | |
| 1120 » case certUsageObjectSigner: | |
| 1121 » flags = trust.objectSigningFlags; | |
| 1122 | 1071 |
| 1123 » if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is | 1072 /* is the cert directly trusted or not trusted ? */ |
| 1124 » » » » » » * authoritative */ | 1073 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
| 1125 » » if ( flags & CERTDB_TRUSTED ) {»/* trust this cert */ | 1074 * authoritative */ |
| 1126 » » *trusted = PR_TRUE; | 1075 if (flags & CERTDB_TRUSTED) { /* trust this cert */ |
| 1127 » » return SECSuccess; | 1076 *trusted = PR_TRUE; |
| 1128 » » } else { /* don't trust this cert */ | 1077 return SECSuccess; |
| 1129 » » *failedFlags = flags; | 1078 } else { /* don't trust this cert */ |
| 1130 » » return SECFailure; | 1079 *failedFlags = flags; |
| 1131 » » } | 1080 return SECFailure; |
| 1132 » } | 1081 } |
| 1133 » break; | 1082 } |
| 1134 » case certUsageVerifyCA: | 1083 break; |
| 1135 » case certUsageStatusResponder: | 1084 case certUsageSSLServerWithStepUp: |
| 1136 » flags = trust.sslFlags; | 1085 /* XXX - step up certs can't be directly trusted, only distrust
*/ |
| 1137 » /* is the cert directly trusted or not trusted ? */ | 1086 flags = trust.sslFlags; |
| 1138 » if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) == | 1087 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
| 1139 » » ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) { | 1088 * authoritative */ |
| 1140 » » *trusted = PR_TRUE; | 1089 if ((flags & CERTDB_TRUSTED) == 0) { |
| 1141 » » return SECSuccess; | 1090 /* don't trust this cert */ |
| 1142 » } | 1091 *failedFlags = flags; |
| 1143 » flags = trust.emailFlags; | 1092 return SECFailure; |
| 1144 » /* is the cert directly trusted or not trusted ? */ | 1093 } |
| 1145 » if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) == | 1094 } |
| 1146 » » ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) { | 1095 break; |
| 1147 » » *trusted = PR_TRUE; | 1096 case certUsageSSLCA: |
| 1148 » » return SECSuccess; | 1097 flags = trust.sslFlags; |
| 1149 » } | 1098 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
| 1150 » flags = trust.objectSigningFlags; | 1099 * authoritative */ |
| 1151 » /* is the cert directly trusted or not trusted ? */ | 1100 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { |
| 1152 » if ( ( flags & ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) == | 1101 /* don't trust this cert */ |
| 1153 » » ( CERTDB_VALID_CA | CERTDB_TRUSTED_CA ) ) { | 1102 *failedFlags = flags; |
| 1154 » » *trusted = PR_TRUE; | 1103 return SECFailure; |
| 1155 » » return SECSuccess; | 1104 } |
| 1156 » } | 1105 } |
| 1157 » /* fall through to test distrust */ | 1106 break; |
| 1158 » case certUsageAnyCA: | 1107 case certUsageEmailSigner: |
| 1159 » case certUsageUserCertImport: | 1108 case certUsageEmailRecipient: |
| 1160 » /* do we distrust these certs explicitly */ | 1109 flags = trust.emailFlags; |
| 1161 » flags = trust.sslFlags; | 1110 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
| 1162 » if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is | 1111 * authoritative */ |
| 1163 » » » » » » * authoritative */ | 1112 if (flags & CERTDB_TRUSTED) { /* trust this cert */ |
| 1164 » » if ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0) { | 1113 *trusted = PR_TRUE; |
| 1165 » » *failedFlags = flags; | 1114 return SECSuccess; |
| 1166 » » return SECFailure; | 1115 } else { /* don't trust this cert */ |
| 1167 » » } | 1116 *failedFlags = flags; |
| 1168 » } | 1117 return SECFailure; |
| 1169 » flags = trust.emailFlags; | 1118 } |
| 1170 » if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is | 1119 } |
| 1171 » » » » » » * authoritative */ | 1120 |
| 1172 » » if ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0) { | 1121 break; |
| 1173 » » *failedFlags = flags; | 1122 case certUsageObjectSigner: |
| 1174 » » return SECFailure; | 1123 flags = trust.objectSigningFlags; |
| 1175 » » } | 1124 |
| 1176 » } | 1125 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
| 1177 » /* fall through */ | 1126 * authoritative */ |
| 1178 » case certUsageProtectedObjectSigner: | 1127 if (flags & CERTDB_TRUSTED) { /* trust this cert */ |
| 1179 » flags = trust.objectSigningFlags; | 1128 *trusted = PR_TRUE; |
| 1180 » if ( flags & CERTDB_TERMINAL_RECORD) { /* the trust record is | 1129 return SECSuccess; |
| 1181 » » » » » » * authoritative */ | 1130 } else { /* don't trust this cert */ |
| 1182 » » if ((flags & (CERTDB_TRUSTED|CERTDB_TRUSTED_CA)) == 0) { | 1131 *failedFlags = flags; |
| 1183 » » *failedFlags = flags; | 1132 return SECFailure; |
| 1184 » » return SECFailure; | 1133 } |
| 1185 » » } | 1134 } |
| 1186 » } | 1135 break; |
| 1187 » break; | 1136 case certUsageVerifyCA: |
| 1188 » } | 1137 case certUsageStatusResponder: |
| 1138 flags = trust.sslFlags; |
| 1139 /* is the cert directly trusted or not trusted ? */ |
| 1140 if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) == |
| 1141 (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) { |
| 1142 *trusted = PR_TRUE; |
| 1143 return SECSuccess; |
| 1144 } |
| 1145 flags = trust.emailFlags; |
| 1146 /* is the cert directly trusted or not trusted ? */ |
| 1147 if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) == |
| 1148 (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) { |
| 1149 *trusted = PR_TRUE; |
| 1150 return SECSuccess; |
| 1151 } |
| 1152 flags = trust.objectSigningFlags; |
| 1153 /* is the cert directly trusted or not trusted ? */ |
| 1154 if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) == |
| 1155 (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) { |
| 1156 *trusted = PR_TRUE; |
| 1157 return SECSuccess; |
| 1158 } |
| 1159 /* fall through to test distrust */ |
| 1160 case certUsageAnyCA: |
| 1161 case certUsageUserCertImport: |
| 1162 /* do we distrust these certs explicitly */ |
| 1163 flags = trust.sslFlags; |
| 1164 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
| 1165 * authoritative */ |
| 1166 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { |
| 1167 *failedFlags = flags; |
| 1168 return SECFailure; |
| 1169 } |
| 1170 } |
| 1171 flags = trust.emailFlags; |
| 1172 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
| 1173 * authoritative */ |
| 1174 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { |
| 1175 *failedFlags = flags; |
| 1176 return SECFailure; |
| 1177 } |
| 1178 } |
| 1179 /* fall through */ |
| 1180 case certUsageProtectedObjectSigner: |
| 1181 flags = trust.objectSigningFlags; |
| 1182 if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is |
| 1183 * authoritative */ |
| 1184 if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) { |
| 1185 *failedFlags = flags; |
| 1186 return SECFailure; |
| 1187 } |
| 1188 } |
| 1189 break; |
| 1190 } |
| 1189 } | 1191 } |
| 1190 return SECSuccess; | 1192 return SECSuccess; |
| 1191 } | 1193 } |
| 1192 | 1194 |
| 1193 /* | 1195 /* |
| 1194 * verify a certificate by checking if it's valid and that we | 1196 * verify a certificate by checking if it's valid and that we |
| 1195 * trust the issuer. | 1197 * trust the issuer. |
| 1196 * | 1198 * |
| 1197 * certificateUsage contains a bitfield of all cert usages that are | 1199 * certificateUsage contains a bitfield of all cert usages that are |
| 1198 * required for verification to succeed | 1200 * required for verification to succeed |
| 1199 * | 1201 * |
| 1200 * a bitfield of cert usages is returned in *returnedUsages | 1202 * a bitfield of cert usages is returned in *returnedUsages |
| 1201 * if requiredUsages is non-zero, the returned bitmap is only | 1203 * if requiredUsages is non-zero, the returned bitmap is only |
| 1202 * for those required usages, otherwise it is for all usages | 1204 * for those required usages, otherwise it is for all usages |
| 1203 * | 1205 * |
| 1204 */ | 1206 */ |
| 1205 SECStatus | 1207 SECStatus |
| 1206 CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert, | 1208 CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 1207 » » PRBool checkSig, SECCertificateUsage requiredUsages, PRTime t, | 1209 PRBool checkSig, SECCertificateUsage requiredUsages, PRTi
me t, |
| 1208 » » void *wincx, CERTVerifyLog *log, SECCertificateUsage* returnedUs
ages) | 1210 void *wincx, CERTVerifyLog *log, SECCertificateUsage *ret
urnedUsages) |
| 1209 { | 1211 { |
| 1210 SECStatus rv; | 1212 SECStatus rv; |
| 1211 SECStatus valid; | 1213 SECStatus valid; |
| 1212 unsigned int requiredKeyUsage; | 1214 unsigned int requiredKeyUsage; |
| 1213 unsigned int requiredCertType; | 1215 unsigned int requiredCertType; |
| 1214 unsigned int flags; | 1216 unsigned int flags; |
| 1215 unsigned int certType; | 1217 unsigned int certType; |
| 1216 PRBool allowOverride; | 1218 PRBool allowOverride; |
| 1217 SECCertTimeValidity validity; | 1219 SECCertTimeValidity validity; |
| 1218 CERTStatusConfig *statusConfig; | 1220 CERTStatusConfig *statusConfig; |
| 1219 PRInt32 i; | 1221 PRInt32 i; |
| 1220 SECCertUsage certUsage = 0; | 1222 SECCertUsage certUsage = 0; |
| 1221 PRBool checkedOCSP = PR_FALSE; | 1223 PRBool checkedOCSP = PR_FALSE; |
| 1222 PRBool checkAllUsages = PR_FALSE; | 1224 PRBool checkAllUsages = PR_FALSE; |
| 1223 PRBool revoked = PR_FALSE; | 1225 PRBool revoked = PR_FALSE; |
| 1224 PRBool sigerror = PR_FALSE; | 1226 PRBool sigerror = PR_FALSE; |
| 1225 PRBool trusted = PR_FALSE; | 1227 PRBool trusted = PR_FALSE; |
| 1226 | 1228 |
| 1227 if (!requiredUsages) { | 1229 if (!requiredUsages) { |
| 1228 /* there are no required usages, so the user probably wants to | 1230 /* there are no required usages, so the user probably wants to |
| 1229 get status for all usages */ | 1231 get status for all usages */ |
| 1230 checkAllUsages = PR_TRUE; | 1232 checkAllUsages = PR_TRUE; |
| 1231 } | 1233 } |
| 1232 | 1234 |
| 1233 if (returnedUsages) { | 1235 if (returnedUsages) { |
| 1234 *returnedUsages = 0; | 1236 *returnedUsages = 0; |
| 1235 } else { | 1237 } else { |
| 1236 /* we don't have a place to return status for all usages, | 1238 /* we don't have a place to return status for all usages, |
| 1237 so we can skip checks for usages that aren't required */ | 1239 so we can skip checks for usages that aren't required */ |
| 1238 checkAllUsages = PR_FALSE; | 1240 checkAllUsages = PR_FALSE; |
| 1239 } | 1241 } |
| 1240 valid = SECSuccess ; /* start off assuming cert is valid */ | 1242 valid = SECSuccess; /* start off assuming cert is valid */ |
| 1241 | 1243 |
| 1242 /* make sure that the cert is valid at time t */ | 1244 /* make sure that the cert is valid at time t */ |
| 1243 allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) || | 1245 allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) || |
| 1244 (requiredUsages & certificateUsageSSLServerWithStep
Up)); | 1246 (requiredUsages & certificateUsageSSLServerWithStep
Up)); |
| 1245 validity = CERT_CheckCertValidTimes(cert, t, allowOverride); | 1247 validity = CERT_CheckCertValidTimes(cert, t, allowOverride); |
| 1246 if ( validity != secCertTimeValid ) { | 1248 if (validity != secCertTimeValid) { |
| 1247 valid = SECFailure; | 1249 valid = SECFailure; |
| 1248 LOG_ERROR_OR_EXIT(log,cert,0,validity); | 1250 LOG_ERROR_OR_EXIT(log, cert, 0, validity); |
| 1249 } | 1251 } |
| 1250 | 1252 |
| 1251 /* check key usage and netscape cert type */ | 1253 /* check key usage and netscape cert type */ |
| 1252 cert_GetCertType(cert); | 1254 cert_GetCertType(cert); |
| 1253 certType = cert->nsCertType; | 1255 certType = cert->nsCertType; |
| 1254 | 1256 |
| 1255 for (i=1; i<=certificateUsageHighest && | 1257 for (i = 1; i <= certificateUsageHighest && |
| 1256 (SECSuccess == valid || returnedUsages || log) ; ) { | 1258 (SECSuccess == valid || returnedUsages || log);) { |
| 1257 PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE; | 1259 PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE; |
| 1258 if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) { | 1260 if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) { |
| 1259 NEXT_USAGE(); | 1261 NEXT_USAGE(); |
| 1260 } | 1262 } |
| 1261 if (returnedUsages) { | 1263 if (returnedUsages) { |
| 1262 *returnedUsages |= i; /* start off assuming this usage is valid */ | 1264 *returnedUsages |= i; /* start off assuming this usage is valid */ |
| 1263 } | 1265 } |
| 1264 switch ( certUsage ) { | 1266 switch (certUsage) { |
| 1265 case certUsageSSLClient: | 1267 case certUsageSSLClient: |
| 1266 case certUsageSSLServer: | 1268 case certUsageSSLServer: |
| 1267 case certUsageSSLServerWithStepUp: | 1269 case certUsageSSLServerWithStepUp: |
| 1268 case certUsageSSLCA: | 1270 case certUsageSSLCA: |
| 1269 case certUsageEmailSigner: | 1271 case certUsageEmailSigner: |
| 1270 case certUsageEmailRecipient: | 1272 case certUsageEmailRecipient: |
| 1271 case certUsageObjectSigner: | 1273 case certUsageObjectSigner: |
| 1272 case certUsageStatusResponder: | 1274 case certUsageStatusResponder: |
| 1273 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE, | 1275 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE, |
| 1274 &requiredKeyUsage, | 1276 &requiredKeyUsage, |
| 1275 &requiredCertType); | 1277 &requiredCertType); |
| 1276 if ( rv != SECSuccess ) { | 1278 if (rv != SECSuccess) { |
| 1279 PORT_Assert(0); |
| 1280 /* EXIT_IF_NOT_LOGGING(log); XXX ??? */ |
| 1281 requiredKeyUsage = 0; |
| 1282 requiredCertType = 0; |
| 1283 INVALID_USAGE(); |
| 1284 } |
| 1285 break; |
| 1286 |
| 1287 case certUsageAnyCA: |
| 1288 case certUsageProtectedObjectSigner: |
| 1289 case certUsageUserCertImport: |
| 1290 case certUsageVerifyCA: |
| 1291 /* these usages cannot be verified */ |
| 1292 NEXT_USAGE(); |
| 1293 |
| 1294 default: |
| 1277 PORT_Assert(0); | 1295 PORT_Assert(0); |
| 1278 /* EXIT_IF_NOT_LOGGING(log); XXX ??? */ | |
| 1279 requiredKeyUsage = 0; | 1296 requiredKeyUsage = 0; |
| 1280 requiredCertType = 0; | 1297 requiredCertType = 0; |
| 1281 INVALID_USAGE(); | 1298 INVALID_USAGE(); |
| 1282 } | |
| 1283 break; | |
| 1284 | |
| 1285 case certUsageAnyCA: | |
| 1286 case certUsageProtectedObjectSigner: | |
| 1287 case certUsageUserCertImport: | |
| 1288 case certUsageVerifyCA: | |
| 1289 /* these usages cannot be verified */ | |
| 1290 NEXT_USAGE(); | |
| 1291 | |
| 1292 default: | |
| 1293 PORT_Assert(0); | |
| 1294 requiredKeyUsage = 0; | |
| 1295 requiredCertType = 0; | |
| 1296 INVALID_USAGE(); | |
| 1297 } | 1299 } |
| 1298 if ( CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess ) { | 1300 if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) { |
| 1299 if (PR_TRUE == requiredUsage) { | 1301 if (PR_TRUE == requiredUsage) { |
| 1300 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); | 1302 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
| 1301 } | 1303 } |
| 1302 LOG_ERROR(log,cert,0,requiredKeyUsage); | 1304 LOG_ERROR(log, cert, 0, requiredKeyUsage); |
| 1303 INVALID_USAGE(); | 1305 INVALID_USAGE(); |
| 1304 } | 1306 } |
| 1305 if ( !( certType & requiredCertType ) ) { | 1307 if (!(certType & requiredCertType)) { |
| 1306 if (PR_TRUE == requiredUsage) { | 1308 if (PR_TRUE == requiredUsage) { |
| 1307 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); | 1309 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); |
| 1308 } | 1310 } |
| 1309 LOG_ERROR(log,cert,0,requiredCertType); | 1311 LOG_ERROR(log, cert, 0, requiredCertType); |
| 1310 INVALID_USAGE(); | 1312 INVALID_USAGE(); |
| 1311 } | 1313 } |
| 1312 | 1314 |
| 1313 » rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted); | 1315 rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted); |
| 1314 » if (rv == SECFailure) { | 1316 if (rv == SECFailure) { |
| 1315 » if (PR_TRUE == requiredUsage) { | 1317 if (PR_TRUE == requiredUsage) { |
| 1316 » » PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); | 1318 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); |
| 1317 » } | 1319 } |
| 1318 » LOG_ERROR(log, cert, 0, flags); | 1320 LOG_ERROR(log, cert, 0, flags); |
| 1319 » INVALID_USAGE(); | 1321 INVALID_USAGE(); |
| 1320 » } else if (trusted) { | 1322 } else if (trusted) { |
| 1321 » VALID_USAGE(); | 1323 VALID_USAGE(); |
| 1322 » } | 1324 } |
| 1323 | 1325 |
| 1324 » if (PR_TRUE == revoked || PR_TRUE == sigerror) { | 1326 if (PR_TRUE == revoked || PR_TRUE == sigerror) { |
| 1325 » INVALID_USAGE(); | 1327 INVALID_USAGE(); |
| 1326 » } | 1328 } |
| 1327 | 1329 |
| 1328 rv = cert_VerifyCertChain(handle, cert, | 1330 rv = cert_VerifyCertChain(handle, cert, |
| 1329 checkSig, &sigerror, | 1331 checkSig, &sigerror, |
| 1330 certUsage, t, wincx, log, | 1332 certUsage, t, wincx, log, |
| 1331 &revoked); | 1333 &revoked); |
| 1332 | 1334 |
| 1333 if (rv != SECSuccess) { | 1335 if (rv != SECSuccess) { |
| 1334 /* EXIT_IF_NOT_LOGGING(log); XXX ???? */ | 1336 /* EXIT_IF_NOT_LOGGING(log); XXX ???? */ |
| 1335 INVALID_USAGE(); | 1337 INVALID_USAGE(); |
| 1336 } | 1338 } |
| 1337 | 1339 |
| 1338 /* | 1340 /* |
| 1339 * Check OCSP revocation status, but only if the cert we are checking | 1341 * Check OCSP revocation status, but only if the cert we are checking |
| 1340 * is not a status responder itself. We only do this in the case | 1342 * is not a status responder itself. We only do this in the case |
| 1341 * where we checked the cert chain (above); explicit trust "wins" | 1343 * where we checked the cert chain (above); explicit trust "wins" |
| 1342 * (avoids status checking, just as it avoids CRL checking) by | 1344 * (avoids status checking, just as it avoids CRL checking) by |
| 1343 * bypassing this code. | 1345 * bypassing this code. |
| 1344 */ | 1346 */ |
| 1345 | 1347 |
| 1346 if (PR_FALSE == checkedOCSP) { | 1348 if (PR_FALSE == checkedOCSP) { |
| 1347 checkedOCSP = PR_TRUE; /* only check OCSP once */ | 1349 checkedOCSP = PR_TRUE; /* only check OCSP once */ |
| 1348 statusConfig = CERT_GetStatusConfig(handle); | 1350 statusConfig = CERT_GetStatusConfig(handle); |
| 1349 if (requiredUsages != certificateUsageStatusResponder && | 1351 if (requiredUsages != certificateUsageStatusResponder && |
| 1350 statusConfig != NULL) { | 1352 statusConfig != NULL) { |
| 1351 if (statusConfig->statusChecker != NULL) { | 1353 if (statusConfig->statusChecker != NULL) { |
| 1352 rv = (* statusConfig->statusChecker)(handle, cert, | 1354 rv = (*statusConfig->statusChecker)(handle, cert, |
| 1353 t, wincx); | 1355 t, wincx); |
| 1354 if (rv != SECSuccess) { | 1356 if (rv != SECSuccess) { |
| 1355 LOG_ERROR(log,cert,0,0); | 1357 LOG_ERROR(log, cert, 0, 0); |
| 1356 revoked = PR_TRUE; | 1358 revoked = PR_TRUE; |
| 1357 INVALID_USAGE(); | 1359 INVALID_USAGE(); |
| 1358 } | 1360 } |
| 1359 } | 1361 } |
| 1360 } | 1362 } |
| 1361 } | 1363 } |
| 1362 | 1364 |
| 1363 NEXT_USAGE(); | 1365 NEXT_USAGE(); |
| 1364 } | 1366 } |
| 1365 | 1367 |
| 1366 loser: | 1368 loser: |
| 1367 return(valid); | 1369 return (valid); |
| 1368 } | 1370 } |
| 1369 | 1371 |
| 1370 SECStatus | 1372 SECStatus |
| 1371 CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert, | 1373 CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 1372 » » PRBool checkSig, SECCertUsage certUsage, PRTime t, | 1374 PRBool checkSig, SECCertUsage certUsage, PRTime t, |
| 1373 » » void *wincx, CERTVerifyLog *log) | 1375 void *wincx, CERTVerifyLog *log) |
| 1374 { | 1376 { |
| 1375 return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t, | 1377 return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t, |
| 1376 CERT_VERIFYCERT_USE_DEFAULTS, wincx, log); | 1378 CERT_VERIFYCERT_USE_DEFAULTS, wincx, log); |
| 1377 } | 1379 } |
| 1378 | 1380 |
| 1379 SECStatus | 1381 SECStatus |
| 1380 cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert, | 1382 cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 1381 PRBool checkSig, SECCertUsage certUsage, PRTime t, | 1383 PRBool checkSig, SECCertUsage certUsage, PRTime t, |
| 1382 PRUint32 flags, void *wincx, CERTVerifyLog *log) | 1384 PRUint32 flags, void *wincx, CERTVerifyLog *log) |
| 1383 { | 1385 { |
| 1384 SECStatus rv; | 1386 SECStatus rv; |
| 1385 unsigned int requiredKeyUsage; | 1387 unsigned int requiredKeyUsage; |
| 1386 unsigned int requiredCertType; | 1388 unsigned int requiredCertType; |
| 1387 unsigned int failedFlags; | 1389 unsigned int failedFlags; |
| 1388 unsigned int certType; | 1390 unsigned int certType; |
| 1389 PRBool trusted; | 1391 PRBool trusted; |
| 1390 PRBool allowOverride; | 1392 PRBool allowOverride; |
| 1391 SECCertTimeValidity validity; | 1393 SECCertTimeValidity validity; |
| 1392 CERTStatusConfig *statusConfig; | 1394 CERTStatusConfig *statusConfig; |
| 1393 | 1395 |
| 1394 #ifdef notdef | 1396 #ifdef notdef |
| 1395 /* check if this cert is in the Evil list */ | 1397 /* check if this cert is in the Evil list */ |
| 1396 rv = CERT_CheckForEvilCert(cert); | 1398 rv = CERT_CheckForEvilCert(cert); |
| 1397 if ( rv != SECSuccess ) { | 1399 if (rv != SECSuccess) { |
| 1398 » PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); | 1400 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); |
| 1399 » LOG_ERROR_OR_EXIT(log,cert,0,0); | 1401 LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
| 1400 } | 1402 } |
| 1401 #endif | 1403 #endif |
| 1402 | 1404 |
| 1403 /* make sure that the cert is valid at time t */ | 1405 /* make sure that the cert is valid at time t */ |
| 1404 allowOverride = (PRBool)((certUsage == certUsageSSLServer) || | 1406 allowOverride = (PRBool)((certUsage == certUsageSSLServer) || |
| 1405 (certUsage == certUsageSSLServerWithStepUp)); | 1407 (certUsage == certUsageSSLServerWithStepUp)); |
| 1406 validity = CERT_CheckCertValidTimes(cert, t, allowOverride); | 1408 validity = CERT_CheckCertValidTimes(cert, t, allowOverride); |
| 1407 if ( validity != secCertTimeValid ) { | 1409 if (validity != secCertTimeValid) { |
| 1408 » LOG_ERROR_OR_EXIT(log,cert,0,validity); | 1410 LOG_ERROR_OR_EXIT(log, cert, 0, validity); |
| 1409 } | 1411 } |
| 1410 | 1412 |
| 1411 /* check key usage and netscape cert type */ | 1413 /* check key usage and netscape cert type */ |
| 1412 cert_GetCertType(cert); | 1414 cert_GetCertType(cert); |
| 1413 certType = cert->nsCertType; | 1415 certType = cert->nsCertType; |
| 1414 switch ( certUsage ) { | 1416 switch (certUsage) { |
| 1415 case certUsageSSLClient: | 1417 case certUsageSSLClient: |
| 1416 case certUsageSSLServer: | 1418 case certUsageSSLServer: |
| 1417 case certUsageSSLServerWithStepUp: | 1419 case certUsageSSLServerWithStepUp: |
| 1418 case certUsageSSLCA: | 1420 case certUsageSSLCA: |
| 1419 case certUsageEmailSigner: | 1421 case certUsageEmailSigner: |
| 1420 case certUsageEmailRecipient: | 1422 case certUsageEmailRecipient: |
| 1421 case certUsageObjectSigner: | 1423 case certUsageObjectSigner: |
| 1422 case certUsageStatusResponder: | 1424 case certUsageStatusResponder: |
| 1423 » rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE, | 1425 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE, |
| 1424 » » » » » &requiredKeyUsage, | 1426 &requiredKeyUsage, |
| 1425 » » » » » &requiredCertType); | 1427 &requiredCertType); |
| 1426 » if ( rv != SECSuccess ) { | 1428 if (rv != SECSuccess) { |
| 1427 » PORT_Assert(0); | 1429 PORT_Assert(0); |
| 1428 » EXIT_IF_NOT_LOGGING(log); | 1430 EXIT_IF_NOT_LOGGING(log); |
| 1429 » requiredKeyUsage = 0; | 1431 requiredKeyUsage = 0; |
| 1430 » requiredCertType = 0; | 1432 requiredCertType = 0; |
| 1431 » } | 1433 } |
| 1432 » break; | 1434 break; |
| 1433 case certUsageVerifyCA: | 1435 case certUsageVerifyCA: |
| 1434 case certUsageAnyCA: | 1436 case certUsageAnyCA: |
| 1435 » requiredKeyUsage = KU_KEY_CERT_SIGN; | 1437 requiredKeyUsage = KU_KEY_CERT_SIGN; |
| 1436 » requiredCertType = NS_CERT_TYPE_CA; | 1438 requiredCertType = NS_CERT_TYPE_CA; |
| 1437 » if ( ! ( certType & NS_CERT_TYPE_CA ) ) { | 1439 if (!(certType & NS_CERT_TYPE_CA)) { |
| 1438 » certType |= NS_CERT_TYPE_CA; | 1440 certType |= NS_CERT_TYPE_CA; |
| 1439 » } | 1441 } |
| 1440 » break; | 1442 break; |
| 1441 default: | 1443 default: |
| 1442 » PORT_Assert(0); | 1444 PORT_Assert(0); |
| 1443 » EXIT_IF_NOT_LOGGING(log); | 1445 EXIT_IF_NOT_LOGGING(log); |
| 1444 » requiredKeyUsage = 0; | 1446 requiredKeyUsage = 0; |
| 1445 » requiredCertType = 0; | 1447 requiredCertType = 0; |
| 1446 } | 1448 } |
| 1447 if ( CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess ) { | 1449 if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) { |
| 1448 » PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); | 1450 PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE); |
| 1449 » LOG_ERROR_OR_EXIT(log,cert,0,requiredKeyUsage); | 1451 LOG_ERROR_OR_EXIT(log, cert, 0, requiredKeyUsage); |
| 1450 } | 1452 } |
| 1451 if ( !( certType & requiredCertType ) ) { | 1453 if (!(certType & requiredCertType)) { |
| 1452 » PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); | 1454 PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); |
| 1453 » LOG_ERROR_OR_EXIT(log,cert,0,requiredCertType); | 1455 LOG_ERROR_OR_EXIT(log, cert, 0, requiredCertType); |
| 1454 } | 1456 } |
| 1455 | 1457 |
| 1456 rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted); | 1458 rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted); |
| 1457 if (rv == SECFailure) { | 1459 if (rv == SECFailure) { |
| 1458 » PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); | 1460 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); |
| 1459 » LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags); | 1461 LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags); |
| 1460 } else if (trusted) { | 1462 } else if (trusted) { |
| 1461 » goto done; | 1463 goto done; |
| 1462 } | 1464 } |
| 1463 | 1465 |
| 1464 | |
| 1465 rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage, | 1466 rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage, |
| 1466 » » » t, wincx, log); | 1467 t, wincx, log); |
| 1467 if (rv != SECSuccess) { | 1468 if (rv != SECSuccess) { |
| 1468 » EXIT_IF_NOT_LOGGING(log); | 1469 EXIT_IF_NOT_LOGGING(log); |
| 1469 } | 1470 } |
| 1470 | 1471 |
| 1471 /* | 1472 /* |
| 1472 * Check revocation status, but only if the cert we are checking is not a | 1473 * Check revocation status, but only if the cert we are checking is not a |
| 1473 * status responder itself and the caller did not ask us to skip the check. | 1474 * status responder itself and the caller did not ask us to skip the check. |
| 1474 * We only do this in the case where we checked the cert chain (above); | 1475 * We only do this in the case where we checked the cert chain (above); |
| 1475 * explicit trust "wins" (avoids status checking, just as it avoids CRL | 1476 * explicit trust "wins" (avoids status checking, just as it avoids CRL |
| 1476 * checking, which is all done inside VerifyCertChain) by bypassing this | 1477 * checking, which is all done inside VerifyCertChain) by bypassing this |
| 1477 * code. | 1478 * code. |
| 1478 */ | 1479 */ |
| 1479 if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) && | 1480 if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) && |
| 1480 » certUsage != certUsageStatusResponder) { | 1481 certUsage != certUsageStatusResponder) { |
| 1481 » statusConfig = CERT_GetStatusConfig(handle); | 1482 statusConfig = CERT_GetStatusConfig(handle); |
| 1482 » if (statusConfig && statusConfig->statusChecker) { | 1483 if (statusConfig && statusConfig->statusChecker) { |
| 1483 » rv = (* statusConfig->statusChecker)(handle, cert, | 1484 rv = (*statusConfig->statusChecker)(handle, cert, |
| 1484 » » » » » » » t, wincx); | 1485 t, wincx); |
| 1485 » if (rv != SECSuccess) { | 1486 if (rv != SECSuccess) { |
| 1486 » » LOG_ERROR_OR_EXIT(log,cert,0,0); | 1487 LOG_ERROR_OR_EXIT(log, cert, 0, 0); |
| 1487 » } | 1488 } |
| 1488 » } | 1489 } |
| 1489 } | 1490 } |
| 1490 | 1491 |
| 1491 done: | 1492 done: |
| 1492 if (log && log->head) { | 1493 if (log && log->head) { |
| 1493 return SECFailure; | 1494 return SECFailure; |
| 1494 } | 1495 } |
| 1495 return(SECSuccess); | 1496 return (SECSuccess); |
| 1496 | 1497 |
| 1497 loser: | 1498 loser: |
| 1498 rv = SECFailure; | 1499 rv = SECFailure; |
| 1499 | 1500 |
| 1500 return(rv); | 1501 return (rv); |
| 1501 } | 1502 } |
| 1502 | 1503 |
| 1503 /* | 1504 /* |
| 1504 * verify a certificate by checking if its valid and that we | 1505 * verify a certificate by checking if its valid and that we |
| 1505 * trust the issuer. Verify time against now. | 1506 * trust the issuer. Verify time against now. |
| 1506 */ | 1507 */ |
| 1507 SECStatus | 1508 SECStatus |
| 1508 CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert, | 1509 CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 1509 » » PRBool checkSig, SECCertificateUsage requiredUsages, | 1510 PRBool checkSig, SECCertificateUsage requiredUsages, |
| 1510 void *wincx, SECCertificateUsage* returnedUsages) | 1511 void *wincx, SECCertificateUsage *returnedUsages) |
| 1511 { | 1512 { |
| 1512 return(CERT_VerifyCertificate(handle, cert, checkSig, | 1513 return (CERT_VerifyCertificate(handle, cert, checkSig, |
| 1513 » » requiredUsages, PR_Now(), wincx, NULL, returnedUsages)); | 1514 requiredUsages, PR_Now(), wincx, NULL, return
edUsages)); |
| 1514 } | 1515 } |
| 1515 | 1516 |
| 1516 /* obsolete, do not use for new code */ | 1517 /* obsolete, do not use for new code */ |
| 1517 SECStatus | 1518 SECStatus |
| 1518 CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert, | 1519 CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert, |
| 1519 » » PRBool checkSig, SECCertUsage certUsage, void *wincx) | 1520 PRBool checkSig, SECCertUsage certUsage, void *wincx) |
| 1520 { | 1521 { |
| 1521 return(CERT_VerifyCert(handle, cert, checkSig, | 1522 return (CERT_VerifyCert(handle, cert, checkSig, |
| 1522 » » certUsage, PR_Now(), wincx, NULL)); | 1523 certUsage, PR_Now(), wincx, NULL)); |
| 1523 } | 1524 } |
| 1524 | 1525 |
| 1525 | |
| 1526 /* [ FROM pcertdb.c ] */ | 1526 /* [ FROM pcertdb.c ] */ |
| 1527 /* | 1527 /* |
| 1528 * Supported usage values and types: | 1528 * Supported usage values and types: |
| 1529 *» certUsageSSLClient | 1529 * certUsageSSLClient |
| 1530 *» certUsageSSLServer | 1530 * certUsageSSLServer |
| 1531 *» certUsageSSLServerWithStepUp | 1531 * certUsageSSLServerWithStepUp |
| 1532 *» certUsageEmailSigner | 1532 * certUsageEmailSigner |
| 1533 *» certUsageEmailRecipient | 1533 * certUsageEmailRecipient |
| 1534 *» certUsageObjectSigner | 1534 * certUsageObjectSigner |
| 1535 */ | 1535 */ |
| 1536 | 1536 |
| 1537 CERTCertificate * | 1537 CERTCertificate * |
| 1538 CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName, | 1538 CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName, |
| 1539 » » CERTCertOwner owner, SECCertUsage usage, | 1539 CERTCertOwner owner, SECCertUsage usage, |
| 1540 » » PRBool preferTrusted, PRTime validTime, PRBool validOnly) | 1540 PRBool preferTrusted, PRTime validTime, PRBool validOnly) |
| 1541 { | 1541 { |
| 1542 CERTCertList *certList = NULL; | 1542 CERTCertList *certList = NULL; |
| 1543 CERTCertificate *cert = NULL; | 1543 CERTCertificate *cert = NULL; |
| 1544 CERTCertTrust certTrust; | 1544 CERTCertTrust certTrust; |
| 1545 unsigned int requiredTrustFlags; | 1545 unsigned int requiredTrustFlags; |
| 1546 SECTrustType requiredTrustType; | 1546 SECTrustType requiredTrustType; |
| 1547 unsigned int flags; | 1547 unsigned int flags; |
| 1548 | 1548 |
| 1549 PRBool lookingForCA = PR_FALSE; | 1549 PRBool lookingForCA = PR_FALSE; |
| 1550 SECStatus rv; | 1550 SECStatus rv; |
| 1551 CERTCertListNode *node; | 1551 CERTCertListNode *node; |
| 1552 CERTCertificate *saveUntrustedCA = NULL; | 1552 CERTCertificate *saveUntrustedCA = NULL; |
| 1553 | 1553 |
| 1554 /* if preferTrusted is set, must be a CA cert */ | 1554 /* if preferTrusted is set, must be a CA cert */ |
| 1555 PORT_Assert( ! ( preferTrusted && ( owner != certOwnerCA ) ) ); | 1555 PORT_Assert(!(preferTrusted && (owner != certOwnerCA))); |
| 1556 | 1556 |
| 1557 if ( owner == certOwnerCA ) { | 1557 if (owner == certOwnerCA) { |
| 1558 » lookingForCA = PR_TRUE; | 1558 lookingForCA = PR_TRUE; |
| 1559 » if ( preferTrusted ) { | 1559 if (preferTrusted) { |
| 1560 » rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags, | 1560 rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags, |
| 1561 » » » » » &requiredTrustType); | 1561 &requiredTrustType); |
| 1562 » if ( rv != SECSuccess ) { | 1562 if (rv != SECSuccess) { |
| 1563 » » goto loser; | 1563 goto loser; |
| 1564 » } | 1564 } |
| 1565 » requiredTrustFlags |= CERTDB_VALID_CA; | 1565 requiredTrustFlags |= CERTDB_VALID_CA; |
| 1566 » } | 1566 } |
| 1567 } | 1567 } |
| 1568 | 1568 |
| 1569 certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime, | 1569 certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime, |
| 1570 » » » » » validOnly); | 1570 validOnly); |
| 1571 if ( certList != NULL ) { | 1571 if (certList != NULL) { |
| 1572 » rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA); | 1572 rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA); |
| 1573 » if ( rv != SECSuccess ) { | 1573 if (rv != SECSuccess) { |
| 1574 » goto loser; | 1574 goto loser; |
| 1575 » } | 1575 } |
| 1576 » | |
| 1577 » node = CERT_LIST_HEAD(certList); | |
| 1578 » | |
| 1579 » while ( !CERT_LIST_END(node, certList) ) { | |
| 1580 » cert = node->cert; | |
| 1581 | 1576 |
| 1582 » /* looking for a trusted CA cert */ | 1577 node = CERT_LIST_HEAD(certList); |
| 1583 » if ( ( owner == certOwnerCA ) && preferTrusted && | |
| 1584 » » ( requiredTrustType != trustTypeNone ) ) { | |
| 1585 | 1578 |
| 1586 » » if ( CERT_GetCertTrust(cert, &certTrust) != SECSuccess ) { | 1579 while (!CERT_LIST_END(node, certList)) { |
| 1587 » » flags = 0; | 1580 cert = node->cert; |
| 1588 » » } else { | |
| 1589 » » flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType); | |
| 1590 » » } | |
| 1591 | 1581 |
| 1592 » » if ( ( flags & requiredTrustFlags ) != requiredTrustFlags ) { | 1582 /* looking for a trusted CA cert */ |
| 1593 » » /* cert is not trusted */ | 1583 if ((owner == certOwnerCA) && preferTrusted && |
| 1594 » » /* if this is the first cert to get this far, then save | 1584 (requiredTrustType != trustTypeNone)) { |
| 1595 » » * it, so we can use it if we can't find a trusted one | |
| 1596 » » */ | |
| 1597 » » if ( saveUntrustedCA == NULL ) { | |
| 1598 » » » saveUntrustedCA = cert; | |
| 1599 » » } | |
| 1600 » » goto endloop; | |
| 1601 » » } | |
| 1602 » } | |
| 1603 » /* if we got this far, then this cert meets all criteria */ | |
| 1604 » break; | |
| 1605 » | |
| 1606 endloop: | |
| 1607 » node = CERT_LIST_NEXT(node); | |
| 1608 » cert = NULL; | |
| 1609 » } | |
| 1610 | 1585 |
| 1611 » /* use the saved one if we have it */ | 1586 if (CERT_GetCertTrust(cert, &certTrust) != SECSuccess) { |
| 1612 » if ( cert == NULL ) { | 1587 flags = 0; |
| 1613 » cert = saveUntrustedCA; | 1588 } else { |
| 1614 » } | 1589 flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType); |
| 1590 } |
| 1615 | 1591 |
| 1616 » /* if we found one then bump the ref count before freeing the list */ | 1592 if ((flags & requiredTrustFlags) != requiredTrustFlags) { |
| 1617 » if ( cert != NULL ) { | 1593 /* cert is not trusted */ |
| 1618 » /* bump the ref count */ | 1594 /* if this is the first cert to get this far, then save |
| 1619 » cert = CERT_DupCertificate(cert); | 1595 * it, so we can use it if we can't find a trusted one |
| 1620 » } | 1596 */ |
| 1621 » | 1597 if (saveUntrustedCA == NULL) { |
| 1622 » CERT_DestroyCertList(certList); | 1598 saveUntrustedCA = cert; |
| 1599 } |
| 1600 goto endloop; |
| 1601 } |
| 1602 } |
| 1603 /* if we got this far, then this cert meets all criteria */ |
| 1604 break; |
| 1605 |
| 1606 endloop: |
| 1607 node = CERT_LIST_NEXT(node); |
| 1608 cert = NULL; |
| 1609 } |
| 1610 |
| 1611 /* use the saved one if we have it */ |
| 1612 if (cert == NULL) { |
| 1613 cert = saveUntrustedCA; |
| 1614 } |
| 1615 |
| 1616 /* if we found one then bump the ref count before freeing the list */ |
| 1617 if (cert != NULL) { |
| 1618 /* bump the ref count */ |
| 1619 cert = CERT_DupCertificate(cert); |
| 1620 } |
| 1621 |
| 1622 CERT_DestroyCertList(certList); |
| 1623 } | 1623 } |
| 1624 | 1624 |
| 1625 return(cert); | 1625 return (cert); |
| 1626 | 1626 |
| 1627 loser: | 1627 loser: |
| 1628 if ( certList != NULL ) { | 1628 if (certList != NULL) { |
| 1629 » CERT_DestroyCertList(certList); | 1629 CERT_DestroyCertList(certList); |
| 1630 } | 1630 } |
| 1631 | 1631 |
| 1632 return(NULL); | 1632 return (NULL); |
| 1633 } | 1633 } |
| 1634 | 1634 |
| 1635 | |
| 1636 /* [ From certdb.c ] */ | 1635 /* [ From certdb.c ] */ |
| 1637 /* | 1636 /* |
| 1638 * Filter a list of certificates, removing those certs that do not have | 1637 * Filter a list of certificates, removing those certs that do not have |
| 1639 * one of the named CA certs somewhere in their cert chain. | 1638 * one of the named CA certs somewhere in their cert chain. |
| 1640 * | 1639 * |
| 1641 *» "certList" - the list of certificates to filter | 1640 * "certList" - the list of certificates to filter |
| 1642 *» "nCANames" - number of CA names | 1641 * "nCANames" - number of CA names |
| 1643 *» "caNames" - array of CA names in string(rfc 1485) form | 1642 * "caNames" - array of CA names in string(rfc 1485) form |
| 1644 *» "usage" - what use the certs are for, this is used when | 1643 * "usage" - what use the certs are for, this is used when |
| 1645 *» » selecting CA certs | 1644 * selecting CA certs |
| 1646 */ | 1645 */ |
| 1647 SECStatus | 1646 SECStatus |
| 1648 CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames, | 1647 CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames, |
| 1649 » » » char **caNames, SECCertUsage usage) | 1648 char **caNames, SECCertUsage usage) |
| 1650 { | 1649 { |
| 1651 CERTCertificate *issuerCert = NULL; | 1650 CERTCertificate *issuerCert = NULL; |
| 1652 CERTCertificate *subjectCert; | 1651 CERTCertificate *subjectCert; |
| 1653 CERTCertListNode *node, *freenode; | 1652 CERTCertListNode *node, *freenode; |
| 1654 CERTCertificate *cert; | 1653 CERTCertificate *cert; |
| 1655 int n; | 1654 int n; |
| 1656 char **names; | 1655 char **names; |
| 1657 PRBool found; | 1656 PRBool found; |
| 1658 PRTime time; | 1657 PRTime time; |
| 1659 | 1658 |
| 1660 if ( nCANames <= 0 ) { | 1659 if (nCANames <= 0) { |
| 1661 » return(SECSuccess); | 1660 return (SECSuccess); |
| 1662 } | 1661 } |
| 1663 | 1662 |
| 1664 time = PR_Now(); | 1663 time = PR_Now(); |
| 1665 | 1664 |
| 1666 node = CERT_LIST_HEAD(certList); | 1665 node = CERT_LIST_HEAD(certList); |
| 1667 | |
| 1668 while ( ! CERT_LIST_END(node, certList) ) { | |
| 1669 cert = node->cert; | |
| 1670 | |
| 1671 subjectCert = CERT_DupCertificate(cert); | |
| 1672 | 1666 |
| 1673 » /* traverse the CA certs for this cert */ | 1667 while (!CERT_LIST_END(node, certList)) { |
| 1674 » found = PR_FALSE; | 1668 cert = node->cert; |
| 1675 » while ( subjectCert != NULL ) { | |
| 1676 » n = nCANames; | |
| 1677 » names = caNames; | |
| 1678 » | |
| 1679 if (subjectCert->issuerName != NULL) { | |
| 1680 » while ( n > 0 ) { | |
| 1681 » » if ( PORT_Strcmp(*names, subjectCert->issuerName) == 0 ) { | |
| 1682 » » found = PR_TRUE; | |
| 1683 » » break; | |
| 1684 » » } | |
| 1685 | 1669 |
| 1686 » » n--; | 1670 subjectCert = CERT_DupCertificate(cert); |
| 1687 » » names++; | 1671 |
| 1672 /* traverse the CA certs for this cert */ |
| 1673 found = PR_FALSE; |
| 1674 while (subjectCert != NULL) { |
| 1675 n = nCANames; |
| 1676 names = caNames; |
| 1677 |
| 1678 if (subjectCert->issuerName != NULL) { |
| 1679 while (n > 0) { |
| 1680 if (PORT_Strcmp(*names, subjectCert->issuerName) == 0) { |
| 1681 found = PR_TRUE; |
| 1682 break; |
| 1683 } |
| 1684 |
| 1685 n--; |
| 1686 names++; |
| 1688 } | 1687 } |
| 1689 » } | 1688 } |
| 1690 | 1689 |
| 1691 » if ( found ) { | 1690 if (found) { |
| 1692 » » break; | 1691 break; |
| 1693 » } | 1692 } |
| 1694 » | |
| 1695 » issuerCert = CERT_FindCertIssuer(subjectCert, time, usage); | |
| 1696 » if ( issuerCert == subjectCert ) { | |
| 1697 » » CERT_DestroyCertificate(issuerCert); | |
| 1698 » » issuerCert = NULL; | |
| 1699 » » break; | |
| 1700 » } | |
| 1701 » CERT_DestroyCertificate(subjectCert); | |
| 1702 » subjectCert = issuerCert; | |
| 1703 | 1693 |
| 1704 » } | 1694 issuerCert = CERT_FindCertIssuer(subjectCert, time, usage); |
| 1705 » CERT_DestroyCertificate(subjectCert); | 1695 if (issuerCert == subjectCert) { |
| 1706 » if ( !found ) { | 1696 CERT_DestroyCertificate(issuerCert); |
| 1707 » /* CA was not found, so remove this cert from the list */ | 1697 issuerCert = NULL; |
| 1708 » freenode = node; | 1698 break; |
| 1709 » node = CERT_LIST_NEXT(node); | 1699 } |
| 1710 » CERT_RemoveCertListNode(freenode); | 1700 CERT_DestroyCertificate(subjectCert); |
| 1711 » } else { | 1701 subjectCert = issuerCert; |
| 1712 » /* CA was found, so leave it in the list */ | 1702 } |
| 1713 » node = CERT_LIST_NEXT(node); | 1703 CERT_DestroyCertificate(subjectCert); |
| 1714 » } | 1704 if (!found) { |
| 1705 /* CA was not found, so remove this cert from the list */ |
| 1706 freenode = node; |
| 1707 node = CERT_LIST_NEXT(node); |
| 1708 CERT_RemoveCertListNode(freenode); |
| 1709 } else { |
| 1710 /* CA was found, so leave it in the list */ |
| 1711 node = CERT_LIST_NEXT(node); |
| 1712 } |
| 1715 } | 1713 } |
| 1716 | 1714 |
| 1717 return(SECSuccess); | 1715 return (SECSuccess); |
| 1718 } | 1716 } |
| 1719 | 1717 |
| 1720 /* | 1718 /* |
| 1721 * Given a certificate, return a string containing the nickname, and possibly | 1719 * Given a certificate, return a string containing the nickname, and possibly |
| 1722 * one of the validity strings, based on the current validity state of the | 1720 * one of the validity strings, based on the current validity state of the |
| 1723 * certificate. | 1721 * certificate. |
| 1724 * | 1722 * |
| 1725 * "arena" - arena to allocate returned string from. If NULL, then heap | 1723 * "arena" - arena to allocate returned string from. If NULL, then heap |
| 1726 *» is used. | 1724 * is used. |
| 1727 * "cert" - the cert to get nickname from | 1725 * "cert" - the cert to get nickname from |
| 1728 * "expiredString" - the string to append to the nickname if the cert is | 1726 * "expiredString" - the string to append to the nickname if the cert is |
| 1729 *» » expired. | 1727 * expired. |
| 1730 * "notYetGoodString" - the string to append to the nickname if the cert is | 1728 * "notYetGoodString" - the string to append to the nickname if the cert is |
| 1731 *» » not yet good. | 1729 * not yet good. |
| 1732 */ | 1730 */ |
| 1733 char * | 1731 char * |
| 1734 CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert, | 1732 CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert, |
| 1735 » » » » char *expiredString, char *notYetGoodString) | 1733 char *expiredString, char *notYetGoodString) |
| 1736 { | 1734 { |
| 1737 SECCertTimeValidity validity; | 1735 SECCertTimeValidity validity; |
| 1738 char *nickname = NULL, *tmpstr = NULL; | 1736 char *nickname = NULL, *tmpstr = NULL; |
| 1739 | 1737 |
| 1740 validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE); | 1738 validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE); |
| 1741 | 1739 |
| 1742 /* if the cert is good, then just use the nickname directly */ | 1740 /* if the cert is good, then just use the nickname directly */ |
| 1743 if ( validity == secCertTimeValid ) { | 1741 if (validity == secCertTimeValid) { |
| 1744 » if ( arena == NULL ) { | 1742 if (arena == NULL) { |
| 1745 » nickname = PORT_Strdup(cert->nickname); | 1743 nickname = PORT_Strdup(cert->nickname); |
| 1746 » } else { | 1744 } else { |
| 1747 » nickname = PORT_ArenaStrdup(arena, cert->nickname); | 1745 nickname = PORT_ArenaStrdup(arena, cert->nickname); |
| 1748 » } | 1746 } |
| 1749 » | 1747 |
| 1750 » if ( nickname == NULL ) { | 1748 if (nickname == NULL) { |
| 1751 » goto loser; | 1749 goto loser; |
| 1752 » } | 1750 } |
| 1753 } else { | 1751 } else { |
| 1754 » | 1752 |
| 1755 » /* if the cert is not valid, then tack one of the strings on the | 1753 /* if the cert is not valid, then tack one of the strings on the |
| 1756 » * end | 1754 * end |
| 1757 » */ | 1755 */ |
| 1758 » if ( validity == secCertTimeExpired ) { | 1756 if (validity == secCertTimeExpired) { |
| 1759 » tmpstr = PR_smprintf("%s%s", cert->nickname, | 1757 tmpstr = PR_smprintf("%s%s", cert->nickname, |
| 1760 » » » » expiredString); | 1758 expiredString); |
| 1761 » } else if ( validity == secCertTimeNotValidYet ) { | 1759 } else if (validity == secCertTimeNotValidYet) { |
| 1762 » /* not yet valid */ | 1760 /* not yet valid */ |
| 1763 » tmpstr = PR_smprintf("%s%s", cert->nickname, | 1761 tmpstr = PR_smprintf("%s%s", cert->nickname, |
| 1764 » » » » notYetGoodString); | 1762 notYetGoodString); |
| 1765 } else { | 1763 } else { |
| 1766 /* undetermined */ | 1764 /* undetermined */ |
| 1767 » tmpstr = PR_smprintf("%s", | 1765 tmpstr = PR_smprintf("%s", |
| 1768 "(NULL) (Validity Unknown)"); | 1766 "(NULL) (Validity Unknown)"); |
| 1769 } | 1767 } |
| 1770 | 1768 |
| 1771 » if ( tmpstr == NULL ) { | 1769 if (tmpstr == NULL) { |
| 1772 » goto loser; | 1770 goto loser; |
| 1773 » } | 1771 } |
| 1774 | 1772 |
| 1775 » if ( arena ) { | 1773 if (arena) { |
| 1776 » /* copy the string into the arena and free the malloc'd one */ | 1774 /* copy the string into the arena and free the malloc'd one */ |
| 1777 » nickname = PORT_ArenaStrdup(arena, tmpstr); | 1775 nickname = PORT_ArenaStrdup(arena, tmpstr); |
| 1778 » PORT_Free(tmpstr); | 1776 PORT_Free(tmpstr); |
| 1779 » } else { | 1777 } else { |
| 1780 » nickname = tmpstr; | 1778 nickname = tmpstr; |
| 1781 » } | 1779 } |
| 1782 » if ( nickname == NULL ) { | 1780 if (nickname == NULL) { |
| 1783 » goto loser; | 1781 goto loser; |
| 1784 » } | 1782 } |
| 1785 } | 1783 } |
| 1786 return(nickname); | 1784 return (nickname); |
| 1787 | 1785 |
| 1788 loser: | 1786 loser: |
| 1789 return(NULL); | 1787 return (NULL); |
| 1790 } | 1788 } |
| 1791 | 1789 |
| 1792 /* | 1790 /* |
| 1793 * Collect the nicknames from all certs in a CertList. If the cert is not | 1791 * Collect the nicknames from all certs in a CertList. If the cert is not |
| 1794 * valid, append a string to that nickname. | 1792 * valid, append a string to that nickname. |
| 1795 * | 1793 * |
| 1796 * "certList" - the list of certificates | 1794 * "certList" - the list of certificates |
| 1797 * "expiredString" - the string to append to the nickname of any expired cert | 1795 * "expiredString" - the string to append to the nickname of any expired cert |
| 1798 * "notYetGoodString" - the string to append to the nickname of any cert | 1796 * "notYetGoodString" - the string to append to the nickname of any cert |
| 1799 *» » that is not yet valid | 1797 * that is not yet valid |
| 1800 */ | 1798 */ |
| 1801 CERTCertNicknames * | 1799 CERTCertNicknames * |
| 1802 CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString, | 1800 CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString, |
| 1803 » » » » char *notYetGoodString) | 1801 char *notYetGoodString) |
| 1804 { | 1802 { |
| 1805 CERTCertNicknames *names; | 1803 CERTCertNicknames *names; |
| 1806 PLArenaPool *arena; | 1804 PLArenaPool *arena; |
| 1807 CERTCertListNode *node; | 1805 CERTCertListNode *node; |
| 1808 char **nn; | 1806 char **nn; |
| 1809 | 1807 |
| 1810 /* allocate an arena */ | 1808 /* allocate an arena */ |
| 1811 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 1809 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 1812 if ( arena == NULL ) { | 1810 if (arena == NULL) { |
| 1813 » return(NULL); | 1811 return (NULL); |
| 1814 } | 1812 } |
| 1815 | 1813 |
| 1816 /* allocate the structure */ | 1814 /* allocate the structure */ |
| 1817 names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames)); | 1815 names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames)); |
| 1818 if ( names == NULL ) { | 1816 if (names == NULL) { |
| 1819 » goto loser; | 1817 goto loser; |
| 1820 } | 1818 } |
| 1821 | 1819 |
| 1822 /* init the structure */ | 1820 /* init the structure */ |
| 1823 names->arena = arena; | 1821 names->arena = arena; |
| 1824 names->head = NULL; | 1822 names->head = NULL; |
| 1825 names->numnicknames = 0; | 1823 names->numnicknames = 0; |
| 1826 names->nicknames = NULL; | 1824 names->nicknames = NULL; |
| 1827 names->totallen = 0; | 1825 names->totallen = 0; |
| 1828 | 1826 |
| 1829 /* count the certs in the list */ | 1827 /* count the certs in the list */ |
| 1830 node = CERT_LIST_HEAD(certList); | 1828 node = CERT_LIST_HEAD(certList); |
| 1831 while ( ! CERT_LIST_END(node, certList) ) { | 1829 while (!CERT_LIST_END(node, certList)) { |
| 1832 » names->numnicknames++; | 1830 names->numnicknames++; |
| 1833 » node = CERT_LIST_NEXT(node); | 1831 node = CERT_LIST_NEXT(node); |
| 1834 } | 1832 } |
| 1835 | 1833 |
| 1836 /* allocate nicknames array */ | 1834 /* allocate nicknames array */ |
| 1837 names->nicknames = PORT_ArenaAlloc(arena, | 1835 names->nicknames = PORT_ArenaAlloc(arena, |
| 1838 » » » » sizeof(char *) * names->numnicknames); | 1836 sizeof(char *) * names->numnicknames); |
| 1839 if ( names->nicknames == NULL ) { | 1837 if (names->nicknames == NULL) { |
| 1840 » goto loser; | 1838 goto loser; |
| 1841 } | 1839 } |
| 1842 | 1840 |
| 1843 /* just in case printf can't deal with null strings */ | 1841 /* just in case printf can't deal with null strings */ |
| 1844 if (expiredString == NULL ) { | 1842 if (expiredString == NULL) { |
| 1845 » expiredString = ""; | 1843 expiredString = ""; |
| 1846 } | 1844 } |
| 1847 | 1845 |
| 1848 if ( notYetGoodString == NULL ) { | 1846 if (notYetGoodString == NULL) { |
| 1849 » notYetGoodString = ""; | 1847 notYetGoodString = ""; |
| 1850 } | 1848 } |
| 1851 | 1849 |
| 1852 /* traverse the list of certs and collect the nicknames */ | 1850 /* traverse the list of certs and collect the nicknames */ |
| 1853 nn = names->nicknames; | 1851 nn = names->nicknames; |
| 1854 node = CERT_LIST_HEAD(certList); | 1852 node = CERT_LIST_HEAD(certList); |
| 1855 while ( ! CERT_LIST_END(node, certList) ) { | 1853 while (!CERT_LIST_END(node, certList)) { |
| 1856 » *nn = CERT_GetCertNicknameWithValidity(arena, node->cert, | 1854 *nn = CERT_GetCertNicknameWithValidity(arena, node->cert, |
| 1857 » » » » » expiredString, | 1855 expiredString, |
| 1858 » » » » » notYetGoodString); | 1856 notYetGoodString); |
| 1859 » if ( *nn == NULL ) { | 1857 if (*nn == NULL) { |
| 1860 » goto loser; | 1858 goto loser; |
| 1861 » } | 1859 } |
| 1862 | 1860 |
| 1863 » names->totallen += PORT_Strlen(*nn); | 1861 names->totallen += PORT_Strlen(*nn); |
| 1864 » | 1862 |
| 1865 » nn++; | 1863 nn++; |
| 1866 » node = CERT_LIST_NEXT(node); | 1864 node = CERT_LIST_NEXT(node); |
| 1867 } | 1865 } |
| 1868 | 1866 |
| 1869 return(names); | 1867 return (names); |
| 1870 | 1868 |
| 1871 loser: | 1869 loser: |
| 1872 PORT_FreeArena(arena, PR_FALSE); | 1870 PORT_FreeArena(arena, PR_FALSE); |
| 1873 return(NULL); | 1871 return (NULL); |
| 1874 } | 1872 } |
| 1875 | 1873 |
| 1876 /* | 1874 /* |
| 1877 * Extract the nickname from a nickmake string that may have either | 1875 * Extract the nickname from a nickmake string that may have either |
| 1878 * expiredString or notYetGoodString appended. | 1876 * expiredString or notYetGoodString appended. |
| 1879 * | 1877 * |
| 1880 * Args: | 1878 * Args: |
| 1881 *» "namestring" - the string containing the nickname, and possibly | 1879 * "namestring" - the string containing the nickname, and possibly |
| 1882 *» » one of the validity label strings | 1880 * one of the validity label strings |
| 1883 *» "expiredString" - the expired validity label string | 1881 * "expiredString" - the expired validity label string |
| 1884 *» "notYetGoodString" - the not yet good validity label string | 1882 * "notYetGoodString" - the not yet good validity label string |
| 1885 * | 1883 * |
| 1886 * Returns the raw nickname | 1884 * Returns the raw nickname |
| 1887 */ | 1885 */ |
| 1888 char * | 1886 char * |
| 1889 CERT_ExtractNicknameString(char *namestring, char *expiredString, | 1887 CERT_ExtractNicknameString(char *namestring, char *expiredString, |
| 1890 » » » char *notYetGoodString) | 1888 char *notYetGoodString) |
| 1891 { | 1889 { |
| 1892 int explen, nyglen, namelen; | 1890 int explen, nyglen, namelen; |
| 1893 int retlen; | 1891 int retlen; |
| 1894 char *retstr; | 1892 char *retstr; |
| 1895 | 1893 |
| 1896 namelen = PORT_Strlen(namestring); | 1894 namelen = PORT_Strlen(namestring); |
| 1897 explen = PORT_Strlen(expiredString); | 1895 explen = PORT_Strlen(expiredString); |
| 1898 nyglen = PORT_Strlen(notYetGoodString); | 1896 nyglen = PORT_Strlen(notYetGoodString); |
| 1899 | 1897 |
| 1900 if ( namelen > explen ) { | 1898 if (namelen > explen) { |
| 1901 » if ( PORT_Strcmp(expiredString, &namestring[namelen-explen]) == 0 ) { | 1899 if (PORT_Strcmp(expiredString, &namestring[namelen - explen]) == 0) { |
| 1902 » retlen = namelen - explen; | 1900 retlen = namelen - explen; |
| 1903 » retstr = (char *)PORT_Alloc(retlen+1); | 1901 retstr = (char *)PORT_Alloc(retlen + 1); |
| 1904 » if ( retstr == NULL ) { | 1902 if (retstr == NULL) { |
| 1905 » » goto loser; | 1903 goto loser; |
| 1906 » } | 1904 } |
| 1907 » | 1905 |
| 1908 » PORT_Memcpy(retstr, namestring, retlen); | 1906 PORT_Memcpy(retstr, namestring, retlen); |
| 1909 » retstr[retlen] = '\0'; | 1907 retstr[retlen] = '\0'; |
| 1910 » goto done; | 1908 goto done; |
| 1911 » } | 1909 } |
| 1912 } | 1910 } |
| 1913 | 1911 |
| 1914 if ( namelen > nyglen ) { | 1912 if (namelen > nyglen) { |
| 1915 » if ( PORT_Strcmp(notYetGoodString, &namestring[namelen-nyglen]) == 0) { | 1913 if (PORT_Strcmp(notYetGoodString, &namestring[namelen - nyglen]) == 0) { |
| 1916 » retlen = namelen - nyglen; | 1914 retlen = namelen - nyglen; |
| 1917 » retstr = (char *)PORT_Alloc(retlen+1); | 1915 retstr = (char *)PORT_Alloc(retlen + 1); |
| 1918 » if ( retstr == NULL ) { | 1916 if (retstr == NULL) { |
| 1919 » » goto loser; | 1917 goto loser; |
| 1920 » } | 1918 } |
| 1921 » | 1919 |
| 1922 » PORT_Memcpy(retstr, namestring, retlen); | 1920 PORT_Memcpy(retstr, namestring, retlen); |
| 1923 » retstr[retlen] = '\0'; | 1921 retstr[retlen] = '\0'; |
| 1924 » goto done; | 1922 goto done; |
| 1925 » } | 1923 } |
| 1926 } | 1924 } |
| 1927 | 1925 |
| 1928 /* if name string is shorter than either invalid string, then it must | 1926 /* if name string is shorter than either invalid string, then it must |
| 1929 * be a raw nickname | 1927 * be a raw nickname |
| 1930 */ | 1928 */ |
| 1931 retstr = PORT_Strdup(namestring); | 1929 retstr = PORT_Strdup(namestring); |
| 1932 | 1930 |
| 1933 done: | 1931 done: |
| 1934 return(retstr); | 1932 return (retstr); |
| 1935 | 1933 |
| 1936 loser: | 1934 loser: |
| 1937 return(NULL); | 1935 return (NULL); |
| 1938 } | 1936 } |
| 1939 | 1937 |
| 1940 CERTCertList * | 1938 CERTCertList * |
| 1941 CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage
) | 1939 CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage
) |
| 1942 { | 1940 { |
| 1943 CERTCertList *chain = NULL; | 1941 CERTCertList *chain = NULL; |
| 1944 int count = 0; | 1942 int count = 0; |
| 1945 | 1943 |
| 1946 if (NULL == cert) { | 1944 if (NULL == cert) { |
| 1947 return NULL; | 1945 return NULL; |
| 1948 } | 1946 } |
| 1949 | 1947 |
| 1950 cert = CERT_DupCertificate(cert); | 1948 cert = CERT_DupCertificate(cert); |
| 1951 if (NULL == cert) { | 1949 if (NULL == cert) { |
| 1952 PORT_SetError(SEC_ERROR_NO_MEMORY); | 1950 PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 1953 return NULL; | 1951 return NULL; |
| 1954 } | 1952 } |
| 1955 | 1953 |
| 1956 chain = CERT_NewCertList(); | 1954 chain = CERT_NewCertList(); |
| 1957 if (NULL == chain) { | 1955 if (NULL == chain) { |
| 1958 PORT_SetError(SEC_ERROR_NO_MEMORY); | 1956 PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 1959 return NULL; | 1957 return NULL; |
| 1960 } | 1958 } |
| 1961 | 1959 |
| 1962 while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) { | 1960 while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) { |
| 1963 » if (SECSuccess != CERT_AddCertToListTail(chain, cert)) { | 1961 if (SECSuccess != CERT_AddCertToListTail(chain, cert)) { |
| 1964 /* return partial chain */ | 1962 /* return partial chain */ |
| 1965 PORT_SetError(SEC_ERROR_NO_MEMORY); | 1963 PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 1966 return chain; | 1964 return chain; |
| 1967 } | 1965 } |
| 1968 | 1966 |
| 1969 » if (cert->isRoot) { | 1967 if (cert->isRoot) { |
| 1970 /* return complete chain */ | 1968 /* return complete chain */ |
| 1971 » return chain; | 1969 return chain; |
| 1972 » } | 1970 } |
| 1973 | 1971 |
| 1974 » cert = CERT_FindCertIssuer(cert, time, usage); | 1972 cert = CERT_FindCertIssuer(cert, time, usage); |
| 1975 } | 1973 } |
| 1976 | 1974 |
| 1977 /* return partial chain */ | 1975 /* return partial chain */ |
| 1978 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); | 1976 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); |
| 1979 return chain; | 1977 return chain; |
| 1980 } | 1978 } |
| OLD | NEW |