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 |