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