OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | 4 |
5 /* | 5 /* |
6 * Moved from secpkcs7.c | 6 * Moved from secpkcs7.c |
7 */ | 7 */ |
8 | 8 |
9 #include "cert.h" | 9 #include "cert.h" |
10 #include "certi.h" | 10 #include "certi.h" |
11 #include "secder.h" | 11 #include "secder.h" |
12 #include "secasn1.h" | 12 #include "secasn1.h" |
13 #include "secoid.h" | 13 #include "secoid.h" |
14 #include "certdb.h" | 14 #include "certdb.h" |
15 #include "certxutl.h" | 15 #include "certxutl.h" |
16 #include "prtime.h" | 16 #include "prtime.h" |
17 #include "secerr.h" | 17 #include "secerr.h" |
18 #include "pk11func.h" | 18 #include "pk11func.h" |
19 #include "dev.h" | 19 #include "dev.h" |
20 #include "dev3hack.h" | 20 #include "dev3hack.h" |
21 #include "nssbase.h" | 21 #include "nssbase.h" |
22 #if defined(DPC_RWLOCK) || defined(GLOBAL_RWLOCK) | 22 #if defined(DPC_RWLOCK) || defined(GLOBAL_RWLOCK) |
23 #include "nssrwlk.h" | 23 #include "nssrwlk.h" |
24 #endif | 24 #endif |
25 #include "pk11priv.h" | 25 #include "pk11priv.h" |
26 | 26 |
27 const SEC_ASN1Template SEC_CERTExtensionTemplate[] = { | 27 const SEC_ASN1Template SEC_CERTExtensionTemplate[] = { |
28 { SEC_ASN1_SEQUENCE, | 28 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCertExtension) }, |
29 » 0, NULL, sizeof(CERTCertExtension) }, | 29 { SEC_ASN1_OBJECT_ID, offsetof(CERTCertExtension, id) }, |
30 { SEC_ASN1_OBJECT_ID, | 30 { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */ |
31 » offsetof(CERTCertExtension,id) }, | 31 offsetof(CERTCertExtension, critical) }, |
32 { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,» » /* XXX DER_DEFAULT */ | 32 { SEC_ASN1_OCTET_STRING, offsetof(CERTCertExtension, value) }, |
33 » offsetof(CERTCertExtension,critical), }, | 33 { 0 } |
34 { SEC_ASN1_OCTET_STRING, | |
35 » offsetof(CERTCertExtension,value) }, | |
36 { 0, } | |
37 }; | 34 }; |
38 | 35 |
39 static const SEC_ASN1Template SEC_CERTExtensionsTemplate[] = { | 36 static const SEC_ASN1Template SEC_CERTExtensionsTemplate[] = { |
40 { SEC_ASN1_SEQUENCE_OF, 0, SEC_CERTExtensionTemplate} | 37 { SEC_ASN1_SEQUENCE_OF, 0, SEC_CERTExtensionTemplate } |
41 }; | 38 }; |
42 | 39 |
43 /* | 40 /* |
44 * XXX Also, these templates need to be tested; Lisa did the obvious | 41 * XXX Also, these templates need to be tested; Lisa did the obvious |
45 * translation but they still should be verified. | 42 * translation but they still should be verified. |
46 */ | 43 */ |
47 | 44 |
48 const SEC_ASN1Template CERT_IssuerAndSNTemplate[] = { | 45 const SEC_ASN1Template CERT_IssuerAndSNTemplate[] = { |
49 { SEC_ASN1_SEQUENCE, | 46 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTIssuerAndSN) }, |
50 » 0, NULL, sizeof(CERTIssuerAndSN) }, | 47 { SEC_ASN1_SAVE, offsetof(CERTIssuerAndSN, derIssuer) }, |
51 { SEC_ASN1_SAVE, | 48 { SEC_ASN1_INLINE, offsetof(CERTIssuerAndSN, issuer), CERT_NameTemplate }, |
52 » offsetof(CERTIssuerAndSN,derIssuer) }, | 49 { SEC_ASN1_INTEGER, offsetof(CERTIssuerAndSN, serialNumber) }, |
53 { SEC_ASN1_INLINE, | |
54 » offsetof(CERTIssuerAndSN,issuer), | |
55 » CERT_NameTemplate }, | |
56 { SEC_ASN1_INTEGER, | |
57 » offsetof(CERTIssuerAndSN,serialNumber) }, | |
58 { 0 } | 50 { 0 } |
59 }; | 51 }; |
60 | 52 |
61 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) | 53 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
62 SEC_ASN1_MKSUB(CERT_TimeChoiceTemplate) | 54 SEC_ASN1_MKSUB(CERT_TimeChoiceTemplate) |
63 | 55 |
64 static const SEC_ASN1Template cert_CrlKeyTemplate[] = { | 56 static const SEC_ASN1Template cert_CrlKeyTemplate[] = { |
65 { SEC_ASN1_SEQUENCE, | 57 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCrlKey) }, |
66 » 0, NULL, sizeof(CERTCrlKey) }, | 58 { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(CERTCrlKey, dummy) }, |
67 { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(CERTCrlKey,dummy) }, | |
68 { SEC_ASN1_SKIP }, | 59 { SEC_ASN1_SKIP }, |
69 { SEC_ASN1_ANY, offsetof(CERTCrlKey,derName) }, | 60 { SEC_ASN1_ANY, offsetof(CERTCrlKey, derName) }, |
70 { SEC_ASN1_SKIP_REST }, | 61 { SEC_ASN1_SKIP_REST }, |
71 { 0 } | 62 { 0 } |
72 }; | 63 }; |
73 | 64 |
74 static const SEC_ASN1Template cert_CrlEntryTemplate[] = { | 65 static const SEC_ASN1Template cert_CrlEntryTemplate[] = { |
75 { SEC_ASN1_SEQUENCE, | 66 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCrlEntry) }, |
76 » 0, NULL, sizeof(CERTCrlEntry) }, | 67 { SEC_ASN1_INTEGER, offsetof(CERTCrlEntry, serialNumber) }, |
77 { SEC_ASN1_INTEGER, | 68 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(CERTCrlEntry, revocationDate), |
78 » offsetof(CERTCrlEntry,serialNumber) }, | 69 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, |
79 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
80 » offsetof(CERTCrlEntry,revocationDate), | |
81 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, | |
82 { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, | 70 { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, |
83 » offsetof(CERTCrlEntry, extensions), | 71 offsetof(CERTCrlEntry, extensions), SEC_CERTExtensionTemplate }, |
84 » SEC_CERTExtensionTemplate}, | |
85 { 0 } | 72 { 0 } |
86 }; | 73 }; |
87 | 74 |
88 const SEC_ASN1Template CERT_CrlTemplate[] = { | 75 const SEC_ASN1Template CERT_CrlTemplate[] = { |
89 { SEC_ASN1_SEQUENCE, | 76 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCrl) }, |
90 » 0, NULL, sizeof(CERTCrl) }, | 77 { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(CERTCrl, version) }, |
91 { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof (CERTCrl, version) }, | 78 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(CERTCrl, signatureAlg), |
92 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | 79 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
93 » offsetof(CERTCrl,signatureAlg), | 80 { SEC_ASN1_SAVE, offsetof(CERTCrl, derName) }, |
94 » SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)}, | 81 { SEC_ASN1_INLINE, offsetof(CERTCrl, name), CERT_NameTemplate }, |
95 { SEC_ASN1_SAVE, | 82 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(CERTCrl, lastUpdate), |
96 » offsetof(CERTCrl,derName) }, | 83 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, |
97 { SEC_ASN1_INLINE, | |
98 » offsetof(CERTCrl,name), | |
99 » CERT_NameTemplate }, | |
100 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
101 » offsetof(CERTCrl,lastUpdate), | |
102 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, | |
103 { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, | 84 { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, |
104 » offsetof(CERTCrl,nextUpdate), | 85 offsetof(CERTCrl, nextUpdate), SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, |
105 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, | 86 { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, offsetof(CERTCrl, entries), |
106 { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, | 87 cert_CrlEntryTemplate }, |
107 » offsetof(CERTCrl,entries), | |
108 » cert_CrlEntryTemplate }, | |
109 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | | 88 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | |
110 » SEC_ASN1_EXPLICIT | 0, | 89 SEC_ASN1_EXPLICIT | 0, |
111 » offsetof(CERTCrl,extensions), | 90 offsetof(CERTCrl, extensions), SEC_CERTExtensionsTemplate }, |
112 » SEC_CERTExtensionsTemplate}, | |
113 { 0 } | 91 { 0 } |
114 }; | 92 }; |
115 | 93 |
116 const SEC_ASN1Template CERT_CrlTemplateNoEntries[] = { | 94 const SEC_ASN1Template CERT_CrlTemplateNoEntries[] = { |
117 { SEC_ASN1_SEQUENCE, | 95 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCrl) }, |
118 » 0, NULL, sizeof(CERTCrl) }, | 96 { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(CERTCrl, version) }, |
119 { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof (CERTCrl, version) }, | 97 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(CERTCrl, signatureAlg), |
120 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | 98 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
121 » offsetof(CERTCrl,signatureAlg), | 99 { SEC_ASN1_SAVE, offsetof(CERTCrl, derName) }, |
122 » SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | 100 { SEC_ASN1_INLINE, offsetof(CERTCrl, name), CERT_NameTemplate }, |
123 { SEC_ASN1_SAVE, | 101 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(CERTCrl, lastUpdate), |
124 » offsetof(CERTCrl,derName) }, | 102 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, |
125 { SEC_ASN1_INLINE, | |
126 » offsetof(CERTCrl,name), | |
127 » CERT_NameTemplate }, | |
128 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
129 » offsetof(CERTCrl,lastUpdate), | |
130 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, | |
131 { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, | 103 { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, |
132 » offsetof(CERTCrl,nextUpdate), | 104 offsetof(CERTCrl, nextUpdate), SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, |
133 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, | |
134 { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF | | 105 { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF | |
135 SEC_ASN1_SKIP }, /* skip entries */ | 106 SEC_ASN1_SKIP }, /* skip entries */ |
136 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | | 107 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | |
137 » SEC_ASN1_EXPLICIT | 0, | 108 SEC_ASN1_EXPLICIT | 0, |
138 » offsetof(CERTCrl,extensions), | 109 offsetof(CERTCrl, extensions), SEC_CERTExtensionsTemplate }, |
139 » SEC_CERTExtensionsTemplate }, | |
140 { 0 } | 110 { 0 } |
141 }; | 111 }; |
142 | 112 |
143 const SEC_ASN1Template CERT_CrlTemplateEntriesOnly[] = { | 113 const SEC_ASN1Template CERT_CrlTemplateEntriesOnly[] = { |
144 { SEC_ASN1_SEQUENCE, | 114 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCrl) }, |
145 » 0, NULL, sizeof(CERTCrl) }, | |
146 { SEC_ASN1_SKIP | SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL }, | 115 { SEC_ASN1_SKIP | SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL }, |
147 { SEC_ASN1_SKIP }, | 116 { SEC_ASN1_SKIP }, |
148 { SEC_ASN1_SKIP }, | 117 { SEC_ASN1_SKIP }, |
149 { SEC_ASN1_SKIP | SEC_ASN1_INLINE | SEC_ASN1_XTRN, | 118 { SEC_ASN1_SKIP | SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
150 offsetof(CERTCrl,lastUpdate), | 119 offsetof(CERTCrl, lastUpdate), SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, |
151 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, | |
152 { SEC_ASN1_SKIP | SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, | 120 { SEC_ASN1_SKIP | SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, |
153 offsetof(CERTCrl,nextUpdate), | 121 offsetof(CERTCrl, nextUpdate), SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, |
154 SEC_ASN1_SUB(CERT_TimeChoiceTemplate) }, | 122 { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, offsetof(CERTCrl, entries), |
155 { SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE_OF, | 123 cert_CrlEntryTemplate }, /* decode entries */ |
156 » offsetof(CERTCrl,entries), | |
157 » cert_CrlEntryTemplate }, /* decode entries */ | |
158 { SEC_ASN1_SKIP_REST }, | 124 { SEC_ASN1_SKIP_REST }, |
159 { 0 } | 125 { 0 } |
160 }; | 126 }; |
161 | 127 |
162 const SEC_ASN1Template CERT_SignedCrlTemplate[] = { | 128 const SEC_ASN1Template CERT_SignedCrlTemplate[] = { |
163 { SEC_ASN1_SEQUENCE, | 129 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTSignedCrl) }, |
164 » 0, NULL, sizeof(CERTSignedCrl) }, | 130 { SEC_ASN1_SAVE, offsetof(CERTSignedCrl, signatureWrap.data) }, |
165 { SEC_ASN1_SAVE, | 131 { SEC_ASN1_INLINE, offsetof(CERTSignedCrl, crl), CERT_CrlTemplate }, |
166 » offsetof(CERTSignedCrl,signatureWrap.data) }, | 132 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
167 { SEC_ASN1_INLINE, | 133 offsetof(CERTSignedCrl, signatureWrap.signatureAlgorithm), |
168 » offsetof(CERTSignedCrl,crl), | 134 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
169 » CERT_CrlTemplate }, | 135 { SEC_ASN1_BIT_STRING, offsetof(CERTSignedCrl, signatureWrap.signature) }, |
170 { SEC_ASN1_INLINE | SEC_ASN1_XTRN , | |
171 » offsetof(CERTSignedCrl,signatureWrap.signatureAlgorithm), | |
172 » SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
173 { SEC_ASN1_BIT_STRING, | |
174 » offsetof(CERTSignedCrl,signatureWrap.signature) }, | |
175 { 0 } | 136 { 0 } |
176 }; | 137 }; |
177 | 138 |
178 static const SEC_ASN1Template cert_SignedCrlTemplateNoEntries[] = { | 139 static const SEC_ASN1Template cert_SignedCrlTemplateNoEntries[] = { |
179 { SEC_ASN1_SEQUENCE, | 140 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTSignedCrl) }, |
180 » 0, NULL, sizeof(CERTSignedCrl) }, | 141 { SEC_ASN1_SAVE, offsetof(CERTSignedCrl, signatureWrap.data) }, |
181 { SEC_ASN1_SAVE, | 142 { SEC_ASN1_INLINE, offsetof(CERTSignedCrl, crl), |
182 » offsetof(CERTSignedCrl,signatureWrap.data) }, | 143 CERT_CrlTemplateNoEntries }, |
183 { SEC_ASN1_INLINE, | |
184 » offsetof(CERTSignedCrl,crl), | |
185 » CERT_CrlTemplateNoEntries }, | |
186 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | 144 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
187 » offsetof(CERTSignedCrl,signatureWrap.signatureAlgorithm), | 145 offsetof(CERTSignedCrl, signatureWrap.signatureAlgorithm), |
188 » SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | 146 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
189 { SEC_ASN1_BIT_STRING, | 147 { SEC_ASN1_BIT_STRING, offsetof(CERTSignedCrl, signatureWrap.signature) }, |
190 » offsetof(CERTSignedCrl,signatureWrap.signature) }, | |
191 { 0 } | 148 { 0 } |
192 }; | 149 }; |
193 | 150 |
194 const SEC_ASN1Template CERT_SetOfSignedCrlTemplate[] = { | 151 const SEC_ASN1Template CERT_SetOfSignedCrlTemplate[] = { |
195 { SEC_ASN1_SET_OF, 0, CERT_SignedCrlTemplate }, | 152 { SEC_ASN1_SET_OF, 0, CERT_SignedCrlTemplate }, |
196 }; | 153 }; |
197 | 154 |
198 /* get CRL version */ | 155 /* get CRL version */ |
199 int cert_get_crl_version(CERTCrl * crl) | 156 int |
| 157 cert_get_crl_version(CERTCrl* crl) |
200 { | 158 { |
201 /* CRL version is defaulted to v1 */ | 159 /* CRL version is defaulted to v1 */ |
202 int version = SEC_CRL_VERSION_1; | 160 int version = SEC_CRL_VERSION_1; |
203 if (crl && crl->version.data != 0) { | 161 if (crl && crl->version.data != 0) { |
204 » version = (int)DER_GetUInteger (&crl->version); | 162 version = (int)DER_GetUInteger(&crl->version); |
205 } | 163 } |
206 return version; | 164 return version; |
207 } | 165 } |
208 | 166 |
209 | |
210 /* check the entries in the CRL */ | 167 /* check the entries in the CRL */ |
211 SECStatus cert_check_crl_entries (CERTCrl *crl) | 168 SECStatus |
| 169 cert_check_crl_entries(CERTCrl* crl) |
212 { | 170 { |
213 CERTCrlEntry **entries; | 171 CERTCrlEntry** entries; |
214 CERTCrlEntry *entry; | 172 CERTCrlEntry* entry; |
215 PRBool hasCriticalExten = PR_FALSE; | 173 PRBool hasCriticalExten = PR_FALSE; |
216 SECStatus rv = SECSuccess; | 174 SECStatus rv = SECSuccess; |
217 | 175 |
218 if (!crl) { | 176 if (!crl) { |
219 return SECFailure; | 177 return SECFailure; |
220 } | 178 } |
221 | 179 |
222 if (crl->entries == NULL) { | 180 if (crl->entries == NULL) { |
223 /* CRLs with no entries are valid */ | 181 /* CRLs with no entries are valid */ |
224 return (SECSuccess); | 182 return (SECSuccess); |
225 } | 183 } |
226 | 184 |
227 /* Look in the crl entry extensions. If there is a critical extension, | 185 /* Look in the crl entry extensions. If there is a critical extension, |
228 then the crl version must be v2; otherwise, it should be v1. | 186 then the crl version must be v2; otherwise, it should be v1. |
229 */ | 187 */ |
230 entries = crl->entries; | 188 entries = crl->entries; |
231 while (*entries) { | 189 while (*entries) { |
232 » entry = *entries; | 190 entry = *entries; |
233 » if (entry->extensions) { | 191 if (entry->extensions) { |
234 » /* If there is a critical extension in the entries, then the | 192 /* If there is a critical extension in the entries, then the |
235 » CRL must be of version 2. If we already saw a critical extension
, | 193 CRL must be of version 2. If we already saw a critical |
236 » there is no need to check the version again. | 194 extension, |
237 » */ | 195 there is no need to check the version again. |
| 196 */ |
238 if (hasCriticalExten == PR_FALSE) { | 197 if (hasCriticalExten == PR_FALSE) { |
239 hasCriticalExten = cert_HasCriticalExtension (entry->extensions)
; | 198 hasCriticalExten = cert_HasCriticalExtension(entry->extensions); |
240 if (hasCriticalExten) { | 199 if (hasCriticalExten) { |
241 if (cert_get_crl_version(crl) != SEC_CRL_VERSION_2) { | 200 if (cert_get_crl_version(crl) != SEC_CRL_VERSION_2) { |
242 /* only CRL v2 critical extensions are supported */ | 201 /* only CRL v2 critical extensions are supported */ |
243 PORT_SetError(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION); | 202 PORT_SetError(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION); |
244 rv = SECFailure; | 203 rv = SECFailure; |
245 break; | 204 break; |
246 } | 205 } |
247 } | 206 } |
248 } | 207 } |
249 | 208 |
250 » /* For each entry, make sure that it does not contain an unknown | 209 /* For each entry, make sure that it does not contain an unknown |
251 » critical extension. If it does, we must reject the CRL since | 210 critical extension. If it does, we must reject the CRL since |
252 » we don't know how to process the extension. | 211 we don't know how to process the extension. |
253 » */ | 212 */ |
254 » if (cert_HasUnknownCriticalExten (entry->extensions) == PR_TRUE) { | 213 if (cert_HasUnknownCriticalExten(entry->extensions) == PR_TRUE) { |
255 » » PORT_SetError (SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION); | 214 PORT_SetError(SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION); |
256 » » rv = SECFailure; | 215 rv = SECFailure; |
257 » » break; | 216 break; |
258 » } | 217 } |
259 » } | 218 } |
260 » ++entries; | 219 ++entries; |
261 } | 220 } |
262 return(rv); | 221 return (rv); |
263 } | 222 } |
264 | 223 |
265 /* Check the version of the CRL. If there is a critical extension in the crl | 224 /* Check the version of the CRL. If there is a critical extension in the crl |
266 or crl entry, then the version must be v2. Otherwise, it should be v1. If | 225 or crl entry, then the version must be v2. Otherwise, it should be v1. If |
267 the crl contains critical extension(s), then we must recognized the | 226 the crl contains critical extension(s), then we must recognized the |
268 extension's OID. | 227 extension's OID. |
269 */ | 228 */ |
270 SECStatus cert_check_crl_version (CERTCrl *crl) | 229 SECStatus |
| 230 cert_check_crl_version(CERTCrl* crl) |
271 { | 231 { |
272 PRBool hasCriticalExten = PR_FALSE; | 232 PRBool hasCriticalExten = PR_FALSE; |
273 int version = cert_get_crl_version(crl); | 233 int version = cert_get_crl_version(crl); |
274 » | 234 |
275 if (version > SEC_CRL_VERSION_2) { | 235 if (version > SEC_CRL_VERSION_2) { |
276 » PORT_SetError (SEC_ERROR_CRL_INVALID_VERSION); | 236 PORT_SetError(SEC_ERROR_CRL_INVALID_VERSION); |
277 » return (SECFailure); | 237 return (SECFailure); |
278 } | 238 } |
279 | 239 |
280 /* Check the crl extensions for a critial extension. If one is found, | 240 /* Check the crl extensions for a critial extension. If one is found, |
281 and the version is not v2, then we are done. | 241 and the version is not v2, then we are done. |
282 */ | 242 */ |
283 if (crl->extensions) { | 243 if (crl->extensions) { |
284 » hasCriticalExten = cert_HasCriticalExtension (crl->extensions); | 244 hasCriticalExten = cert_HasCriticalExtension(crl->extensions); |
285 » if (hasCriticalExten) { | 245 if (hasCriticalExten) { |
286 if (version != SEC_CRL_VERSION_2) { | 246 if (version != SEC_CRL_VERSION_2) { |
287 /* only CRL v2 critical extensions are supported */ | 247 /* only CRL v2 critical extensions are supported */ |
288 PORT_SetError(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION); | 248 PORT_SetError(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION); |
289 return (SECFailure); | 249 return (SECFailure); |
290 } | 250 } |
291 » /* make sure that there is no unknown critical extension */ | 251 /* make sure that there is no unknown critical extension */ |
292 » if (cert_HasUnknownCriticalExten (crl->extensions) == PR_TRUE) { | 252 if (cert_HasUnknownCriticalExten(crl->extensions) == PR_TRUE) { |
293 » » PORT_SetError (SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION); | 253 PORT_SetError(SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION); |
294 » » return (SECFailure); | 254 return (SECFailure); |
295 » } | 255 } |
296 » } | 256 } |
297 } | 257 } |
298 | 258 |
299 return (SECSuccess); | 259 return (SECSuccess); |
300 } | 260 } |
301 | 261 |
302 /* | 262 /* |
303 * Generate a database key, based on the issuer name from a | 263 * Generate a database key, based on the issuer name from a |
304 * DER crl. | 264 * DER crl. |
305 */ | 265 */ |
306 SECStatus | 266 SECStatus |
307 CERT_KeyFromDERCrl(PLArenaPool *arena, SECItem *derCrl, SECItem *key) | 267 CERT_KeyFromDERCrl(PLArenaPool* arena, SECItem* derCrl, SECItem* key) |
308 { | 268 { |
309 SECStatus rv; | 269 SECStatus rv; |
310 CERTSignedData sd; | 270 CERTSignedData sd; |
311 CERTCrlKey crlkey; | 271 CERTCrlKey crlkey; |
312 PLArenaPool* myArena; | 272 PLArenaPool* myArena; |
313 | 273 |
314 if (!arena) { | 274 if (!arena) { |
315 /* arena needed for QuickDER */ | 275 /* arena needed for QuickDER */ |
316 myArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 276 myArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
317 } else { | 277 } else { |
318 myArena = arena; | 278 myArena = arena; |
319 } | 279 } |
320 PORT_Memset (&sd, 0, sizeof (sd)); | 280 PORT_Memset(&sd, 0, sizeof(sd)); |
321 rv = SEC_QuickDERDecodeItem (myArena, &sd, CERT_SignedDataTemplate, derCrl); | 281 rv = SEC_QuickDERDecodeItem(myArena, &sd, CERT_SignedDataTemplate, derCrl); |
322 if (SECSuccess == rv) { | 282 if (SECSuccess == rv) { |
323 PORT_Memset (&crlkey, 0, sizeof (crlkey)); | 283 PORT_Memset(&crlkey, 0, sizeof(crlkey)); |
324 rv = SEC_QuickDERDecodeItem(myArena, &crlkey, cert_CrlKeyTemplate, &sd.d
ata); | 284 rv = SEC_QuickDERDecodeItem(myArena, &crlkey, cert_CrlKeyTemplate, |
| 285 &sd.data); |
325 } | 286 } |
326 | 287 |
327 /* make a copy so the data doesn't point to memory inside derCrl, which | 288 /* make a copy so the data doesn't point to memory inside derCrl, which |
328 may be temporary */ | 289 may be temporary */ |
329 if (SECSuccess == rv) { | 290 if (SECSuccess == rv) { |
330 rv = SECITEM_CopyItem(arena, key, &crlkey.derName); | 291 rv = SECITEM_CopyItem(arena, key, &crlkey.derName); |
331 } | 292 } |
332 | 293 |
333 if (myArena != arena) { | 294 if (myArena != arena) { |
334 PORT_FreeArena(myArena, PR_FALSE); | 295 PORT_FreeArena(myArena, PR_FALSE); |
335 } | 296 } |
336 | 297 |
337 return rv; | 298 return rv; |
338 } | 299 } |
339 | 300 |
340 #define GetOpaqueCRLFields(x) ((OpaqueCRLFields*)x->opaque) | 301 #define GetOpaqueCRLFields(x) ((OpaqueCRLFields*)x->opaque) |
341 | 302 |
342 SECStatus CERT_CompleteCRLDecodeEntries(CERTSignedCrl* crl) | 303 SECStatus |
| 304 CERT_CompleteCRLDecodeEntries(CERTSignedCrl* crl) |
343 { | 305 { |
344 SECStatus rv = SECSuccess; | 306 SECStatus rv = SECSuccess; |
345 SECItem* crldata = NULL; | 307 SECItem* crldata = NULL; |
346 OpaqueCRLFields* extended = NULL; | 308 OpaqueCRLFields* extended = NULL; |
347 | 309 |
348 if ( (!crl) || | 310 if ((!crl) || (!(extended = (OpaqueCRLFields*)crl->opaque)) || |
349 (!(extended = (OpaqueCRLFields*) crl->opaque)) || | 311 (PR_TRUE == extended->decodingError)) { |
350 (PR_TRUE == extended->decodingError) ) { | |
351 rv = SECFailure; | 312 rv = SECFailure; |
352 } else { | 313 } else { |
353 if (PR_FALSE == extended->partial) { | 314 if (PR_FALSE == extended->partial) { |
354 /* the CRL has already been fully decoded */ | 315 /* the CRL has already been fully decoded */ |
355 return SECSuccess; | 316 return SECSuccess; |
356 } | 317 } |
357 if (PR_TRUE == extended->badEntries) { | 318 if (PR_TRUE == extended->badEntries) { |
358 /* the entries decoding already failed */ | 319 /* the entries decoding already failed */ |
359 return SECFailure; | 320 return SECFailure; |
360 } | 321 } |
361 crldata = &crl->signatureWrap.data; | 322 crldata = &crl->signatureWrap.data; |
362 if (!crldata) { | 323 if (!crldata) { |
363 rv = SECFailure; | 324 rv = SECFailure; |
364 } | 325 } |
365 } | 326 } |
366 | 327 |
367 if (SECSuccess == rv) { | 328 if (SECSuccess == rv) { |
368 rv = SEC_QuickDERDecodeItem(crl->arena, | 329 rv = SEC_QuickDERDecodeItem(crl->arena, &crl->crl, |
369 &crl->crl, | 330 CERT_CrlTemplateEntriesOnly, crldata); |
370 CERT_CrlTemplateEntriesOnly, | |
371 crldata); | |
372 if (SECSuccess == rv) { | 331 if (SECSuccess == rv) { |
373 extended->partial = PR_FALSE; /* successful decode, avoid | 332 extended->partial = PR_FALSE; /* successful decode, avoid |
374 decoding again */ | 333 decoding again */ |
375 } else { | 334 } else { |
376 extended->decodingError = PR_TRUE; | 335 extended->decodingError = PR_TRUE; |
377 extended->badEntries = PR_TRUE; | 336 extended->badEntries = PR_TRUE; |
378 /* cache the decoding failure. If it fails the first time, | 337 /* cache the decoding failure. If it fails the first time, |
379 it will fail again, which will grow the arena and leak | 338 it will fail again, which will grow the arena and leak |
380 memory, so we want to avoid it */ | 339 memory, so we want to avoid it */ |
381 } | 340 } |
382 rv = cert_check_crl_entries(&crl->crl); | 341 rv = cert_check_crl_entries(&crl->crl); |
383 if (rv != SECSuccess) { | 342 if (rv != SECSuccess) { |
384 extended->badExtensions = PR_TRUE; | 343 extended->badExtensions = PR_TRUE; |
385 } | 344 } |
386 } | 345 } |
387 return rv; | 346 return rv; |
388 } | 347 } |
389 | 348 |
390 /* | 349 /* |
391 * take a DER CRL and decode it into a CRL structure | 350 * take a DER CRL and decode it into a CRL structure |
392 * allow reusing the input DER without making a copy | 351 * allow reusing the input DER without making a copy |
393 */ | 352 */ |
394 CERTSignedCrl * | 353 CERTSignedCrl* |
395 CERT_DecodeDERCrlWithFlags(PLArenaPool *narena, SECItem *derSignedCrl, | 354 CERT_DecodeDERCrlWithFlags(PLArenaPool* narena, SECItem* derSignedCrl, int type, |
396 int type, PRInt32 options) | 355 PRInt32 options) |
397 { | 356 { |
398 PLArenaPool *arena; | 357 PLArenaPool* arena; |
399 CERTSignedCrl *crl; | 358 CERTSignedCrl* crl; |
400 SECStatus rv; | 359 SECStatus rv; |
401 OpaqueCRLFields* extended = NULL; | 360 OpaqueCRLFields* extended = NULL; |
402 const SEC_ASN1Template* crlTemplate = CERT_SignedCrlTemplate; | 361 const SEC_ASN1Template* crlTemplate = CERT_SignedCrlTemplate; |
403 PRInt32 testOptions = options; | 362 PRInt32 testOptions = options; |
404 | 363 |
405 PORT_Assert(derSignedCrl); | 364 PORT_Assert(derSignedCrl); |
406 if (!derSignedCrl) { | 365 if (!derSignedCrl) { |
407 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 366 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
408 return NULL; | 367 return NULL; |
409 } | 368 } |
410 | 369 |
411 /* Adopting DER requires not copying it. Code that sets ADOPT flag | 370 /* Adopting DER requires not copying it. Code that sets ADOPT flag |
412 * but doesn't set DONT_COPY probably doesn't know What it is doing. | 371 * but doesn't set DONT_COPY probably doesn't know What it is doing. |
413 * That condition is a programming error in the caller. | 372 * That condition is a programming error in the caller. |
414 */ | 373 */ |
415 testOptions &= (CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_DONT_COPY_DER); | 374 testOptions &= (CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_DONT_COPY_DER); |
416 PORT_Assert(testOptions != CRL_DECODE_ADOPT_HEAP_DER); | 375 PORT_Assert(testOptions != CRL_DECODE_ADOPT_HEAP_DER); |
417 if (testOptions == CRL_DECODE_ADOPT_HEAP_DER) { | 376 if (testOptions == CRL_DECODE_ADOPT_HEAP_DER) { |
418 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 377 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
419 return NULL; | 378 return NULL; |
420 } | 379 } |
421 | 380 |
422 /* make a new arena if needed */ | 381 /* make a new arena if needed */ |
423 if (narena == NULL) { | 382 if (narena == NULL) { |
424 » arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 383 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
425 » if ( !arena ) { | 384 if (!arena) { |
426 » return NULL; | 385 return NULL; |
427 » } | 386 } |
428 } else { | 387 } else { |
429 » arena = narena; | 388 arena = narena; |
430 } | 389 } |
431 | 390 |
432 /* allocate the CRL structure */ | 391 /* allocate the CRL structure */ |
433 crl = (CERTSignedCrl *)PORT_ArenaZAlloc(arena, sizeof(CERTSignedCrl)); | 392 crl = (CERTSignedCrl*)PORT_ArenaZAlloc(arena, sizeof(CERTSignedCrl)); |
434 if ( !crl ) { | 393 if (!crl) { |
435 PORT_SetError(SEC_ERROR_NO_MEMORY); | 394 PORT_SetError(SEC_ERROR_NO_MEMORY); |
436 » goto loser; | 395 goto loser; |
437 } | 396 } |
438 | 397 |
439 crl->arena = arena; | 398 crl->arena = arena; |
440 | 399 |
441 /* allocate opaque fields */ | 400 /* allocate opaque fields */ |
442 crl->opaque = (void*)PORT_ArenaZAlloc(arena, sizeof(OpaqueCRLFields)); | 401 crl->opaque = (void*)PORT_ArenaZAlloc(arena, sizeof(OpaqueCRLFields)); |
443 if ( !crl->opaque ) { | 402 if (!crl->opaque) { |
444 » goto loser; | 403 goto loser; |
445 } | 404 } |
446 extended = (OpaqueCRLFields*) crl->opaque; | 405 extended = (OpaqueCRLFields*)crl->opaque; |
447 if (options & CRL_DECODE_ADOPT_HEAP_DER) { | 406 if (options & CRL_DECODE_ADOPT_HEAP_DER) { |
448 extended->heapDER = PR_TRUE; | 407 extended->heapDER = PR_TRUE; |
449 } | 408 } |
450 if (options & CRL_DECODE_DONT_COPY_DER) { | 409 if (options & CRL_DECODE_DONT_COPY_DER) { |
451 crl->derCrl = derSignedCrl; /* DER is not copied . The application | 410 crl->derCrl = derSignedCrl; /* DER is not copied . The application |
452 must keep derSignedCrl until it | 411 must keep derSignedCrl until it |
453 destroys the CRL */ | 412 destroys the CRL */ |
454 } else { | 413 } else { |
455 crl->derCrl = (SECItem *)PORT_ArenaZAlloc(arena,sizeof(SECItem)); | 414 crl->derCrl = (SECItem*)PORT_ArenaZAlloc(arena, sizeof(SECItem)); |
456 if (crl->derCrl == NULL) { | 415 if (crl->derCrl == NULL) { |
457 goto loser; | 416 goto loser; |
458 } | 417 } |
459 rv = SECITEM_CopyItem(arena, crl->derCrl, derSignedCrl); | 418 rv = SECITEM_CopyItem(arena, crl->derCrl, derSignedCrl); |
460 if (rv != SECSuccess) { | 419 if (rv != SECSuccess) { |
461 goto loser; | 420 goto loser; |
462 } | 421 } |
463 } | 422 } |
464 | 423 |
465 /* Save the arena in the inner crl for CRL extensions support */ | 424 /* Save the arena in the inner crl for CRL extensions support */ |
466 crl->crl.arena = arena; | 425 crl->crl.arena = arena; |
467 if (options & CRL_DECODE_SKIP_ENTRIES) { | 426 if (options & CRL_DECODE_SKIP_ENTRIES) { |
468 crlTemplate = cert_SignedCrlTemplateNoEntries; | 427 crlTemplate = cert_SignedCrlTemplateNoEntries; |
469 extended->partial = PR_TRUE; | 428 extended->partial = PR_TRUE; |
470 } | 429 } |
471 | 430 |
472 /* decode the CRL info */ | 431 /* decode the CRL info */ |
473 switch (type) { | 432 switch (type) { |
474 case SEC_CRL_TYPE: | 433 case SEC_CRL_TYPE: |
475 rv = SEC_QuickDERDecodeItem(arena, crl, crlTemplate, crl->derCrl); | 434 rv = SEC_QuickDERDecodeItem(arena, crl, crlTemplate, crl->derCrl); |
476 if (rv != SECSuccess) { | 435 if (rv != SECSuccess) { |
477 extended->badDER = PR_TRUE; | 436 extended->badDER = PR_TRUE; |
| 437 break; |
| 438 } |
| 439 /* check for critical extensions */ |
| 440 rv = cert_check_crl_version(&crl->crl); |
| 441 if (rv != SECSuccess) { |
| 442 extended->badExtensions = PR_TRUE; |
| 443 break; |
| 444 } |
| 445 |
| 446 if (PR_TRUE == extended->partial) { |
| 447 /* partial decoding, don't verify entries */ |
| 448 break; |
| 449 } |
| 450 |
| 451 rv = cert_check_crl_entries(&crl->crl); |
| 452 if (rv != SECSuccess) { |
| 453 extended->badExtensions = PR_TRUE; |
| 454 } |
| 455 |
478 break; | 456 break; |
479 } | 457 |
480 /* check for critical extensions */ | 458 default: |
481 rv = cert_check_crl_version (&crl->crl); | 459 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
482 if (rv != SECSuccess) { | 460 rv = SECFailure; |
483 extended->badExtensions = PR_TRUE; | |
484 break; | 461 break; |
485 } | |
486 | |
487 if (PR_TRUE == extended->partial) { | |
488 /* partial decoding, don't verify entries */ | |
489 break; | |
490 } | |
491 | |
492 rv = cert_check_crl_entries(&crl->crl); | |
493 if (rv != SECSuccess) { | |
494 extended->badExtensions = PR_TRUE; | |
495 } | |
496 | |
497 break; | |
498 | |
499 default: | |
500 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
501 rv = SECFailure; | |
502 break; | |
503 } | 462 } |
504 | 463 |
505 if (rv != SECSuccess) { | 464 if (rv != SECSuccess) { |
506 » goto loser; | 465 goto loser; |
507 } | 466 } |
508 | 467 |
509 crl->referenceCount = 1; | 468 crl->referenceCount = 1; |
510 | 469 |
511 return(crl); | 470 return (crl); |
512 | 471 |
513 loser: | 472 loser: |
514 if (options & CRL_DECODE_KEEP_BAD_CRL) { | 473 if (options & CRL_DECODE_KEEP_BAD_CRL) { |
515 if (extended) { | 474 if (extended) { |
516 extended->decodingError = PR_TRUE; | 475 extended->decodingError = PR_TRUE; |
517 } | 476 } |
518 if (crl) { | 477 if (crl) { |
519 crl->referenceCount = 1; | 478 crl->referenceCount = 1; |
520 return(crl); | 479 return (crl); |
521 } | 480 } |
522 } | 481 } |
523 | 482 |
524 if ((narena == NULL) && arena ) { | 483 if ((narena == NULL) && arena) { |
525 » PORT_FreeArena(arena, PR_FALSE); | 484 PORT_FreeArena(arena, PR_FALSE); |
526 } | 485 } |
527 | 486 |
528 return(0); | 487 return (0); |
529 } | 488 } |
530 | 489 |
531 /* | 490 /* |
532 * take a DER CRL and decode it into a CRL structure | 491 * take a DER CRL and decode it into a CRL structure |
533 */ | 492 */ |
534 CERTSignedCrl * | 493 CERTSignedCrl* |
535 CERT_DecodeDERCrl(PLArenaPool *narena, SECItem *derSignedCrl, int type) | 494 CERT_DecodeDERCrl(PLArenaPool* narena, SECItem* derSignedCrl, int type) |
536 { | 495 { |
537 return CERT_DecodeDERCrlWithFlags(narena, derSignedCrl, type, | 496 return CERT_DecodeDERCrlWithFlags(narena, derSignedCrl, type, |
538 CRL_DECODE_DEFAULT_OPTIONS); | 497 CRL_DECODE_DEFAULT_OPTIONS); |
539 } | 498 } |
540 | 499 |
541 /* | 500 /* |
542 * Lookup a CRL in the databases. We mirror the same fast caching data base | 501 * Lookup a CRL in the databases. We mirror the same fast caching data base |
543 * caching stuff used by certificates....? | 502 * caching stuff used by certificates....? |
544 * return values : | 503 * return values : |
545 * | 504 * |
546 * SECSuccess means we got a valid decodable DER CRL, or no CRL at all. | 505 * SECSuccess means we got a valid decodable DER CRL, or no CRL at all. |
547 * Caller may distinguish those cases by the value returned in "decoded". | 506 * Caller may distinguish those cases by the value returned in "decoded". |
548 * When DER CRL is not found, error code will be SEC_ERROR_CRL_NOT_FOUND. | 507 * When DER CRL is not found, error code will be SEC_ERROR_CRL_NOT_FOUND. |
549 * | 508 * |
550 * SECFailure means we got a fatal error - most likely, we found a CRL, | 509 * SECFailure means we got a fatal error - most likely, we found a CRL, |
551 * and it failed decoding, or there was an out of memory error. Do NOT ignore | 510 * and it failed decoding, or there was an out of memory error. Do NOT ignore |
552 * it and specifically do NOT treat it the same as having no CRL, as this | 511 * it and specifically do NOT treat it the same as having no CRL, as this |
553 * can compromise security !!! Ideally, you should treat this case as if you | 512 * can compromise security !!! Ideally, you should treat this case as if you |
554 * received a "catch-all" CRL where all certs you were looking up are | 513 * received a "catch-all" CRL where all certs you were looking up are |
555 * considered to be revoked | 514 * considered to be revoked |
556 */ | 515 */ |
557 static SECStatus | 516 static SECStatus |
558 SEC_FindCrlByKeyOnSlot(PK11SlotInfo *slot, SECItem *crlKey, int type, | 517 SEC_FindCrlByKeyOnSlot(PK11SlotInfo* slot, SECItem* crlKey, int type, |
559 CERTSignedCrl** decoded, PRInt32 decodeoptions) | 518 CERTSignedCrl** decoded, PRInt32 decodeoptions) |
560 { | 519 { |
561 SECStatus rv = SECSuccess; | 520 SECStatus rv = SECSuccess; |
562 CERTSignedCrl *crl = NULL; | 521 CERTSignedCrl* crl = NULL; |
563 SECItem *derCrl = NULL; | 522 SECItem* derCrl = NULL; |
564 CK_OBJECT_HANDLE crlHandle = 0; | 523 CK_OBJECT_HANDLE crlHandle = 0; |
565 char *url = NULL; | 524 char* url = NULL; |
566 | 525 |
567 PORT_Assert(decoded); | 526 PORT_Assert(decoded); |
568 if (!decoded) { | 527 if (!decoded) { |
569 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 528 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
570 return SECFailure; | 529 return SECFailure; |
571 } | 530 } |
572 | 531 |
573 derCrl = PK11_FindCrlByName(&slot, &crlHandle, crlKey, type, &url); | 532 derCrl = PK11_FindCrlByName(&slot, &crlHandle, crlKey, type, &url); |
574 if (derCrl == NULL) { | 533 if (derCrl == NULL) { |
575 » /* if we had a problem other than the CRL just didn't exist, return | 534 /* if we had a problem other than the CRL just didn't exist, return |
576 » * a failure to the upper level */ | 535 * a failure to the upper level */ |
577 » int nsserror = PORT_GetError(); | 536 int nsserror = PORT_GetError(); |
578 » if (nsserror != SEC_ERROR_CRL_NOT_FOUND) { | 537 if (nsserror != SEC_ERROR_CRL_NOT_FOUND) { |
579 » rv = SECFailure; | 538 rv = SECFailure; |
580 » } | 539 } |
581 » goto loser; | 540 goto loser; |
582 } | 541 } |
583 PORT_Assert(crlHandle != CK_INVALID_HANDLE); | 542 PORT_Assert(crlHandle != CK_INVALID_HANDLE); |
584 /* PK11_FindCrlByName obtained a slot reference. */ | 543 /* PK11_FindCrlByName obtained a slot reference. */ |
585 | 544 |
586 /* derCRL is a fresh HEAP copy made for us by PK11_FindCrlByName. | 545 /* derCRL is a fresh HEAP copy made for us by PK11_FindCrlByName. |
587 Force adoption of the DER CRL from the heap - this will cause it | 546 Force adoption of the DER CRL from the heap - this will cause it |
588 to be automatically freed when SEC_DestroyCrl is invoked */ | 547 to be automatically freed when SEC_DestroyCrl is invoked */ |
589 decodeoptions |= (CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_DONT_COPY_DER); | 548 decodeoptions |= (CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_DONT_COPY_DER); |
590 | 549 |
591 crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl, type, decodeoptions); | 550 crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl, type, decodeoptions); |
592 if (crl) { | 551 if (crl) { |
593 crl->slot = slot; | 552 crl->slot = slot; |
594 slot = NULL; /* adopt it */ | 553 slot = NULL; /* adopt it */ |
595 » derCrl = NULL; /* adopted by the crl struct */ | 554 derCrl = NULL; /* adopted by the crl struct */ |
596 crl->pkcs11ID = crlHandle; | 555 crl->pkcs11ID = crlHandle; |
597 if (url) { | 556 if (url) { |
598 crl->url = PORT_ArenaStrdup(crl->arena,url); | 557 crl->url = PORT_ArenaStrdup(crl->arena, url); |
599 } | 558 } |
600 } else { | 559 } else { |
601 rv = SECFailure; | 560 rv = SECFailure; |
602 } | 561 } |
603 | 562 |
604 if (url) { | 563 if (url) { |
605 » PORT_Free(url); | 564 PORT_Free(url); |
606 } | 565 } |
607 | 566 |
608 if (slot) { | 567 if (slot) { |
609 » PK11_FreeSlot(slot); | 568 PK11_FreeSlot(slot); |
610 } | 569 } |
611 | 570 |
612 loser: | 571 loser: |
613 if (derCrl) { | 572 if (derCrl) { |
614 » SECITEM_FreeItem(derCrl, PR_TRUE); | 573 SECITEM_FreeItem(derCrl, PR_TRUE); |
615 } | 574 } |
616 | 575 |
617 *decoded = crl; | 576 *decoded = crl; |
618 | 577 |
619 return rv; | 578 return rv; |
620 } | 579 } |
621 | 580 |
622 | 581 CERTSignedCrl* |
623 CERTSignedCrl * | 582 crl_storeCRL(PK11SlotInfo* slot, char* url, CERTSignedCrl* newCrl, |
624 crl_storeCRL (PK11SlotInfo *slot,char *url, | 583 SECItem* derCrl, int type) |
625 CERTSignedCrl *newCrl, SECItem *derCrl, int type) | |
626 { | 584 { |
627 CERTSignedCrl *oldCrl = NULL, *crl = NULL; | 585 CERTSignedCrl *oldCrl = NULL, *crl = NULL; |
628 PRBool deleteOldCrl = PR_FALSE; | 586 PRBool deleteOldCrl = PR_FALSE; |
629 CK_OBJECT_HANDLE crlHandle = CK_INVALID_HANDLE; | 587 CK_OBJECT_HANDLE crlHandle = CK_INVALID_HANDLE; |
630 | 588 |
631 PORT_Assert(newCrl); | 589 PORT_Assert(newCrl); |
632 PORT_Assert(derCrl); | 590 PORT_Assert(derCrl); |
633 PORT_Assert(type == SEC_CRL_TYPE); | 591 PORT_Assert(type == SEC_CRL_TYPE); |
634 | 592 |
635 if (type != SEC_CRL_TYPE) { | 593 if (type != SEC_CRL_TYPE) { |
636 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 594 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
637 return NULL; | 595 return NULL; |
638 } | 596 } |
639 | 597 |
640 /* we can't use the cache here because we must look in the same | 598 /* we can't use the cache here because we must look in the same |
641 token */ | 599 token */ |
642 (void)SEC_FindCrlByKeyOnSlot(slot, &newCrl->crl.derName, type, | 600 (void)SEC_FindCrlByKeyOnSlot(slot, &newCrl->crl.derName, type, &oldCrl, |
643 &oldCrl, CRL_DECODE_SKIP_ENTRIES); | 601 CRL_DECODE_SKIP_ENTRIES); |
644 /* if there is an old crl on the token, make sure the one we are | 602 /* if there is an old crl on the token, make sure the one we are |
645 installing is newer. If not, exit out, otherwise delete the | 603 installing is newer. If not, exit out, otherwise delete the |
646 old crl. | 604 old crl. |
647 */ | 605 */ |
648 if (oldCrl != NULL) { | 606 if (oldCrl != NULL) { |
649 » /* if it's already there, quietly continue */ | 607 /* if it's already there, quietly continue */ |
650 » if (SECITEM_CompareItem(newCrl->derCrl, oldCrl->derCrl) | 608 if (SECITEM_CompareItem(newCrl->derCrl, oldCrl->derCrl) == SECEqual) { |
651 » » » » » » == SECEqual) { | 609 crl = newCrl; |
652 » crl = newCrl; | 610 crl->slot = PK11_ReferenceSlot(slot); |
653 » crl->slot = PK11_ReferenceSlot(slot); | 611 crl->pkcs11ID = oldCrl->pkcs11ID; |
654 » crl->pkcs11ID = oldCrl->pkcs11ID; | 612 if (oldCrl->url && !url) |
655 » if (oldCrl->url && !url) | 613 url = oldCrl->url; |
656 » url = oldCrl->url; | 614 if (url) |
657 » if (url) | 615 crl->url = PORT_ArenaStrdup(crl->arena, url); |
658 » » crl->url = PORT_ArenaStrdup(crl->arena, url); | 616 goto done; |
659 » goto done; | 617 } |
660 » } | 618 if (!SEC_CrlIsNewer(&newCrl->crl, &oldCrl->crl)) { |
661 if (!SEC_CrlIsNewer(&newCrl->crl,&oldCrl->crl)) { | |
662 PORT_SetError(SEC_ERROR_OLD_CRL); | 619 PORT_SetError(SEC_ERROR_OLD_CRL); |
663 goto done; | 620 goto done; |
664 } | 621 } |
665 | 622 |
666 /* if we have a url in the database, use that one */ | 623 /* if we have a url in the database, use that one */ |
667 if (oldCrl->url && !url) { | 624 if (oldCrl->url && !url) { |
668 » url = oldCrl->url; | 625 url = oldCrl->url; |
669 } | 626 } |
670 | 627 |
671 /* really destroy this crl */ | 628 /* really destroy this crl */ |
672 /* first drum it out of the permanment Data base */ | 629 /* first drum it out of the permanment Data base */ |
673 » deleteOldCrl = PR_TRUE; | 630 deleteOldCrl = PR_TRUE; |
674 } | 631 } |
675 | 632 |
676 /* invalidate CRL cache for this issuer */ | 633 /* invalidate CRL cache for this issuer */ |
677 CERT_CRLCacheRefreshIssuer(NULL, &newCrl->crl.derName); | 634 CERT_CRLCacheRefreshIssuer(NULL, &newCrl->crl.derName); |
678 /* Write the new entry into the data base */ | 635 /* Write the new entry into the data base */ |
679 crlHandle = PK11_PutCrl(slot, derCrl, &newCrl->crl.derName, url, type); | 636 crlHandle = PK11_PutCrl(slot, derCrl, &newCrl->crl.derName, url, type); |
680 if (crlHandle != CK_INVALID_HANDLE) { | 637 if (crlHandle != CK_INVALID_HANDLE) { |
681 » crl = newCrl; | 638 crl = newCrl; |
682 » crl->slot = PK11_ReferenceSlot(slot); | 639 crl->slot = PK11_ReferenceSlot(slot); |
683 » crl->pkcs11ID = crlHandle; | 640 crl->pkcs11ID = crlHandle; |
684 » if (url) { | 641 if (url) { |
685 » crl->url = PORT_ArenaStrdup(crl->arena,url); | 642 crl->url = PORT_ArenaStrdup(crl->arena, url); |
686 » } | 643 } |
687 } | 644 } |
688 | 645 |
689 done: | 646 done: |
690 if (oldCrl) { | 647 if (oldCrl) { |
691 » if (deleteOldCrl && crlHandle != CK_INVALID_HANDLE) { | 648 if (deleteOldCrl && crlHandle != CK_INVALID_HANDLE) { |
692 » SEC_DeletePermCRL(oldCrl); | 649 SEC_DeletePermCRL(oldCrl); |
693 » } | 650 } |
694 » SEC_DestroyCrl(oldCrl); | 651 SEC_DestroyCrl(oldCrl); |
695 } | 652 } |
696 | 653 |
697 return crl; | 654 return crl; |
698 } | 655 } |
699 | 656 |
700 /* | 657 /* |
701 * | 658 * |
702 * create a new CRL from DER material. | 659 * create a new CRL from DER material. |
703 * | 660 * |
704 * The signature on this CRL must be checked before you | 661 * The signature on this CRL must be checked before you |
705 * load it. ??? | 662 * load it. ??? |
706 */ | 663 */ |
707 CERTSignedCrl * | 664 CERTSignedCrl* |
708 SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type) | 665 SEC_NewCrl(CERTCertDBHandle* handle, char* url, SECItem* derCrl, int type) |
709 { | 666 { |
710 CERTSignedCrl* retCrl = NULL; | 667 CERTSignedCrl* retCrl = NULL; |
711 PK11SlotInfo* slot = PK11_GetInternalKeySlot(); | 668 PK11SlotInfo* slot = PK11_GetInternalKeySlot(); |
712 retCrl = PK11_ImportCRL(slot, derCrl, url, type, NULL, | 669 retCrl = |
713 CRL_IMPORT_BYPASS_CHECKS, NULL, CRL_DECODE_DEFAULT_OPTIONS); | 670 PK11_ImportCRL(slot, derCrl, url, type, NULL, CRL_IMPORT_BYPASS_CHECKS, |
| 671 NULL, CRL_DECODE_DEFAULT_OPTIONS); |
714 PK11_FreeSlot(slot); | 672 PK11_FreeSlot(slot); |
715 | 673 |
716 return retCrl; | 674 return retCrl; |
717 } | 675 } |
718 | 676 |
719 CERTSignedCrl * | 677 CERTSignedCrl* |
720 SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl, int type) | 678 SEC_FindCrlByDERCert(CERTCertDBHandle* handle, SECItem* derCrl, int type) |
721 { | 679 { |
722 PLArenaPool *arena; | 680 PLArenaPool* arena; |
723 SECItem crlKey; | 681 SECItem crlKey; |
724 SECStatus rv; | 682 SECStatus rv; |
725 CERTSignedCrl *crl = NULL; | 683 CERTSignedCrl* crl = NULL; |
726 | 684 |
727 /* create a scratch arena */ | 685 /* create a scratch arena */ |
728 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 686 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
729 if ( arena == NULL ) { | 687 if (arena == NULL) { |
730 » return(NULL); | 688 return (NULL); |
731 } | 689 } |
732 | 690 |
733 /* extract the database key from the cert */ | 691 /* extract the database key from the cert */ |
734 rv = CERT_KeyFromDERCrl(arena, derCrl, &crlKey); | 692 rv = CERT_KeyFromDERCrl(arena, derCrl, &crlKey); |
735 if ( rv != SECSuccess ) { | 693 if (rv != SECSuccess) { |
736 » goto loser; | 694 goto loser; |
737 } | 695 } |
738 | 696 |
739 /* find the crl */ | 697 /* find the crl */ |
740 crl = SEC_FindCrlByName(handle, &crlKey, type); | 698 crl = SEC_FindCrlByName(handle, &crlKey, type); |
741 | 699 |
742 loser: | 700 loser: |
743 PORT_FreeArena(arena, PR_FALSE); | 701 PORT_FreeArena(arena, PR_FALSE); |
744 return(crl); | 702 return (crl); |
745 } | 703 } |
746 | 704 |
747 CERTSignedCrl* SEC_DupCrl(CERTSignedCrl* acrl) | 705 CERTSignedCrl* |
| 706 SEC_DupCrl(CERTSignedCrl* acrl) |
748 { | 707 { |
749 if (acrl) | 708 if (acrl) { |
750 { | |
751 PR_ATOMIC_INCREMENT(&acrl->referenceCount); | 709 PR_ATOMIC_INCREMENT(&acrl->referenceCount); |
752 return acrl; | 710 return acrl; |
753 } | 711 } |
754 return NULL; | 712 return NULL; |
755 } | 713 } |
756 | 714 |
757 SECStatus | 715 SECStatus |
758 SEC_DestroyCrl(CERTSignedCrl *crl) | 716 SEC_DestroyCrl(CERTSignedCrl* crl) |
759 { | 717 { |
760 if (crl) { | 718 if (crl) { |
761 » if (PR_ATOMIC_DECREMENT(&crl->referenceCount) < 1) { | 719 if (PR_ATOMIC_DECREMENT(&crl->referenceCount) < 1) { |
762 » if (crl->slot) { | 720 if (crl->slot) { |
763 » » PK11_FreeSlot(crl->slot); | 721 PK11_FreeSlot(crl->slot); |
764 » } | 722 } |
765 if (GetOpaqueCRLFields(crl) && | 723 if (GetOpaqueCRLFields(crl) && |
766 PR_TRUE == GetOpaqueCRLFields(crl)->heapDER) { | 724 PR_TRUE == GetOpaqueCRLFields(crl)->heapDER) { |
767 SECITEM_FreeItem(crl->derCrl, PR_TRUE); | 725 SECITEM_FreeItem(crl->derCrl, PR_TRUE); |
768 } | 726 } |
769 if (crl->arena) { | 727 if (crl->arena) { |
770 PORT_FreeArena(crl->arena, PR_FALSE); | 728 PORT_FreeArena(crl->arena, PR_FALSE); |
771 } | 729 } |
772 » } | 730 } |
773 return SECSuccess; | 731 return SECSuccess; |
774 } else { | 732 } else { |
775 return SECFailure; | 733 return SECFailure; |
776 } | 734 } |
777 } | 735 } |
778 | 736 |
779 SECStatus | 737 SECStatus |
780 SEC_LookupCrls(CERTCertDBHandle *handle, CERTCrlHeadNode **nodes, int type) | 738 SEC_LookupCrls(CERTCertDBHandle* handle, CERTCrlHeadNode** nodes, int type) |
781 { | 739 { |
782 CERTCrlHeadNode *head; | 740 CERTCrlHeadNode* head; |
783 PLArenaPool *arena = NULL; | 741 PLArenaPool* arena = NULL; |
784 SECStatus rv; | 742 SECStatus rv; |
785 | 743 |
786 *nodes = NULL; | 744 *nodes = NULL; |
787 | 745 |
788 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 746 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
789 if ( arena == NULL ) { | 747 if (arena == NULL) { |
790 » return SECFailure; | 748 return SECFailure; |
791 } | 749 } |
792 | 750 |
793 /* build a head structure */ | 751 /* build a head structure */ |
794 head = (CERTCrlHeadNode *)PORT_ArenaAlloc(arena, sizeof(CERTCrlHeadNode)); | 752 head = (CERTCrlHeadNode*)PORT_ArenaAlloc(arena, sizeof(CERTCrlHeadNode)); |
795 head->arena = arena; | 753 head->arena = arena; |
796 head->first = NULL; | 754 head->first = NULL; |
797 head->last = NULL; | 755 head->last = NULL; |
798 head->dbhandle = handle; | 756 head->dbhandle = handle; |
799 | 757 |
800 /* Look up the proper crl types */ | 758 /* Look up the proper crl types */ |
801 *nodes = head; | 759 *nodes = head; |
802 | 760 |
803 rv = PK11_LookupCrls(head, type, NULL); | 761 rv = PK11_LookupCrls(head, type, NULL); |
804 | 762 |
805 if (rv != SECSuccess) { | 763 if (rv != SECSuccess) { |
806 » if ( arena ) { | 764 if (arena) { |
807 » PORT_FreeArena(arena, PR_FALSE); | 765 PORT_FreeArena(arena, PR_FALSE); |
808 » *nodes = NULL; | 766 *nodes = NULL; |
809 » } | 767 } |
810 } | 768 } |
811 | 769 |
812 return rv; | 770 return rv; |
813 } | 771 } |
814 | 772 |
815 /* These functions simply return the address of the above-declared templates. | 773 /* These functions simply return the address of the above-declared templates. |
816 ** This is necessary for Windows DLLs. Sigh. | 774 ** This is necessary for Windows DLLs. Sigh. |
817 */ | 775 */ |
818 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_IssuerAndSNTemplate) | 776 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_IssuerAndSNTemplate) |
819 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CrlTemplate) | 777 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CrlTemplate) |
820 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedCrlTemplate) | 778 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedCrlTemplate) |
821 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SetOfSignedCrlTemplate) | 779 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SetOfSignedCrlTemplate) |
822 | 780 |
823 /* CRL cache code starts here */ | 781 /* CRL cache code starts here */ |
824 | 782 |
825 /* constructor */ | 783 /* constructor */ |
826 static SECStatus CachedCrl_Create(CachedCrl** returned, CERTSignedCrl* crl, | 784 static SECStatus CachedCrl_Create(CachedCrl** returned, CERTSignedCrl* crl, |
827 CRLOrigin origin); | 785 CRLOrigin origin); |
828 /* destructor */ | 786 /* destructor */ |
829 static SECStatus CachedCrl_Destroy(CachedCrl* crl); | 787 static SECStatus CachedCrl_Destroy(CachedCrl* crl); |
830 | 788 |
831 /* create hash table of CRL entries */ | 789 /* create hash table of CRL entries */ |
832 static SECStatus CachedCrl_Populate(CachedCrl* crlobject); | 790 static SECStatus CachedCrl_Populate(CachedCrl* crlobject); |
833 | 791 |
834 /* empty the cache content */ | 792 /* empty the cache content */ |
835 static SECStatus CachedCrl_Depopulate(CachedCrl* crl); | 793 static SECStatus CachedCrl_Depopulate(CachedCrl* crl); |
836 | 794 |
837 /* are these CRLs the same, as far as the cache is concerned ? | 795 /* are these CRLs the same, as far as the cache is concerned ? |
838 Or are they the same token object, but with different DER ? */ | 796 Or are they the same token object, but with different DER ? */ |
839 | 797 |
840 static SECStatus CachedCrl_Compare(CachedCrl* a, CachedCrl* b, PRBool* isDupe, | 798 static SECStatus CachedCrl_Compare(CachedCrl* a, CachedCrl* b, PRBool* isDupe, |
841 PRBool* isUpdated); | 799 PRBool* isUpdated); |
842 | 800 |
843 /* create a DPCache object */ | 801 /* create a DPCache object */ |
844 static SECStatus DPCache_Create(CRLDPCache** returned, CERTCertificate* issuer, | 802 static SECStatus DPCache_Create(CRLDPCache** returned, CERTCertificate* issuer, |
845 const SECItem* subject, SECItem* dp); | 803 const SECItem* subject, SECItem* dp); |
846 | 804 |
847 /* destructor for CRL DPCache object */ | 805 /* destructor for CRL DPCache object */ |
848 static SECStatus DPCache_Destroy(CRLDPCache* cache); | 806 static SECStatus DPCache_Destroy(CRLDPCache* cache); |
849 | 807 |
850 /* add a new CRL object to the dynamic array of CRLs of the DPCache, and | 808 /* add a new CRL object to the dynamic array of CRLs of the DPCache, and |
851 returns the cached CRL object . Needs write access to DPCache. */ | 809 returns the cached CRL object . Needs write access to DPCache. */ |
852 static SECStatus DPCache_AddCRL(CRLDPCache* cache, CachedCrl* crl, | 810 static SECStatus DPCache_AddCRL(CRLDPCache* cache, CachedCrl* crl, |
853 PRBool* added); | 811 PRBool* added); |
854 | 812 |
855 /* fetch the CRL for this DP from the PKCS#11 tokens */ | 813 /* fetch the CRL for this DP from the PKCS#11 tokens */ |
856 static SECStatus DPCache_FetchFromTokens(CRLDPCache* cache, PRTime vfdate, | 814 static SECStatus DPCache_FetchFromTokens(CRLDPCache* cache, PRTime vfdate, |
857 void* wincx); | 815 void* wincx); |
858 | 816 |
859 /* update the content of the CRL cache, including fetching of CRLs, and | 817 /* update the content of the CRL cache, including fetching of CRLs, and |
860 reprocessing with specified issuer and date */ | 818 reprocessing with specified issuer and date */ |
861 static SECStatus DPCache_GetUpToDate(CRLDPCache* cache, CERTCertificate* issuer, | 819 static SECStatus DPCache_GetUpToDate(CRLDPCache* cache, CERTCertificate* issuer, |
862 PRBool readlocked, PRTime vfdate, void* wincx); | 820 PRBool readlocked, PRTime vfdate, |
| 821 void* wincx); |
863 | 822 |
864 /* returns true if there are CRLs from PKCS#11 slots */ | 823 /* returns true if there are CRLs from PKCS#11 slots */ |
865 static PRBool DPCache_HasTokenCRLs(CRLDPCache* cache); | 824 static PRBool DPCache_HasTokenCRLs(CRLDPCache* cache); |
866 | 825 |
867 /* remove CRL at offset specified */ | 826 /* remove CRL at offset specified */ |
868 static SECStatus DPCache_RemoveCRL(CRLDPCache* cache, PRUint32 offset); | 827 static SECStatus DPCache_RemoveCRL(CRLDPCache* cache, PRUint32 offset); |
869 | 828 |
870 /* Pick best CRL to use . needs write access */ | 829 /* Pick best CRL to use . needs write access */ |
871 static SECStatus DPCache_SelectCRL(CRLDPCache* cache); | 830 static SECStatus DPCache_SelectCRL(CRLDPCache* cache); |
872 | 831 |
873 /* create an issuer cache object (per CA subject ) */ | 832 /* create an issuer cache object (per CA subject ) */ |
874 static SECStatus IssuerCache_Create(CRLIssuerCache** returned, | 833 static SECStatus IssuerCache_Create(CRLIssuerCache** returned, |
875 CERTCertificate* issuer, | 834 CERTCertificate* issuer, |
876 const SECItem* subject, const SECItem* dp); | 835 const SECItem* subject, const SECItem* dp); |
877 | 836 |
878 /* destructor for CRL IssuerCache object */ | 837 /* destructor for CRL IssuerCache object */ |
879 SECStatus IssuerCache_Destroy(CRLIssuerCache* cache); | 838 SECStatus IssuerCache_Destroy(CRLIssuerCache* cache); |
880 | 839 |
881 /* add a DPCache to the issuer cache */ | 840 /* add a DPCache to the issuer cache */ |
882 static SECStatus IssuerCache_AddDP(CRLIssuerCache* cache, | 841 static SECStatus IssuerCache_AddDP(CRLIssuerCache* cache, |
883 CERTCertificate* issuer, | 842 CERTCertificate* issuer, |
884 const SECItem* subject, | 843 const SECItem* subject, const SECItem* dp, |
885 const SECItem* dp, CRLDPCache** newdpc); | 844 CRLDPCache** newdpc); |
886 | 845 |
887 /* get a particular DPCache object from an IssuerCache */ | 846 /* get a particular DPCache object from an IssuerCache */ |
888 static CRLDPCache* IssuerCache_GetDPCache(CRLIssuerCache* cache, | 847 static CRLDPCache* IssuerCache_GetDPCache(CRLIssuerCache* cache, |
889 const SECItem* dp); | 848 const SECItem* dp); |
890 | 849 |
891 /* | 850 /* |
892 ** Pre-allocator hash allocator ops. | 851 ** Pre-allocator hash allocator ops. |
893 */ | 852 */ |
894 | 853 |
895 /* allocate memory for hash table */ | 854 /* allocate memory for hash table */ |
896 static void * PR_CALLBACK | 855 static void* PR_CALLBACK |
897 PreAllocTable(void *pool, PRSize size) | 856 PreAllocTable(void* pool, PRSize size) |
898 { | 857 { |
899 PreAllocator* alloc = (PreAllocator*)pool; | 858 PreAllocator* alloc = (PreAllocator*)pool; |
900 PORT_Assert(alloc); | 859 PORT_Assert(alloc); |
901 if (!alloc) | 860 if (!alloc) { |
902 { | |
903 /* no allocator, or buffer full */ | 861 /* no allocator, or buffer full */ |
904 return NULL; | 862 return NULL; |
905 } | 863 } |
906 if (size > (alloc->len - alloc->used)) | 864 if (size > (alloc->len - alloc->used)) { |
907 { | |
908 /* initial buffer full, let's use the arena */ | 865 /* initial buffer full, let's use the arena */ |
909 alloc->extra += size; | 866 alloc->extra += size; |
910 return PORT_ArenaAlloc(alloc->arena, size); | 867 return PORT_ArenaAlloc(alloc->arena, size); |
911 } | 868 } |
912 /* use the initial buffer */ | 869 /* use the initial buffer */ |
913 alloc->used += size; | 870 alloc->used += size; |
914 return (char*) alloc->data + alloc->used - size; | 871 return (char*)alloc->data + alloc->used - size; |
915 } | 872 } |
916 | 873 |
917 /* free hash table memory. | 874 /* free hash table memory. |
918 Individual PreAllocator elements cannot be freed, so this is a no-op. */ | 875 Individual PreAllocator elements cannot be freed, so this is a no-op. */ |
919 static void PR_CALLBACK | 876 static void PR_CALLBACK |
920 PreFreeTable(void *pool, void *item) | 877 PreFreeTable(void* pool, void* item) |
921 { | 878 { |
922 } | 879 } |
923 | 880 |
924 /* allocate memory for hash table */ | 881 /* allocate memory for hash table */ |
925 static PLHashEntry * PR_CALLBACK | 882 static PLHashEntry* PR_CALLBACK |
926 PreAllocEntry(void *pool, const void *key) | 883 PreAllocEntry(void* pool, const void* key) |
927 { | 884 { |
928 return PreAllocTable(pool, sizeof(PLHashEntry)); | 885 return PreAllocTable(pool, sizeof(PLHashEntry)); |
929 } | 886 } |
930 | 887 |
931 /* free hash table entry. | 888 /* free hash table entry. |
932 Individual PreAllocator elements cannot be freed, so this is a no-op. */ | 889 Individual PreAllocator elements cannot be freed, so this is a no-op. */ |
933 static void PR_CALLBACK | 890 static void PR_CALLBACK |
934 PreFreeEntry(void *pool, PLHashEntry *he, PRUintn flag) | 891 PreFreeEntry(void* pool, PLHashEntry* he, PRUintn flag) |
935 { | 892 { |
936 } | 893 } |
937 | 894 |
938 /* methods required for PL hash table functions */ | 895 /* methods required for PL hash table functions */ |
939 static PLHashAllocOps preAllocOps = | 896 static PLHashAllocOps preAllocOps = { PreAllocTable, PreFreeTable, |
940 { | 897 PreAllocEntry, PreFreeEntry }; |
941 PreAllocTable, PreFreeTable, | |
942 PreAllocEntry, PreFreeEntry | |
943 }; | |
944 | 898 |
945 /* destructor for PreAllocator object */ | 899 /* destructor for PreAllocator object */ |
946 void PreAllocator_Destroy(PreAllocator* PreAllocator) | 900 void |
| 901 PreAllocator_Destroy(PreAllocator* PreAllocator) |
947 { | 902 { |
948 if (!PreAllocator) | 903 if (!PreAllocator) { |
949 { | |
950 return; | 904 return; |
951 } | 905 } |
952 if (PreAllocator->arena) | 906 if (PreAllocator->arena) { |
953 { | |
954 PORT_FreeArena(PreAllocator->arena, PR_TRUE); | 907 PORT_FreeArena(PreAllocator->arena, PR_TRUE); |
955 } | 908 } |
956 } | 909 } |
957 | 910 |
958 /* constructor for PreAllocator object */ | 911 /* constructor for PreAllocator object */ |
959 PreAllocator* PreAllocator_Create(PRSize size) | 912 PreAllocator* |
| 913 PreAllocator_Create(PRSize size) |
960 { | 914 { |
961 PLArenaPool* arena = NULL; | 915 PLArenaPool* arena = NULL; |
962 PreAllocator* prebuffer = NULL; | 916 PreAllocator* prebuffer = NULL; |
963 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 917 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
964 if (!arena) | 918 if (!arena) { |
965 { | |
966 return NULL; | 919 return NULL; |
967 } | 920 } |
968 prebuffer = (PreAllocator*)PORT_ArenaZAlloc(arena, | 921 prebuffer = (PreAllocator*)PORT_ArenaZAlloc(arena, sizeof(PreAllocator)); |
969 sizeof(PreAllocator)); | 922 if (!prebuffer) { |
970 if (!prebuffer) | |
971 { | |
972 PORT_FreeArena(arena, PR_TRUE); | 923 PORT_FreeArena(arena, PR_TRUE); |
973 return NULL; | 924 return NULL; |
974 } | 925 } |
975 prebuffer->arena = arena; | 926 prebuffer->arena = arena; |
976 | 927 |
977 if (size) | 928 if (size) { |
978 { | |
979 prebuffer->len = size; | 929 prebuffer->len = size; |
980 prebuffer->data = PORT_ArenaAlloc(arena, size); | 930 prebuffer->data = PORT_ArenaAlloc(arena, size); |
981 if (!prebuffer->data) | 931 if (!prebuffer->data) { |
982 { | |
983 PORT_FreeArena(arena, PR_TRUE); | 932 PORT_FreeArena(arena, PR_TRUE); |
984 return NULL; | 933 return NULL; |
985 } | 934 } |
986 } | 935 } |
987 return prebuffer; | 936 return prebuffer; |
988 } | 937 } |
989 | 938 |
990 /* global Named CRL cache object */ | 939 /* global Named CRL cache object */ |
991 static NamedCRLCache namedCRLCache = { NULL, NULL }; | 940 static NamedCRLCache namedCRLCache = { NULL, NULL }; |
992 | 941 |
993 /* global CRL cache object */ | 942 /* global CRL cache object */ |
994 static CRLCache crlcache = { NULL, NULL }; | 943 static CRLCache crlcache = { NULL, NULL }; |
995 | 944 |
996 /* initial state is off */ | 945 /* initial state is off */ |
997 static PRBool crlcache_initialized = PR_FALSE; | 946 static PRBool crlcache_initialized = PR_FALSE; |
998 | 947 |
999 PRTime CRLCache_Empty_TokenFetch_Interval = 60 * 1000000; /* how often | 948 PRTime CRLCache_Empty_TokenFetch_Interval = 60 * 1000000; /* how often |
1000 to query the tokens for CRL objects, in order to discover new objects, if | 949 to query the tokens for CRL objects, in order to discover new objects, if |
1001 the cache does not contain any token CRLs . In microseconds */ | 950 the cache does not contain any token CRLs . In microseconds */ |
1002 | 951 |
1003 PRTime CRLCache_TokenRefetch_Interval = 600 * 1000000 ; /* how often | 952 PRTime CRLCache_TokenRefetch_Interval = 600 * 1000000; /* how often |
1004 to query the tokens for CRL objects, in order to discover new objects, if | 953 to query the tokens for CRL objects, in order to discover new objects, if |
1005 the cache already contains token CRLs In microseconds */ | 954 the cache already contains token CRLs In microseconds */ |
1006 | 955 |
1007 PRTime CRLCache_ExistenceCheck_Interval = 60 * 1000000; /* how often to check | 956 PRTime CRLCache_ExistenceCheck_Interval = 60 * 1000000; /* how often to check |
1008 if a token CRL object still exists. In microseconds */ | 957 if a token CRL object still exists. In microseconds */ |
1009 | 958 |
1010 /* this function is called at NSS initialization time */ | 959 /* this function is called at NSS initialization time */ |
1011 SECStatus InitCRLCache(void) | 960 SECStatus |
| 961 InitCRLCache(void) |
1012 { | 962 { |
1013 if (PR_FALSE == crlcache_initialized) | 963 if (PR_FALSE == crlcache_initialized) { |
1014 { | |
1015 PORT_Assert(NULL == crlcache.lock); | 964 PORT_Assert(NULL == crlcache.lock); |
1016 PORT_Assert(NULL == crlcache.issuers); | 965 PORT_Assert(NULL == crlcache.issuers); |
1017 PORT_Assert(NULL == namedCRLCache.lock); | 966 PORT_Assert(NULL == namedCRLCache.lock); |
1018 PORT_Assert(NULL == namedCRLCache.entries); | 967 PORT_Assert(NULL == namedCRLCache.entries); |
1019 if (crlcache.lock || crlcache.issuers || namedCRLCache.lock || | 968 if (crlcache.lock || crlcache.issuers || namedCRLCache.lock || |
1020 namedCRLCache.entries) | 969 namedCRLCache.entries) { |
1021 { | |
1022 /* CRL cache already partially initialized */ | 970 /* CRL cache already partially initialized */ |
1023 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 971 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1024 return SECFailure; | 972 return SECFailure; |
1025 } | 973 } |
1026 #ifdef GLOBAL_RWLOCK | 974 #ifdef GLOBAL_RWLOCK |
1027 crlcache.lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); | 975 crlcache.lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); |
1028 #else | 976 #else |
1029 crlcache.lock = PR_NewLock(); | 977 crlcache.lock = PR_NewLock(); |
1030 #endif | 978 #endif |
1031 namedCRLCache.lock = PR_NewLock(); | 979 namedCRLCache.lock = PR_NewLock(); |
1032 crlcache.issuers = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, | 980 crlcache.issuers = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, |
1033 PL_CompareValues, NULL, NULL); | 981 PL_CompareValues, NULL, NULL); |
1034 namedCRLCache.entries = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCom
pare, | 982 namedCRLCache.entries = PL_NewHashTable( |
1035 PL_CompareValues, NULL, NULL); | 983 0, SECITEM_Hash, SECITEM_HashCompare, PL_CompareValues, NULL, NULL); |
1036 if (!crlcache.lock || !namedCRLCache.lock || !crlcache.issuers || | 984 if (!crlcache.lock || !namedCRLCache.lock || !crlcache.issuers || |
1037 !namedCRLCache.entries) | 985 !namedCRLCache.entries) { |
1038 { | 986 if (crlcache.lock) { |
1039 if (crlcache.lock) | |
1040 { | |
1041 #ifdef GLOBAL_RWLOCK | 987 #ifdef GLOBAL_RWLOCK |
1042 NSSRWLock_Destroy(crlcache.lock); | 988 NSSRWLock_Destroy(crlcache.lock); |
1043 #else | 989 #else |
1044 PR_DestroyLock(crlcache.lock); | 990 PR_DestroyLock(crlcache.lock); |
1045 #endif | 991 #endif |
1046 crlcache.lock = NULL; | 992 crlcache.lock = NULL; |
1047 } | 993 } |
1048 if (namedCRLCache.lock) | 994 if (namedCRLCache.lock) { |
1049 { | |
1050 PR_DestroyLock(namedCRLCache.lock); | 995 PR_DestroyLock(namedCRLCache.lock); |
1051 namedCRLCache.lock = NULL; | 996 namedCRLCache.lock = NULL; |
1052 } | 997 } |
1053 if (crlcache.issuers) | 998 if (crlcache.issuers) { |
1054 { | |
1055 PL_HashTableDestroy(crlcache.issuers); | 999 PL_HashTableDestroy(crlcache.issuers); |
1056 crlcache.issuers = NULL; | 1000 crlcache.issuers = NULL; |
1057 } | 1001 } |
1058 if (namedCRLCache.entries) | 1002 if (namedCRLCache.entries) { |
1059 { | |
1060 PL_HashTableDestroy(namedCRLCache.entries); | 1003 PL_HashTableDestroy(namedCRLCache.entries); |
1061 namedCRLCache.entries = NULL; | 1004 namedCRLCache.entries = NULL; |
1062 } | 1005 } |
1063 | 1006 |
1064 return SECFailure; | 1007 return SECFailure; |
1065 } | 1008 } |
1066 crlcache_initialized = PR_TRUE; | 1009 crlcache_initialized = PR_TRUE; |
1067 return SECSuccess; | 1010 return SECSuccess; |
1068 } | 1011 } else { |
1069 else | |
1070 { | |
1071 PORT_Assert(crlcache.lock); | 1012 PORT_Assert(crlcache.lock); |
1072 PORT_Assert(crlcache.issuers); | 1013 PORT_Assert(crlcache.issuers); |
1073 if ( (NULL == crlcache.lock) || (NULL == crlcache.issuers) ) | 1014 if ((NULL == crlcache.lock) || (NULL == crlcache.issuers)) { |
1074 { | |
1075 /* CRL cache not fully initialized */ | 1015 /* CRL cache not fully initialized */ |
1076 return SECFailure; | 1016 return SECFailure; |
1077 } | 1017 } else { |
1078 else | |
1079 { | |
1080 /* CRL cache already initialized */ | 1018 /* CRL cache already initialized */ |
1081 return SECSuccess; | 1019 return SECSuccess; |
1082 } | 1020 } |
1083 } | 1021 } |
1084 } | 1022 } |
1085 | 1023 |
1086 /* destructor for CRL DPCache object */ | 1024 /* destructor for CRL DPCache object */ |
1087 static SECStatus DPCache_Destroy(CRLDPCache* cache) | 1025 static SECStatus |
| 1026 DPCache_Destroy(CRLDPCache* cache) |
1088 { | 1027 { |
1089 PRUint32 i = 0; | 1028 PRUint32 i = 0; |
1090 PORT_Assert(cache); | 1029 PORT_Assert(cache); |
1091 if (!cache) | 1030 if (!cache) { |
1092 { | |
1093 PORT_Assert(0); | 1031 PORT_Assert(0); |
1094 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1032 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1095 return SECFailure; | 1033 return SECFailure; |
1096 } | 1034 } |
1097 if (cache->lock) | 1035 if (cache->lock) { |
1098 { | |
1099 #ifdef DPC_RWLOCK | 1036 #ifdef DPC_RWLOCK |
1100 NSSRWLock_Destroy(cache->lock); | 1037 NSSRWLock_Destroy(cache->lock); |
1101 #else | 1038 #else |
1102 PR_DestroyLock(cache->lock); | 1039 PR_DestroyLock(cache->lock); |
1103 #endif | 1040 #endif |
1104 } | 1041 } else { |
1105 else | |
1106 { | |
1107 PORT_Assert(0); | 1042 PORT_Assert(0); |
1108 return SECFailure; | 1043 return SECFailure; |
1109 } | 1044 } |
1110 /* destroy all our CRL objects */ | 1045 /* destroy all our CRL objects */ |
1111 for (i=0;i<cache->ncrls;i++) | 1046 for (i = 0; i < cache->ncrls; i++) { |
1112 { | |
1113 if (!cache->crls || !cache->crls[i] || | 1047 if (!cache->crls || !cache->crls[i] || |
1114 SECSuccess != CachedCrl_Destroy(cache->crls[i])) | 1048 SECSuccess != CachedCrl_Destroy(cache->crls[i])) { |
1115 { | |
1116 return SECFailure; | 1049 return SECFailure; |
1117 } | 1050 } |
1118 } | 1051 } |
1119 /* free the array of CRLs */ | 1052 /* free the array of CRLs */ |
1120 if (cache->crls) | 1053 if (cache->crls) { |
1121 { | 1054 PORT_Free(cache->crls); |
1122 » PORT_Free(cache->crls); | |
1123 } | 1055 } |
1124 /* destroy the cert */ | 1056 /* destroy the cert */ |
1125 if (cache->issuerDERCert) | 1057 if (cache->issuerDERCert) { |
1126 { | |
1127 SECITEM_FreeItem(cache->issuerDERCert, PR_TRUE); | 1058 SECITEM_FreeItem(cache->issuerDERCert, PR_TRUE); |
1128 } | 1059 } |
1129 /* free the subject */ | 1060 /* free the subject */ |
1130 if (cache->subject) | 1061 if (cache->subject) { |
1131 { | |
1132 SECITEM_FreeItem(cache->subject, PR_TRUE); | 1062 SECITEM_FreeItem(cache->subject, PR_TRUE); |
1133 } | 1063 } |
1134 /* free the distribution points */ | 1064 /* free the distribution points */ |
1135 if (cache->distributionPoint) | 1065 if (cache->distributionPoint) { |
1136 { | |
1137 SECITEM_FreeItem(cache->distributionPoint, PR_TRUE); | 1066 SECITEM_FreeItem(cache->distributionPoint, PR_TRUE); |
1138 } | 1067 } |
1139 PORT_Free(cache); | 1068 PORT_Free(cache); |
1140 return SECSuccess; | 1069 return SECSuccess; |
1141 } | 1070 } |
1142 | 1071 |
1143 /* destructor for CRL IssuerCache object */ | 1072 /* destructor for CRL IssuerCache object */ |
1144 SECStatus IssuerCache_Destroy(CRLIssuerCache* cache) | 1073 SECStatus |
| 1074 IssuerCache_Destroy(CRLIssuerCache* cache) |
1145 { | 1075 { |
1146 PORT_Assert(cache); | 1076 PORT_Assert(cache); |
1147 if (!cache) | 1077 if (!cache) { |
1148 { | |
1149 PORT_Assert(0); | 1078 PORT_Assert(0); |
1150 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1079 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1151 return SECFailure; | 1080 return SECFailure; |
1152 } | 1081 } |
1153 #ifdef XCRL | 1082 #ifdef XCRL |
1154 if (cache->lock) | 1083 if (cache->lock) { |
1155 { | |
1156 NSSRWLock_Destroy(cache->lock); | 1084 NSSRWLock_Destroy(cache->lock); |
1157 } | 1085 } else { |
1158 else | |
1159 { | |
1160 PORT_Assert(0); | 1086 PORT_Assert(0); |
1161 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1087 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1162 return SECFailure; | 1088 return SECFailure; |
1163 } | 1089 } |
1164 if (cache->issuer) | 1090 if (cache->issuer) { |
1165 { | |
1166 CERT_DestroyCertificate(cache->issuer); | 1091 CERT_DestroyCertificate(cache->issuer); |
1167 } | 1092 } |
1168 #endif | 1093 #endif |
1169 /* free the subject */ | 1094 /* free the subject */ |
1170 if (cache->subject) | 1095 if (cache->subject) { |
1171 { | |
1172 SECITEM_FreeItem(cache->subject, PR_TRUE); | 1096 SECITEM_FreeItem(cache->subject, PR_TRUE); |
1173 } | 1097 } |
1174 if (SECSuccess != DPCache_Destroy(cache->dpp)) | 1098 if (SECSuccess != DPCache_Destroy(cache->dpp)) { |
1175 { | |
1176 PORT_Assert(0); | 1099 PORT_Assert(0); |
1177 return SECFailure; | 1100 return SECFailure; |
1178 } | 1101 } |
1179 PORT_Free(cache); | 1102 PORT_Free(cache); |
1180 return SECSuccess; | 1103 return SECSuccess; |
1181 } | 1104 } |
1182 | 1105 |
1183 /* create a named CRL entry object */ | 1106 /* create a named CRL entry object */ |
1184 static SECStatus NamedCRLCacheEntry_Create(NamedCRLCacheEntry** returned) | 1107 static SECStatus |
| 1108 NamedCRLCacheEntry_Create(NamedCRLCacheEntry** returned) |
1185 { | 1109 { |
1186 NamedCRLCacheEntry* entry = NULL; | 1110 NamedCRLCacheEntry* entry = NULL; |
1187 if (!returned) | 1111 if (!returned) { |
1188 { | |
1189 PORT_Assert(0); | 1112 PORT_Assert(0); |
1190 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1113 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1191 return SECFailure; | 1114 return SECFailure; |
1192 } | 1115 } |
1193 *returned = NULL; | 1116 *returned = NULL; |
1194 entry = (NamedCRLCacheEntry*) PORT_ZAlloc(sizeof(NamedCRLCacheEntry)); | 1117 entry = (NamedCRLCacheEntry*)PORT_ZAlloc(sizeof(NamedCRLCacheEntry)); |
1195 if (!entry) | 1118 if (!entry) { |
1196 { | |
1197 return SECFailure; | 1119 return SECFailure; |
1198 } | 1120 } |
1199 *returned = entry; | 1121 *returned = entry; |
1200 return SECSuccess; | 1122 return SECSuccess; |
1201 } | 1123 } |
1202 | 1124 |
1203 /* destroy a named CRL entry object */ | 1125 /* destroy a named CRL entry object */ |
1204 static SECStatus NamedCRLCacheEntry_Destroy(NamedCRLCacheEntry* entry) | 1126 static SECStatus |
| 1127 NamedCRLCacheEntry_Destroy(NamedCRLCacheEntry* entry) |
1205 { | 1128 { |
1206 if (!entry) | 1129 if (!entry) { |
1207 { | |
1208 PORT_Assert(0); | 1130 PORT_Assert(0); |
1209 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1131 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1210 return SECFailure; | 1132 return SECFailure; |
1211 } | 1133 } |
1212 if (entry->crl) | 1134 if (entry->crl) { |
1213 { | |
1214 /* named CRL cache owns DER memory */ | 1135 /* named CRL cache owns DER memory */ |
1215 SECITEM_ZfreeItem(entry->crl, PR_TRUE); | 1136 SECITEM_ZfreeItem(entry->crl, PR_TRUE); |
1216 } | 1137 } |
1217 if (entry->canonicalizedName) | 1138 if (entry->canonicalizedName) { |
1218 { | |
1219 SECITEM_FreeItem(entry->canonicalizedName, PR_TRUE); | 1139 SECITEM_FreeItem(entry->canonicalizedName, PR_TRUE); |
1220 } | 1140 } |
1221 PORT_Free(entry); | 1141 PORT_Free(entry); |
1222 return SECSuccess; | 1142 return SECSuccess; |
1223 } | 1143 } |
1224 | 1144 |
1225 /* callback function used in hash table destructor */ | 1145 /* callback function used in hash table destructor */ |
1226 static PRIntn PR_CALLBACK FreeIssuer(PLHashEntry *he, PRIntn i, void *arg) | 1146 static PRIntn PR_CALLBACK |
| 1147 FreeIssuer(PLHashEntry* he, PRIntn i, void* arg) |
1227 { | 1148 { |
1228 CRLIssuerCache* issuer = NULL; | 1149 CRLIssuerCache* issuer = NULL; |
1229 SECStatus* rv = (SECStatus*) arg; | 1150 SECStatus* rv = (SECStatus*)arg; |
1230 | 1151 |
1231 PORT_Assert(he); | 1152 PORT_Assert(he); |
1232 if (!he) | 1153 if (!he) { |
1233 { | |
1234 return HT_ENUMERATE_NEXT; | 1154 return HT_ENUMERATE_NEXT; |
1235 } | 1155 } |
1236 issuer = (CRLIssuerCache*) he->value; | 1156 issuer = (CRLIssuerCache*)he->value; |
1237 PORT_Assert(issuer); | 1157 PORT_Assert(issuer); |
1238 if (issuer) | 1158 if (issuer) { |
1239 { | 1159 if (SECSuccess != IssuerCache_Destroy(issuer)) { |
1240 if (SECSuccess != IssuerCache_Destroy(issuer)) | |
1241 { | |
1242 PORT_Assert(rv); | 1160 PORT_Assert(rv); |
1243 if (rv) | 1161 if (rv) { |
1244 { | |
1245 *rv = SECFailure; | 1162 *rv = SECFailure; |
1246 } | 1163 } |
1247 return HT_ENUMERATE_NEXT; | 1164 return HT_ENUMERATE_NEXT; |
1248 } | 1165 } |
1249 } | 1166 } |
1250 return HT_ENUMERATE_NEXT; | 1167 return HT_ENUMERATE_NEXT; |
1251 } | 1168 } |
1252 | 1169 |
1253 /* callback function used in hash table destructor */ | 1170 /* callback function used in hash table destructor */ |
1254 static PRIntn PR_CALLBACK FreeNamedEntries(PLHashEntry *he, PRIntn i, void *arg) | 1171 static PRIntn PR_CALLBACK |
| 1172 FreeNamedEntries(PLHashEntry* he, PRIntn i, void* arg) |
1255 { | 1173 { |
1256 NamedCRLCacheEntry* entry = NULL; | 1174 NamedCRLCacheEntry* entry = NULL; |
1257 SECStatus* rv = (SECStatus*) arg; | 1175 SECStatus* rv = (SECStatus*)arg; |
1258 | 1176 |
1259 PORT_Assert(he); | 1177 PORT_Assert(he); |
1260 if (!he) | 1178 if (!he) { |
1261 { | |
1262 return HT_ENUMERATE_NEXT; | 1179 return HT_ENUMERATE_NEXT; |
1263 } | 1180 } |
1264 entry = (NamedCRLCacheEntry*) he->value; | 1181 entry = (NamedCRLCacheEntry*)he->value; |
1265 PORT_Assert(entry); | 1182 PORT_Assert(entry); |
1266 if (entry) | 1183 if (entry) { |
1267 { | 1184 if (SECSuccess != NamedCRLCacheEntry_Destroy(entry)) { |
1268 if (SECSuccess != NamedCRLCacheEntry_Destroy(entry)) | |
1269 { | |
1270 PORT_Assert(rv); | 1185 PORT_Assert(rv); |
1271 if (rv) | 1186 if (rv) { |
1272 { | |
1273 *rv = SECFailure; | 1187 *rv = SECFailure; |
1274 } | 1188 } |
1275 return HT_ENUMERATE_NEXT; | 1189 return HT_ENUMERATE_NEXT; |
1276 } | 1190 } |
1277 } | 1191 } |
1278 return HT_ENUMERATE_NEXT; | 1192 return HT_ENUMERATE_NEXT; |
1279 } | 1193 } |
1280 | 1194 |
1281 /* needs to be called at NSS shutdown time | 1195 /* needs to be called at NSS shutdown time |
1282 This will destroy the global CRL cache, including | 1196 This will destroy the global CRL cache, including |
1283 - the hash table of issuer cache objects | 1197 - the hash table of issuer cache objects |
1284 - the issuer cache objects | 1198 - the issuer cache objects |
1285 - DPCache objects in issuer cache objects */ | 1199 - DPCache objects in issuer cache objects */ |
1286 SECStatus ShutdownCRLCache(void) | 1200 SECStatus |
| 1201 ShutdownCRLCache(void) |
1287 { | 1202 { |
1288 SECStatus rv = SECSuccess; | 1203 SECStatus rv = SECSuccess; |
1289 if (PR_FALSE == crlcache_initialized && | 1204 if (PR_FALSE == crlcache_initialized && !crlcache.lock && |
1290 !crlcache.lock && !crlcache.issuers) | 1205 !crlcache.issuers) { |
1291 { | |
1292 /* CRL cache has already been shut down */ | 1206 /* CRL cache has already been shut down */ |
1293 return SECSuccess; | 1207 return SECSuccess; |
1294 } | 1208 } |
1295 if (PR_TRUE == crlcache_initialized && | 1209 if (PR_TRUE == crlcache_initialized && |
1296 (!crlcache.lock || !crlcache.issuers || !namedCRLCache.lock || | 1210 (!crlcache.lock || !crlcache.issuers || !namedCRLCache.lock || |
1297 !namedCRLCache.entries)) | 1211 !namedCRLCache.entries)) { |
1298 { | |
1299 /* CRL cache has partially been shut down */ | 1212 /* CRL cache has partially been shut down */ |
1300 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1213 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1301 return SECFailure; | 1214 return SECFailure; |
1302 } | 1215 } |
1303 /* empty the CRL cache */ | 1216 /* empty the CRL cache */ |
1304 /* free the issuers */ | 1217 /* free the issuers */ |
1305 PL_HashTableEnumerateEntries(crlcache.issuers, &FreeIssuer, &rv); | 1218 PL_HashTableEnumerateEntries(crlcache.issuers, &FreeIssuer, &rv); |
1306 /* free the hash table of issuers */ | 1219 /* free the hash table of issuers */ |
1307 PL_HashTableDestroy(crlcache.issuers); | 1220 PL_HashTableDestroy(crlcache.issuers); |
1308 crlcache.issuers = NULL; | 1221 crlcache.issuers = NULL; |
1309 /* free the global lock */ | 1222 /* free the global lock */ |
1310 #ifdef GLOBAL_RWLOCK | 1223 #ifdef GLOBAL_RWLOCK |
1311 NSSRWLock_Destroy(crlcache.lock); | 1224 NSSRWLock_Destroy(crlcache.lock); |
1312 #else | 1225 #else |
1313 PR_DestroyLock(crlcache.lock); | 1226 PR_DestroyLock(crlcache.lock); |
1314 #endif | 1227 #endif |
1315 crlcache.lock = NULL; | 1228 crlcache.lock = NULL; |
1316 | 1229 |
1317 /* empty the named CRL cache. This must be done after freeing the CRL | 1230 /* empty the named CRL cache. This must be done after freeing the CRL |
1318 * cache, since some CRLs in this cache are in the memory for the other */ | 1231 * cache, since some CRLs in this cache are in the memory for the other */ |
1319 /* free the entries */ | 1232 /* free the entries */ |
1320 PL_HashTableEnumerateEntries(namedCRLCache.entries, &FreeNamedEntries, &rv); | 1233 PL_HashTableEnumerateEntries(namedCRLCache.entries, &FreeNamedEntries, &rv); |
1321 /* free the hash table of issuers */ | 1234 /* free the hash table of issuers */ |
1322 PL_HashTableDestroy(namedCRLCache.entries); | 1235 PL_HashTableDestroy(namedCRLCache.entries); |
1323 namedCRLCache.entries = NULL; | 1236 namedCRLCache.entries = NULL; |
1324 /* free the global lock */ | 1237 /* free the global lock */ |
1325 PR_DestroyLock(namedCRLCache.lock); | 1238 PR_DestroyLock(namedCRLCache.lock); |
1326 namedCRLCache.lock = NULL; | 1239 namedCRLCache.lock = NULL; |
1327 | 1240 |
1328 crlcache_initialized = PR_FALSE; | 1241 crlcache_initialized = PR_FALSE; |
1329 return rv; | 1242 return rv; |
1330 } | 1243 } |
1331 | 1244 |
1332 /* add a new CRL object to the dynamic array of CRLs of the DPCache, and | 1245 /* add a new CRL object to the dynamic array of CRLs of the DPCache, and |
1333 returns the cached CRL object . Needs write access to DPCache. */ | 1246 returns the cached CRL object . Needs write access to DPCache. */ |
1334 static SECStatus DPCache_AddCRL(CRLDPCache* cache, CachedCrl* newcrl, | 1247 static SECStatus |
1335 PRBool* added) | 1248 DPCache_AddCRL(CRLDPCache* cache, CachedCrl* newcrl, PRBool* added) |
1336 { | 1249 { |
1337 CachedCrl** newcrls = NULL; | 1250 CachedCrl** newcrls = NULL; |
1338 PRUint32 i = 0; | 1251 PRUint32 i = 0; |
1339 PORT_Assert(cache); | 1252 PORT_Assert(cache); |
1340 PORT_Assert(newcrl); | 1253 PORT_Assert(newcrl); |
1341 PORT_Assert(added); | 1254 PORT_Assert(added); |
1342 if (!cache || !newcrl || !added) | 1255 if (!cache || !newcrl || !added) { |
1343 { | |
1344 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1256 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1345 return SECFailure; | 1257 return SECFailure; |
1346 } | 1258 } |
1347 | 1259 |
1348 *added = PR_FALSE; | 1260 *added = PR_FALSE; |
1349 /* before adding a new CRL, check if it is a duplicate */ | 1261 /* before adding a new CRL, check if it is a duplicate */ |
1350 for (i=0;i<cache->ncrls;i++) | 1262 for (i = 0; i < cache->ncrls; i++) { |
1351 { | |
1352 CachedCrl* existing = NULL; | 1263 CachedCrl* existing = NULL; |
1353 SECStatus rv = SECSuccess; | 1264 SECStatus rv = SECSuccess; |
1354 PRBool dupe = PR_FALSE, updated = PR_FALSE; | 1265 PRBool dupe = PR_FALSE, updated = PR_FALSE; |
1355 if (!cache->crls) | 1266 if (!cache->crls) { |
1356 { | |
1357 PORT_Assert(0); | 1267 PORT_Assert(0); |
1358 return SECFailure; | 1268 return SECFailure; |
1359 } | 1269 } |
1360 existing = cache->crls[i]; | 1270 existing = cache->crls[i]; |
1361 if (!existing) | 1271 if (!existing) { |
1362 { | |
1363 PORT_Assert(0); | 1272 PORT_Assert(0); |
1364 return SECFailure; | 1273 return SECFailure; |
1365 } | 1274 } |
1366 rv = CachedCrl_Compare(existing, newcrl, &dupe, &updated); | 1275 rv = CachedCrl_Compare(existing, newcrl, &dupe, &updated); |
1367 if (SECSuccess != rv) | 1276 if (SECSuccess != rv) { |
1368 { | |
1369 PORT_Assert(0); | 1277 PORT_Assert(0); |
1370 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1278 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1371 return SECFailure; | 1279 return SECFailure; |
1372 } | 1280 } |
1373 if (PR_TRUE == dupe) | 1281 if (PR_TRUE == dupe) { |
1374 { | |
1375 /* dupe */ | 1282 /* dupe */ |
1376 PORT_SetError(SEC_ERROR_CRL_ALREADY_EXISTS); | 1283 PORT_SetError(SEC_ERROR_CRL_ALREADY_EXISTS); |
1377 return SECSuccess; | 1284 return SECSuccess; |
1378 } | 1285 } |
1379 if (PR_TRUE == updated) | 1286 if (PR_TRUE == updated) { |
1380 { | |
1381 /* this token CRL is in the same slot and has the same object ID, | 1287 /* this token CRL is in the same slot and has the same object ID, |
1382 but different content. We need to remove the old object */ | 1288 but different content. We need to remove the old object */ |
1383 if (SECSuccess != DPCache_RemoveCRL(cache, i)) | 1289 if (SECSuccess != DPCache_RemoveCRL(cache, i)) { |
1384 { | |
1385 PORT_Assert(0); | 1290 PORT_Assert(0); |
1386 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1291 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1387 return PR_FALSE; | 1292 return PR_FALSE; |
1388 } | 1293 } |
1389 } | 1294 } |
1390 } | 1295 } |
1391 | 1296 |
1392 newcrls = (CachedCrl**)PORT_Realloc(cache->crls, | 1297 newcrls = (CachedCrl**)PORT_Realloc(cache->crls, (cache->ncrls + 1) * |
1393 (cache->ncrls+1)*sizeof(CachedCrl*)); | 1298 sizeof(CachedCrl*)); |
1394 if (!newcrls) | 1299 if (!newcrls) { |
1395 { | |
1396 return SECFailure; | 1300 return SECFailure; |
1397 } | 1301 } |
1398 cache->crls = newcrls; | 1302 cache->crls = newcrls; |
1399 cache->ncrls++; | 1303 cache->ncrls++; |
1400 cache->crls[cache->ncrls-1] = newcrl; | 1304 cache->crls[cache->ncrls - 1] = newcrl; |
1401 *added = PR_TRUE; | 1305 *added = PR_TRUE; |
1402 return SECSuccess; | 1306 return SECSuccess; |
1403 } | 1307 } |
1404 | 1308 |
1405 /* remove CRL at offset specified */ | 1309 /* remove CRL at offset specified */ |
1406 static SECStatus DPCache_RemoveCRL(CRLDPCache* cache, PRUint32 offset) | 1310 static SECStatus |
| 1311 DPCache_RemoveCRL(CRLDPCache* cache, PRUint32 offset) |
1407 { | 1312 { |
1408 CachedCrl* acrl = NULL; | 1313 CachedCrl* acrl = NULL; |
1409 PORT_Assert(cache); | 1314 PORT_Assert(cache); |
1410 if (!cache || (!cache->crls) || (!(offset<cache->ncrls)) ) | 1315 if (!cache || (!cache->crls) || (!(offset < cache->ncrls))) { |
1411 { | |
1412 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1316 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1413 return SECFailure; | 1317 return SECFailure; |
1414 } | 1318 } |
1415 acrl = cache->crls[offset]; | 1319 acrl = cache->crls[offset]; |
1416 PORT_Assert(acrl); | 1320 PORT_Assert(acrl); |
1417 if (!acrl) | 1321 if (!acrl) { |
1418 { | |
1419 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1322 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1420 return SECFailure; | 1323 return SECFailure; |
1421 } | 1324 } |
1422 cache->crls[offset] = cache->crls[cache->ncrls-1]; | 1325 cache->crls[offset] = cache->crls[cache->ncrls - 1]; |
1423 cache->crls[cache->ncrls-1] = NULL; | 1326 cache->crls[cache->ncrls - 1] = NULL; |
1424 cache->ncrls--; | 1327 cache->ncrls--; |
1425 if (cache->selected == acrl) { | 1328 if (cache->selected == acrl) { |
1426 cache->selected = NULL; | 1329 cache->selected = NULL; |
1427 } | 1330 } |
1428 if (SECSuccess != CachedCrl_Destroy(acrl)) | 1331 if (SECSuccess != CachedCrl_Destroy(acrl)) { |
1429 { | |
1430 PORT_Assert(0); | 1332 PORT_Assert(0); |
1431 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1333 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1432 return SECFailure; | 1334 return SECFailure; |
1433 } | 1335 } |
1434 return SECSuccess; | 1336 return SECSuccess; |
1435 } | 1337 } |
1436 | 1338 |
1437 /* check whether a CRL object stored in a PKCS#11 token still exists in | 1339 /* check whether a CRL object stored in a PKCS#11 token still exists in |
1438 that token . This has to be efficient (the entire CRL value cannot be | 1340 that token . This has to be efficient (the entire CRL value cannot be |
1439 transferred accross the token boundaries), so this is accomplished by | 1341 transferred accross the token boundaries), so this is accomplished by |
1440 simply fetching the subject attribute and making sure it hasn't changed . | 1342 simply fetching the subject attribute and making sure it hasn't changed . |
1441 Note that technically, the CRL object could have been replaced with a new | 1343 Note that technically, the CRL object could have been replaced with a new |
1442 PKCS#11 object of the same ID and subject (which actually happens in | 1344 PKCS#11 object of the same ID and subject (which actually happens in |
1443 softoken), but this function has no way of knowing that the object | 1345 softoken), but this function has no way of knowing that the object |
1444 value changed, since CKA_VALUE isn't checked. */ | 1346 value changed, since CKA_VALUE isn't checked. */ |
1445 static PRBool TokenCRLStillExists(CERTSignedCrl* crl) | 1347 static PRBool |
| 1348 TokenCRLStillExists(CERTSignedCrl* crl) |
1446 { | 1349 { |
1447 NSSItem newsubject; | 1350 NSSItem newsubject; |
1448 SECItem subject; | 1351 SECItem subject; |
1449 CK_ULONG crl_class; | 1352 CK_ULONG crl_class; |
1450 PRStatus status; | 1353 PRStatus status; |
1451 PK11SlotInfo* slot = NULL; | 1354 PK11SlotInfo* slot = NULL; |
1452 nssCryptokiObject instance; | 1355 nssCryptokiObject instance; |
1453 NSSArena* arena; | 1356 NSSArena* arena; |
1454 PRBool xstatus = PR_TRUE; | 1357 PRBool xstatus = PR_TRUE; |
1455 SECItem* oldSubject = NULL; | 1358 SECItem* oldSubject = NULL; |
1456 | 1359 |
1457 PORT_Assert(crl); | 1360 PORT_Assert(crl); |
1458 if (!crl) | 1361 if (!crl) { |
1459 { | |
1460 return PR_FALSE; | 1362 return PR_FALSE; |
1461 } | 1363 } |
1462 slot = crl->slot; | 1364 slot = crl->slot; |
1463 PORT_Assert(crl->slot); | 1365 PORT_Assert(crl->slot); |
1464 if (!slot) | 1366 if (!slot) { |
1465 { | |
1466 return PR_FALSE; | 1367 return PR_FALSE; |
1467 } | 1368 } |
1468 oldSubject = &crl->crl.derName; | 1369 oldSubject = &crl->crl.derName; |
1469 PORT_Assert(oldSubject); | 1370 PORT_Assert(oldSubject); |
1470 if (!oldSubject) | 1371 if (!oldSubject) { |
1471 { | |
1472 return PR_FALSE; | 1372 return PR_FALSE; |
1473 } | 1373 } |
1474 | 1374 |
1475 /* query subject and type attributes in order to determine if the | 1375 /* query subject and type attributes in order to determine if the |
1476 object has been deleted */ | 1376 object has been deleted */ |
1477 | 1377 |
1478 /* first, make an nssCryptokiObject */ | 1378 /* first, make an nssCryptokiObject */ |
1479 instance.handle = crl->pkcs11ID; | 1379 instance.handle = crl->pkcs11ID; |
1480 PORT_Assert(instance.handle); | 1380 PORT_Assert(instance.handle); |
1481 if (!instance.handle) | 1381 if (!instance.handle) { |
1482 { | |
1483 return PR_FALSE; | 1382 return PR_FALSE; |
1484 } | 1383 } |
1485 instance.token = PK11Slot_GetNSSToken(slot); | 1384 instance.token = PK11Slot_GetNSSToken(slot); |
1486 PORT_Assert(instance.token); | 1385 PORT_Assert(instance.token); |
1487 if (!instance.token) | 1386 if (!instance.token) { |
1488 { | |
1489 return PR_FALSE; | 1387 return PR_FALSE; |
1490 } | 1388 } |
1491 instance.isTokenObject = PR_TRUE; | 1389 instance.isTokenObject = PR_TRUE; |
1492 instance.label = NULL; | 1390 instance.label = NULL; |
1493 | 1391 |
1494 arena = NSSArena_Create(); | 1392 arena = NSSArena_Create(); |
1495 PORT_Assert(arena); | 1393 PORT_Assert(arena); |
1496 if (!arena) | 1394 if (!arena) { |
1497 { | |
1498 return PR_FALSE; | 1395 return PR_FALSE; |
1499 } | 1396 } |
1500 | 1397 |
1501 status = nssCryptokiCRL_GetAttributes(&instance, | 1398 status = |
1502 NULL, /* XXX sessionOpt */ | 1399 nssCryptokiCRL_GetAttributes(&instance, NULL, /* XXX sessionOpt
*/ |
1503 arena, | 1400 arena, NULL, &newsubject, /* subject */ |
1504 NULL, | 1401 &crl_class, /* class */ |
1505 &newsubject, /* subject */ | 1402 NULL, NULL); |
1506 &crl_class, /* class */ | 1403 if (PR_SUCCESS == status) { |
1507 NULL, | |
1508 NULL); | |
1509 if (PR_SUCCESS == status) | |
1510 { | |
1511 subject.data = newsubject.data; | 1404 subject.data = newsubject.data; |
1512 subject.len = newsubject.size; | 1405 subject.len = newsubject.size; |
1513 if (SECITEM_CompareItem(oldSubject, &subject) != SECEqual) | 1406 if (SECITEM_CompareItem(oldSubject, &subject) != SECEqual) { |
1514 { | |
1515 xstatus = PR_FALSE; | 1407 xstatus = PR_FALSE; |
1516 } | 1408 } |
1517 if (CKO_NETSCAPE_CRL != crl_class) | 1409 if (CKO_NETSCAPE_CRL != crl_class) { |
1518 { | |
1519 xstatus = PR_FALSE; | 1410 xstatus = PR_FALSE; |
1520 } | 1411 } |
1521 } | 1412 } else { |
1522 else | |
1523 { | |
1524 xstatus = PR_FALSE; | 1413 xstatus = PR_FALSE; |
1525 } | 1414 } |
1526 NSSArena_Destroy(arena); | 1415 NSSArena_Destroy(arena); |
1527 return xstatus; | 1416 return xstatus; |
1528 } | 1417 } |
1529 | 1418 |
1530 /* verify the signature of a CRL against its issuer at a given date */ | 1419 /* verify the signature of a CRL against its issuer at a given date */ |
1531 static SECStatus CERT_VerifyCRL( | 1420 static SECStatus |
1532 CERTSignedCrl* crlobject, | 1421 CERT_VerifyCRL(CERTSignedCrl* crlobject, CERTCertificate* issuer, PRTime vfdate, |
1533 CERTCertificate* issuer, | 1422 void* wincx) |
1534 PRTime vfdate, | |
1535 void* wincx) | |
1536 { | 1423 { |
1537 return CERT_VerifySignedData(&crlobject->signatureWrap, | 1424 return CERT_VerifySignedData(&crlobject->signatureWrap, issuer, vfdate, |
1538 issuer, vfdate, wincx); | 1425 wincx); |
1539 } | 1426 } |
1540 | 1427 |
1541 /* verify a CRL and update cache state */ | 1428 /* verify a CRL and update cache state */ |
1542 static SECStatus CachedCrl_Verify(CRLDPCache* cache, CachedCrl* crlobject, | 1429 static SECStatus |
1543 PRTime vfdate, void* wincx) | 1430 CachedCrl_Verify(CRLDPCache* cache, CachedCrl* crlobject, PRTime vfdate, |
| 1431 void* wincx) |
1544 { | 1432 { |
1545 /* Check if it is an invalid CRL | 1433 /* Check if it is an invalid CRL |
1546 if we got a bad CRL, we want to cache it in order to avoid | 1434 if we got a bad CRL, we want to cache it in order to avoid |
1547 subsequent fetches of this same identical bad CRL. We set | 1435 subsequent fetches of this same identical bad CRL. We set |
1548 the cache to the invalid state to ensure that all certs on this | 1436 the cache to the invalid state to ensure that all certs on this |
1549 DP are considered to have unknown status from now on. The cache | 1437 DP are considered to have unknown status from now on. The cache |
1550 object will remain in this state until the bad CRL object | 1438 object will remain in this state until the bad CRL object |
1551 is removed from the token it was fetched from. If the cause | 1439 is removed from the token it was fetched from. If the cause |
1552 of the failure is that we didn't have the issuer cert to | 1440 of the failure is that we didn't have the issuer cert to |
1553 verify the signature, this state can be cleared when | 1441 verify the signature, this state can be cleared when |
1554 the issuer certificate becomes available if that causes the | 1442 the issuer certificate becomes available if that causes the |
1555 signature to verify */ | 1443 signature to verify */ |
1556 | 1444 |
1557 if (!cache || !crlobject) | 1445 if (!cache || !crlobject) { |
1558 { | |
1559 PORT_Assert(0); | 1446 PORT_Assert(0); |
1560 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1447 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1561 return SECFailure; | 1448 return SECFailure; |
1562 } | 1449 } |
1563 if (PR_TRUE == GetOpaqueCRLFields(crlobject->crl)->decodingError) | 1450 if (PR_TRUE == GetOpaqueCRLFields(crlobject->crl)->decodingError) { |
1564 { | |
1565 crlobject->sigChecked = PR_TRUE; /* we can never verify a CRL | 1451 crlobject->sigChecked = PR_TRUE; /* we can never verify a CRL |
1566 with bogus DER. Mark it checked so we won't try again */ | 1452 with bogus DER. Mark it checked so we won't try again */ |
1567 PORT_SetError(SEC_ERROR_BAD_DER); | 1453 PORT_SetError(SEC_ERROR_BAD_DER); |
1568 return SECSuccess; | 1454 return SECSuccess; |
1569 } | 1455 } else { |
1570 else | |
1571 { | |
1572 SECStatus signstatus = SECFailure; | 1456 SECStatus signstatus = SECFailure; |
1573 if (cache->issuerDERCert) | 1457 if (cache->issuerDERCert) { |
1574 { | 1458 CERTCertificate* issuer = CERT_NewTempCertificate( |
1575 » CERTCertificate *issuer = CERT_NewTempCertificate(cache->dbHandle, | 1459 cache->dbHandle, cache->issuerDERCert, NULL, PR_FALSE, PR_TRUE); |
1576 » » cache->issuerDERCert, NULL, PR_FALSE, PR_TRUE); | |
1577 | 1460 |
1578 » if (issuer) { | 1461 if (issuer) { |
1579 signstatus = CERT_VerifyCRL(crlobject->crl, issuer, vfdate, | 1462 signstatus = |
1580 wincx); | 1463 CERT_VerifyCRL(crlobject->crl, issuer, vfdate, wincx); |
1581 » » CERT_DestroyCertificate(issuer); | 1464 CERT_DestroyCertificate(issuer); |
1582 » } | 1465 } |
1583 } | 1466 } |
1584 if (SECSuccess != signstatus) | 1467 if (SECSuccess != signstatus) { |
1585 { | 1468 if (!cache->issuerDERCert) { |
1586 if (!cache->issuerDERCert) | |
1587 { | |
1588 /* we tried to verify without an issuer cert . This is | 1469 /* we tried to verify without an issuer cert . This is |
1589 because this CRL came through a call to SEC_FindCrlByName. | 1470 because this CRL came through a call to SEC_FindCrlByName. |
1590 So, we don't cache this verification failure. We'll try | 1471 So, we don't cache this verification failure. We'll try |
1591 to verify the CRL again when a certificate from that issuer | 1472 to verify the CRL again when a certificate from that issuer |
1592 becomes available */ | 1473 becomes available */ |
1593 } else | 1474 } else { |
1594 { | |
1595 crlobject->sigChecked = PR_TRUE; | 1475 crlobject->sigChecked = PR_TRUE; |
1596 } | 1476 } |
1597 PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE); | 1477 PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE); |
1598 return SECSuccess; | 1478 return SECSuccess; |
1599 } else | 1479 } else { |
1600 { | |
1601 crlobject->sigChecked = PR_TRUE; | 1480 crlobject->sigChecked = PR_TRUE; |
1602 crlobject->sigValid = PR_TRUE; | 1481 crlobject->sigValid = PR_TRUE; |
1603 } | 1482 } |
1604 } | 1483 } |
1605 | 1484 |
1606 return SECSuccess; | 1485 return SECSuccess; |
1607 } | 1486 } |
1608 | 1487 |
1609 /* fetch the CRLs for this DP from the PKCS#11 tokens */ | 1488 /* fetch the CRLs for this DP from the PKCS#11 tokens */ |
1610 static SECStatus DPCache_FetchFromTokens(CRLDPCache* cache, PRTime vfdate, | 1489 static SECStatus |
1611 void* wincx) | 1490 DPCache_FetchFromTokens(CRLDPCache* cache, PRTime vfdate, void* wincx) |
1612 { | 1491 { |
1613 SECStatus rv = SECSuccess; | 1492 SECStatus rv = SECSuccess; |
1614 CERTCrlHeadNode head; | 1493 CERTCrlHeadNode head; |
1615 if (!cache) | 1494 if (!cache) { |
1616 { | |
1617 PORT_Assert(0); | 1495 PORT_Assert(0); |
1618 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1496 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1619 return SECFailure; | 1497 return SECFailure; |
1620 } | 1498 } |
1621 /* first, initialize list */ | 1499 /* first, initialize list */ |
1622 memset(&head, 0, sizeof(head)); | 1500 memset(&head, 0, sizeof(head)); |
1623 head.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 1501 head.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
1624 rv = pk11_RetrieveCrls(&head, cache->subject, wincx); | 1502 rv = pk11_RetrieveCrls(&head, cache->subject, wincx); |
1625 | 1503 |
1626 /* if this function fails, something very wrong happened, such as an out | 1504 /* if this function fails, something very wrong happened, such as an out |
1627 of memory error during CRL decoding. We don't want to proceed and must | 1505 of memory error during CRL decoding. We don't want to proceed and must |
1628 mark the cache object invalid */ | 1506 mark the cache object invalid */ |
1629 if (SECFailure == rv) | 1507 if (SECFailure == rv) { |
1630 { | |
1631 /* fetch failed, add error bit */ | 1508 /* fetch failed, add error bit */ |
1632 cache->invalid |= CRL_CACHE_LAST_FETCH_FAILED; | 1509 cache->invalid |= CRL_CACHE_LAST_FETCH_FAILED; |
1633 } else | 1510 } else { |
1634 { | |
1635 /* fetch was successful, clear this error bit */ | 1511 /* fetch was successful, clear this error bit */ |
1636 cache->invalid &= (~CRL_CACHE_LAST_FETCH_FAILED); | 1512 cache->invalid &= (~CRL_CACHE_LAST_FETCH_FAILED); |
1637 } | 1513 } |
1638 | 1514 |
1639 /* add any CRLs found to our array */ | 1515 /* add any CRLs found to our array */ |
1640 if (SECSuccess == rv) | 1516 if (SECSuccess == rv) { |
1641 { | |
1642 CERTCrlNode* crlNode = NULL; | 1517 CERTCrlNode* crlNode = NULL; |
1643 | 1518 |
1644 for (crlNode = head.first; crlNode ; crlNode = crlNode->next) | 1519 for (crlNode = head.first; crlNode; crlNode = crlNode->next) { |
1645 { | |
1646 CachedCrl* returned = NULL; | 1520 CachedCrl* returned = NULL; |
1647 CERTSignedCrl* crlobject = crlNode->crl; | 1521 CERTSignedCrl* crlobject = crlNode->crl; |
1648 if (!crlobject) | 1522 if (!crlobject) { |
1649 { | |
1650 PORT_Assert(0); | 1523 PORT_Assert(0); |
1651 continue; | 1524 continue; |
1652 } | 1525 } |
1653 rv = CachedCrl_Create(&returned, crlobject, CRL_OriginToken); | 1526 rv = CachedCrl_Create(&returned, crlobject, CRL_OriginToken); |
1654 if (SECSuccess == rv) | 1527 if (SECSuccess == rv) { |
1655 { | |
1656 PRBool added = PR_FALSE; | 1528 PRBool added = PR_FALSE; |
1657 rv = DPCache_AddCRL(cache, returned, &added); | 1529 rv = DPCache_AddCRL(cache, returned, &added); |
1658 if (PR_TRUE != added) | 1530 if (PR_TRUE != added) { |
1659 { | |
1660 rv = CachedCrl_Destroy(returned); | 1531 rv = CachedCrl_Destroy(returned); |
1661 returned = NULL; | 1532 returned = NULL; |
1662 } | 1533 } else if (vfdate) { |
1663 else if (vfdate) | |
1664 { | |
1665 rv = CachedCrl_Verify(cache, returned, vfdate, wincx); | 1534 rv = CachedCrl_Verify(cache, returned, vfdate, wincx); |
1666 } | 1535 } |
1667 } | 1536 } else { |
1668 else | |
1669 { | |
1670 /* not enough memory to add the CRL to the cache. mark it | 1537 /* not enough memory to add the CRL to the cache. mark it |
1671 invalid so we will try again . */ | 1538 invalid so we will try again . */ |
1672 cache->invalid |= CRL_CACHE_LAST_FETCH_FAILED; | 1539 cache->invalid |= CRL_CACHE_LAST_FETCH_FAILED; |
1673 } | 1540 } |
1674 if (SECFailure == rv) | 1541 if (SECFailure == rv) { |
1675 { | |
1676 break; | 1542 break; |
1677 } | 1543 } |
1678 } | 1544 } |
1679 } | 1545 } |
1680 | 1546 |
1681 if (head.arena) | 1547 if (head.arena) { |
1682 { | |
1683 CERTCrlNode* crlNode = NULL; | 1548 CERTCrlNode* crlNode = NULL; |
1684 /* clean up the CRL list in case we got a partial one | 1549 /* clean up the CRL list in case we got a partial one |
1685 during a failed fetch */ | 1550 during a failed fetch */ |
1686 for (crlNode = head.first; crlNode ; crlNode = crlNode->next) | 1551 for (crlNode = head.first; crlNode; crlNode = crlNode->next) { |
1687 { | 1552 if (crlNode->crl) { |
1688 if (crlNode->crl) | |
1689 { | |
1690 SEC_DestroyCrl(crlNode->crl); /* free the CRL. Either it got | 1553 SEC_DestroyCrl(crlNode->crl); /* free the CRL. Either it got |
1691 added to the cache and the refcount got bumped, or not, and | 1554 added to the cache and the refcount got bumped, or not, and |
1692 thus we need to free its RAM */ | 1555 thus we need to free its RAM */ |
1693 } | 1556 } |
1694 } | 1557 } |
1695 PORT_FreeArena(head.arena, PR_FALSE); /* destroy CRL list */ | 1558 PORT_FreeArena(head.arena, PR_FALSE); /* destroy CRL list */ |
1696 } | 1559 } |
1697 | 1560 |
1698 return rv; | 1561 return rv; |
1699 } | 1562 } |
1700 | 1563 |
1701 static SECStatus CachedCrl_GetEntry(CachedCrl* crl, const SECItem* sn, | 1564 static SECStatus |
1702 CERTCrlEntry** returned) | 1565 CachedCrl_GetEntry(CachedCrl* crl, const SECItem* sn, CERTCrlEntry** returned) |
1703 { | 1566 { |
1704 CERTCrlEntry* acrlEntry; | 1567 CERTCrlEntry* acrlEntry; |
1705 | 1568 |
1706 PORT_Assert(crl); | 1569 PORT_Assert(crl); |
1707 PORT_Assert(crl->entries); | 1570 PORT_Assert(crl->entries); |
1708 PORT_Assert(sn); | 1571 PORT_Assert(sn); |
1709 PORT_Assert(returned); | 1572 PORT_Assert(returned); |
1710 if (!crl || !sn || !returned || !crl->entries) | 1573 if (!crl || !sn || !returned || !crl->entries) { |
1711 { | |
1712 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1574 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1713 return SECFailure; | 1575 return SECFailure; |
1714 } | 1576 } |
1715 acrlEntry = PL_HashTableLookup(crl->entries, (void*)sn); | 1577 acrlEntry = PL_HashTableLookup(crl->entries, (void*)sn); |
1716 if (acrlEntry) | 1578 if (acrlEntry) { |
1717 { | |
1718 *returned = acrlEntry; | 1579 *returned = acrlEntry; |
1719 } | 1580 } else { |
1720 else | |
1721 { | |
1722 *returned = NULL; | 1581 *returned = NULL; |
1723 } | 1582 } |
1724 return SECSuccess; | 1583 return SECSuccess; |
1725 } | 1584 } |
1726 | 1585 |
1727 /* check if a particular SN is in the CRL cache and return its entry */ | 1586 /* check if a particular SN is in the CRL cache and return its entry */ |
1728 dpcacheStatus DPCache_Lookup(CRLDPCache* cache, const SECItem* sn, | 1587 dpcacheStatus |
1729 CERTCrlEntry** returned) | 1588 DPCache_Lookup(CRLDPCache* cache, const SECItem* sn, CERTCrlEntry** returned) |
1730 { | 1589 { |
1731 SECStatus rv; | 1590 SECStatus rv; |
1732 if (!cache || !sn || !returned) | 1591 if (!cache || !sn || !returned) { |
1733 { | |
1734 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 1592 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
1735 /* no cache or SN to look up, or no way to return entry */ | 1593 /* no cache or SN to look up, or no way to return entry */ |
1736 return dpcacheCallerError; | 1594 return dpcacheCallerError; |
1737 } | 1595 } |
1738 *returned = NULL; | 1596 *returned = NULL; |
1739 if (0 != cache->invalid) | 1597 if (0 != cache->invalid) { |
1740 { | |
1741 /* the cache contains a bad CRL, or there was a CRL fetching error. */ | 1598 /* the cache contains a bad CRL, or there was a CRL fetching error. */ |
1742 PORT_SetError(SEC_ERROR_CRL_INVALID); | 1599 PORT_SetError(SEC_ERROR_CRL_INVALID); |
1743 return dpcacheInvalidCacheError; | 1600 return dpcacheInvalidCacheError; |
1744 } | 1601 } |
1745 if (!cache->selected) | 1602 if (!cache->selected) { |
1746 { | |
1747 /* no CRL means no entry to return. This is OK, except for | 1603 /* no CRL means no entry to return. This is OK, except for |
1748 * NIST policy */ | 1604 * NIST policy */ |
1749 return dpcacheEmpty; | 1605 return dpcacheEmpty; |
1750 } | 1606 } |
1751 rv = CachedCrl_GetEntry(cache->selected, sn, returned); | 1607 rv = CachedCrl_GetEntry(cache->selected, sn, returned); |
1752 if (SECSuccess != rv) | 1608 if (SECSuccess != rv) { |
1753 { | |
1754 return dpcacheLookupError; | 1609 return dpcacheLookupError; |
1755 } | 1610 } else { |
1756 else | 1611 if (*returned) { |
1757 { | |
1758 if (*returned) | |
1759 { | |
1760 return dpcacheFoundEntry; | 1612 return dpcacheFoundEntry; |
1761 } | 1613 } else { |
1762 else | |
1763 { | |
1764 return dpcacheNoEntry; | 1614 return dpcacheNoEntry; |
1765 } | 1615 } |
1766 } | 1616 } |
1767 } | 1617 } |
1768 | 1618 |
1769 #if defined(DPC_RWLOCK) | 1619 #if defined(DPC_RWLOCK) |
1770 | 1620 |
1771 #define DPCache_LockWrite() \ | 1621 #define DPCache_LockWrite() \ |
1772 { \ | 1622 { \ |
1773 if (readlocked) \ | 1623 if (readlocked) { \ |
1774 { \ | 1624 NSSRWLock_UnlockRead(cache->lock); \ |
1775 NSSRWLock_UnlockRead(cache->lock); \ | 1625 } \ |
1776 } \ | 1626 NSSRWLock_LockWrite(cache->lock); \ |
1777 NSSRWLock_LockWrite(cache->lock); \ | 1627 } |
1778 } | |
1779 | 1628 |
1780 #define DPCache_UnlockWrite() \ | 1629 #define DPCache_UnlockWrite() \ |
1781 { \ | 1630 { \ |
1782 if (readlocked) \ | 1631 if (readlocked) { \ |
1783 { \ | 1632 NSSRWLock_LockRead(cache->lock); \ |
1784 NSSRWLock_LockRead(cache->lock); \ | 1633 } \ |
1785 } \ | 1634 NSSRWLock_UnlockWrite(cache->lock); \ |
1786 NSSRWLock_UnlockWrite(cache->lock); \ | 1635 } |
1787 } | |
1788 | 1636 |
1789 #else | 1637 #else |
1790 | 1638 |
1791 /* with a global lock, we are always locked for read before we need write | 1639 /* with a global lock, we are always locked for read before we need write |
1792 access, so do nothing */ | 1640 access, so do nothing */ |
1793 | 1641 |
1794 #define DPCache_LockWrite() \ | 1642 #define DPCache_LockWrite() \ |
1795 { \ | 1643 { \ |
1796 } | 1644 } |
1797 | 1645 |
1798 #define DPCache_UnlockWrite() \ | 1646 #define DPCache_UnlockWrite() \ |
1799 { \ | 1647 { \ |
1800 } | 1648 } |
1801 | 1649 |
1802 #endif | 1650 #endif |
1803 | 1651 |
1804 /* update the content of the CRL cache, including fetching of CRLs, and | 1652 /* update the content of the CRL cache, including fetching of CRLs, and |
1805 reprocessing with specified issuer and date . We are always holding | 1653 reprocessing with specified issuer and date . We are always holding |
1806 either the read or write lock on DPCache upon entry. */ | 1654 either the read or write lock on DPCache upon entry. */ |
1807 static SECStatus DPCache_GetUpToDate(CRLDPCache* cache, CERTCertificate* | 1655 static SECStatus |
1808 issuer, PRBool readlocked, PRTime vfdate, | 1656 DPCache_GetUpToDate(CRLDPCache* cache, CERTCertificate* issuer, |
1809 void* wincx) | 1657 PRBool readlocked, PRTime vfdate, void* wincx) |
1810 { | 1658 { |
1811 /* Update the CRLDPCache now. We don't cache token CRL lookup misses | 1659 /* Update the CRLDPCache now. We don't cache token CRL lookup misses |
1812 yet, as we have no way of getting notified of new PKCS#11 object | 1660 yet, as we have no way of getting notified of new PKCS#11 object |
1813 creation that happens in a token */ | 1661 creation that happens in a token */ |
1814 SECStatus rv = SECSuccess; | 1662 SECStatus rv = SECSuccess; |
1815 PRUint32 i = 0; | 1663 PRUint32 i = 0; |
1816 PRBool forcedrefresh = PR_FALSE; | 1664 PRBool forcedrefresh = PR_FALSE; |
1817 PRBool dirty = PR_FALSE; /* whether something was changed in the | 1665 PRBool dirty = PR_FALSE; /* whether something was changed in the |
1818 cache state during this update cycle */ | 1666 cache state during this update cycle */ |
1819 PRBool hastokenCRLs = PR_FALSE; | 1667 PRBool hastokenCRLs = PR_FALSE; |
1820 PRTime now = 0; | 1668 PRTime now = 0; |
1821 PRTime lastfetch = 0; | 1669 PRTime lastfetch = 0; |
1822 PRBool mustunlock = PR_FALSE; | 1670 PRBool mustunlock = PR_FALSE; |
1823 | 1671 |
1824 if (!cache) | 1672 if (!cache) { |
1825 { | |
1826 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1673 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1827 return SECFailure; | 1674 return SECFailure; |
1828 } | 1675 } |
1829 | 1676 |
1830 /* first, make sure we have obtained all the CRLs we need. | 1677 /* first, make sure we have obtained all the CRLs we need. |
1831 We do an expensive token fetch in the following cases : | 1678 We do an expensive token fetch in the following cases : |
1832 1) cache is empty because no fetch was ever performed yet | 1679 1) cache is empty because no fetch was ever performed yet |
1833 2) cache is explicitly set to refresh state | 1680 2) cache is explicitly set to refresh state |
1834 3) cache is in invalid state because last fetch failed | 1681 3) cache is in invalid state because last fetch failed |
1835 4) cache contains no token CRLs, and it's been more than one minute | 1682 4) cache contains no token CRLs, and it's been more than one minute |
1836 since the last fetch | 1683 since the last fetch |
1837 5) cache contains token CRLs, and it's been more than 10 minutes since | 1684 5) cache contains token CRLs, and it's been more than 10 minutes since |
1838 the last fetch | 1685 the last fetch |
1839 */ | 1686 */ |
1840 forcedrefresh = cache->refresh; | 1687 forcedrefresh = cache->refresh; |
1841 lastfetch = cache->lastfetch; | 1688 lastfetch = cache->lastfetch; |
1842 if (PR_TRUE != forcedrefresh && | 1689 if (PR_TRUE != forcedrefresh && |
1843 (!(cache->invalid & CRL_CACHE_LAST_FETCH_FAILED))) | 1690 (!(cache->invalid & CRL_CACHE_LAST_FETCH_FAILED))) { |
1844 { | |
1845 now = PR_Now(); | 1691 now = PR_Now(); |
1846 hastokenCRLs = DPCache_HasTokenCRLs(cache); | 1692 hastokenCRLs = DPCache_HasTokenCRLs(cache); |
1847 } | 1693 } |
1848 if ( (0 == lastfetch) || | 1694 if ((0 == lastfetch) || |
1849 | 1695 |
1850 (PR_TRUE == forcedrefresh) || | 1696 (PR_TRUE == forcedrefresh) || |
1851 | 1697 |
1852 (cache->invalid & CRL_CACHE_LAST_FETCH_FAILED) || | 1698 (cache->invalid & CRL_CACHE_LAST_FETCH_FAILED) || |
1853 | 1699 |
1854 ( (PR_FALSE == hastokenCRLs) && | 1700 ((PR_FALSE == hastokenCRLs) && |
1855 ( (now - cache->lastfetch > CRLCache_Empty_TokenFetch_Interval) || | 1701 ((now - cache->lastfetch > CRLCache_Empty_TokenFetch_Interval) || |
1856 (now < cache->lastfetch)) ) || | 1702 (now < cache->lastfetch))) || |
1857 | 1703 |
1858 ( (PR_TRUE == hastokenCRLs) && | 1704 ((PR_TRUE == hastokenCRLs) && |
1859 ((now - cache->lastfetch > CRLCache_TokenRefetch_Interval) || | 1705 ((now - cache->lastfetch > CRLCache_TokenRefetch_Interval) || |
1860 (now < cache->lastfetch)) ) ) | 1706 (now < cache->lastfetch)))) { |
1861 { | |
1862 /* the cache needs to be refreshed, and/or we had zero CRL for this | 1707 /* the cache needs to be refreshed, and/or we had zero CRL for this |
1863 DP. Try to get one from PKCS#11 tokens */ | 1708 DP. Try to get one from PKCS#11 tokens */ |
1864 DPCache_LockWrite(); | 1709 DPCache_LockWrite(); |
1865 /* check if another thread updated before us, and skip update if so */ | 1710 /* check if another thread updated before us, and skip update if so */ |
1866 if (lastfetch == cache->lastfetch) | 1711 if (lastfetch == cache->lastfetch) { |
1867 { | |
1868 /* we are the first */ | 1712 /* we are the first */ |
1869 rv = DPCache_FetchFromTokens(cache, vfdate, wincx); | 1713 rv = DPCache_FetchFromTokens(cache, vfdate, wincx); |
1870 if (PR_TRUE == cache->refresh) | 1714 if (PR_TRUE == cache->refresh) { |
1871 { | |
1872 cache->refresh = PR_FALSE; /* clear refresh state */ | 1715 cache->refresh = PR_FALSE; /* clear refresh state */ |
1873 } | 1716 } |
1874 dirty = PR_TRUE; | 1717 dirty = PR_TRUE; |
1875 cache->lastfetch = PR_Now(); | 1718 cache->lastfetch = PR_Now(); |
1876 } | 1719 } |
1877 DPCache_UnlockWrite(); | 1720 DPCache_UnlockWrite(); |
1878 } | 1721 } |
1879 | 1722 |
1880 /* now, make sure we have no extraneous CRLs (deleted token objects) | 1723 /* now, make sure we have no extraneous CRLs (deleted token objects) |
1881 we'll do this inexpensive existence check either | 1724 we'll do this inexpensive existence check either |
1882 1) if there was a token object fetch | 1725 1) if there was a token object fetch |
1883 2) every minute */ | 1726 2) every minute */ |
1884 if (( PR_TRUE != dirty) && (!now) ) | 1727 if ((PR_TRUE != dirty) && (!now)) { |
1885 { | |
1886 now = PR_Now(); | 1728 now = PR_Now(); |
1887 } | 1729 } |
1888 if ( (PR_TRUE == dirty) || | 1730 if ((PR_TRUE == dirty) || |
1889 ( (now - cache->lastcheck > CRLCache_ExistenceCheck_Interval) || | 1731 ((now - cache->lastcheck > CRLCache_ExistenceCheck_Interval) || |
1890 (now < cache->lastcheck)) ) | 1732 (now < cache->lastcheck))) { |
1891 { | |
1892 PRTime lastcheck = cache->lastcheck; | 1733 PRTime lastcheck = cache->lastcheck; |
1893 mustunlock = PR_FALSE; | 1734 mustunlock = PR_FALSE; |
1894 /* check if all CRLs still exist */ | 1735 /* check if all CRLs still exist */ |
1895 for (i = 0; (i < cache->ncrls) ; i++) | 1736 for (i = 0; (i < cache->ncrls); i++) { |
1896 { | |
1897 CachedCrl* savcrl = cache->crls[i]; | 1737 CachedCrl* savcrl = cache->crls[i]; |
1898 if ( (!savcrl) || (savcrl && CRL_OriginToken != savcrl->origin)) | 1738 if ((!savcrl) || (savcrl && CRL_OriginToken != savcrl->origin)) { |
1899 { | |
1900 /* we only want to check token CRLs */ | 1739 /* we only want to check token CRLs */ |
1901 continue; | 1740 continue; |
1902 } | 1741 } |
1903 if ((PR_TRUE != TokenCRLStillExists(savcrl->crl))) | 1742 if ((PR_TRUE != TokenCRLStillExists(savcrl->crl))) { |
1904 { | 1743 |
1905 | |
1906 /* this CRL is gone */ | 1744 /* this CRL is gone */ |
1907 if (PR_TRUE != mustunlock) | 1745 if (PR_TRUE != mustunlock) { |
1908 { | |
1909 DPCache_LockWrite(); | 1746 DPCache_LockWrite(); |
1910 mustunlock = PR_TRUE; | 1747 mustunlock = PR_TRUE; |
1911 } | 1748 } |
1912 /* first, we need to check if another thread did an update | 1749 /* first, we need to check if another thread did an update |
1913 before we did */ | 1750 before we did */ |
1914 if (lastcheck == cache->lastcheck) | 1751 if (lastcheck == cache->lastcheck) { |
1915 { | |
1916 /* the CRL is gone. And we are the one to do the update */ | 1752 /* the CRL is gone. And we are the one to do the update */ |
1917 DPCache_RemoveCRL(cache, i); | 1753 DPCache_RemoveCRL(cache, i); |
1918 dirty = PR_TRUE; | 1754 dirty = PR_TRUE; |
1919 } | 1755 } |
1920 /* stay locked here intentionally so we do all the other | 1756 /* stay locked here intentionally so we do all the other |
1921 updates in this thread for the remaining CRLs */ | 1757 updates in this thread for the remaining CRLs */ |
1922 } | 1758 } |
1923 } | 1759 } |
1924 if (PR_TRUE == mustunlock) | 1760 if (PR_TRUE == mustunlock) { |
1925 { | |
1926 cache->lastcheck = PR_Now(); | 1761 cache->lastcheck = PR_Now(); |
1927 DPCache_UnlockWrite(); | 1762 DPCache_UnlockWrite(); |
1928 mustunlock = PR_FALSE; | 1763 mustunlock = PR_FALSE; |
1929 } | 1764 } |
1930 } | 1765 } |
1931 | 1766 |
1932 /* add issuer certificate if it was previously unavailable */ | 1767 /* add issuer certificate if it was previously unavailable */ |
1933 if (issuer && (NULL == cache->issuerDERCert) && | 1768 if (issuer && (NULL == cache->issuerDERCert) && |
1934 (SECSuccess == CERT_CheckCertUsage(issuer, KU_CRL_SIGN))) | 1769 (SECSuccess == CERT_CheckCertUsage(issuer, KU_CRL_SIGN))) { |
1935 { | |
1936 /* if we didn't have a valid issuer cert yet, but we do now. add it */ | 1770 /* if we didn't have a valid issuer cert yet, but we do now. add it */ |
1937 DPCache_LockWrite(); | 1771 DPCache_LockWrite(); |
1938 if (!cache->issuerDERCert) | 1772 if (!cache->issuerDERCert) { |
1939 { | |
1940 dirty = PR_TRUE; | 1773 dirty = PR_TRUE; |
1941 » cache->dbHandle = issuer->dbhandle; | 1774 cache->dbHandle = issuer->dbhandle; |
1942 » cache->issuerDERCert = SECITEM_DupItem(&issuer->derCert); | 1775 cache->issuerDERCert = SECITEM_DupItem(&issuer->derCert); |
1943 } | 1776 } |
1944 DPCache_UnlockWrite(); | 1777 DPCache_UnlockWrite(); |
1945 } | 1778 } |
1946 | 1779 |
1947 /* verify CRLs that couldn't be checked when inserted into the cache | 1780 /* verify CRLs that couldn't be checked when inserted into the cache |
1948 because the issuer cert or a verification date was unavailable. | 1781 because the issuer cert or a verification date was unavailable. |
1949 These are CRLs that were inserted into the cache through | 1782 These are CRLs that were inserted into the cache through |
1950 SEC_FindCrlByName, or through manual insertion, rather than through a | 1783 SEC_FindCrlByName, or through manual insertion, rather than through a |
1951 certificate verification (CERT_CheckCRL) */ | 1784 certificate verification (CERT_CheckCRL) */ |
1952 | 1785 |
1953 if (cache->issuerDERCert && vfdate ) | 1786 if (cache->issuerDERCert && vfdate) { |
1954 { | 1787 mustunlock = PR_FALSE; |
1955 » mustunlock = PR_FALSE; | |
1956 /* re-process all unverified CRLs */ | 1788 /* re-process all unverified CRLs */ |
1957 for (i = 0; i < cache->ncrls ; i++) | 1789 for (i = 0; i < cache->ncrls; i++) { |
1958 { | |
1959 CachedCrl* savcrl = cache->crls[i]; | 1790 CachedCrl* savcrl = cache->crls[i]; |
1960 if (!savcrl) | 1791 if (!savcrl) { |
1961 { | |
1962 continue; | 1792 continue; |
1963 } | 1793 } |
1964 if (PR_TRUE != savcrl->sigChecked) | 1794 if (PR_TRUE != savcrl->sigChecked) { |
1965 { | 1795 if (!mustunlock) { |
1966 if (!mustunlock) | |
1967 { | |
1968 DPCache_LockWrite(); | 1796 DPCache_LockWrite(); |
1969 mustunlock = PR_TRUE; | 1797 mustunlock = PR_TRUE; |
1970 } | 1798 } |
1971 /* first, we need to check if another thread updated | 1799 /* first, we need to check if another thread updated |
1972 it before we did, and abort if it has been modified since | 1800 it before we did, and abort if it has been modified since |
1973 we acquired the lock. Make sure first that the CRL is still | 1801 we acquired the lock. Make sure first that the CRL is still |
1974 in the array at the same position */ | 1802 in the array at the same position */ |
1975 if ( (i<cache->ncrls) && (savcrl == cache->crls[i]) && | 1803 if ((i < cache->ncrls) && (savcrl == cache->crls[i]) && |
1976 (PR_TRUE != savcrl->sigChecked) ) | 1804 (PR_TRUE != savcrl->sigChecked)) { |
1977 { | |
1978 /* the CRL is still there, unverified. Do it */ | 1805 /* the CRL is still there, unverified. Do it */ |
1979 CachedCrl_Verify(cache, savcrl, vfdate, wincx); | 1806 CachedCrl_Verify(cache, savcrl, vfdate, wincx); |
1980 dirty = PR_TRUE; | 1807 dirty = PR_TRUE; |
1981 } | 1808 } |
1982 /* stay locked here intentionally so we do all the other | 1809 /* stay locked here intentionally so we do all the other |
1983 updates in this thread for the remaining CRLs */ | 1810 updates in this thread for the remaining CRLs */ |
1984 } | 1811 } |
1985 if (mustunlock && !dirty) | 1812 if (mustunlock && !dirty) { |
1986 { | |
1987 DPCache_UnlockWrite(); | 1813 DPCache_UnlockWrite(); |
1988 mustunlock = PR_FALSE; | 1814 mustunlock = PR_FALSE; |
1989 } | 1815 } |
1990 } | 1816 } |
1991 } | 1817 } |
1992 | 1818 |
1993 if (dirty || cache->mustchoose) | 1819 if (dirty || cache->mustchoose) { |
1994 { | |
1995 /* changes to the content of the CRL cache necessitate examining all | 1820 /* changes to the content of the CRL cache necessitate examining all |
1996 CRLs for selection of the most appropriate one to cache */ | 1821 CRLs for selection of the most appropriate one to cache */ |
1997 » if (!mustunlock) | 1822 if (!mustunlock) { |
1998 » { | 1823 DPCache_LockWrite(); |
1999 » DPCache_LockWrite(); | 1824 mustunlock = PR_TRUE; |
2000 » mustunlock = PR_TRUE; | 1825 } |
2001 » } | |
2002 DPCache_SelectCRL(cache); | 1826 DPCache_SelectCRL(cache); |
2003 cache->mustchoose = PR_FALSE; | 1827 cache->mustchoose = PR_FALSE; |
2004 } | 1828 } |
2005 if (mustunlock) | 1829 if (mustunlock) |
2006 » DPCache_UnlockWrite(); | 1830 DPCache_UnlockWrite(); |
2007 | 1831 |
2008 return rv; | 1832 return rv; |
2009 } | 1833 } |
2010 | 1834 |
2011 /* callback for qsort to sort by thisUpdate */ | 1835 /* callback for qsort to sort by thisUpdate */ |
2012 static int SortCRLsByThisUpdate(const void* arg1, const void* arg2) | 1836 static int |
| 1837 SortCRLsByThisUpdate(const void* arg1, const void* arg2) |
2013 { | 1838 { |
2014 PRTime timea, timeb; | 1839 PRTime timea, timeb; |
2015 SECStatus rv = SECSuccess; | 1840 SECStatus rv = SECSuccess; |
2016 CachedCrl* a, *b; | 1841 CachedCrl *a, *b; |
2017 | 1842 |
2018 a = *(CachedCrl**) arg1; | 1843 a = *(CachedCrl**)arg1; |
2019 b = *(CachedCrl**) arg2; | 1844 b = *(CachedCrl**)arg2; |
2020 | 1845 |
2021 if (!a || !b) | 1846 if (!a || !b) { |
2022 { | |
2023 PORT_Assert(0); | 1847 PORT_Assert(0); |
2024 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1848 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2025 rv = SECFailure; | 1849 rv = SECFailure; |
2026 } | 1850 } |
2027 | 1851 |
2028 if (SECSuccess == rv) | 1852 if (SECSuccess == rv) { |
2029 { | |
2030 rv = DER_DecodeTimeChoice(&timea, &a->crl->crl.lastUpdate); | 1853 rv = DER_DecodeTimeChoice(&timea, &a->crl->crl.lastUpdate); |
2031 } | 1854 } |
2032 if (SECSuccess == rv) | 1855 if (SECSuccess == rv) { |
2033 { | |
2034 rv = DER_DecodeTimeChoice(&timeb, &b->crl->crl.lastUpdate); | 1856 rv = DER_DecodeTimeChoice(&timeb, &b->crl->crl.lastUpdate); |
2035 } | 1857 } |
2036 if (SECSuccess == rv) | 1858 if (SECSuccess == rv) { |
2037 { | 1859 if (timea > timeb) { |
2038 if (timea > timeb) | |
2039 { | |
2040 return 1; /* a is better than b */ | 1860 return 1; /* a is better than b */ |
2041 } | 1861 } |
2042 if (timea < timeb ) | 1862 if (timea < timeb) { |
2043 { | |
2044 return -1; /* a is not as good as b */ | 1863 return -1; /* a is not as good as b */ |
2045 } | 1864 } |
2046 } | 1865 } |
2047 | 1866 |
2048 /* if they are equal, or if all else fails, use pointer differences */ | 1867 /* if they are equal, or if all else fails, use pointer differences */ |
2049 PORT_Assert(a != b); /* they should never be equal */ | 1868 PORT_Assert(a != b); /* they should never be equal */ |
2050 return a>b?1:-1; | 1869 return a > b ? 1 : -1; |
2051 } | 1870 } |
2052 | 1871 |
2053 /* callback for qsort to sort a set of disparate CRLs, some of which are | 1872 /* callback for qsort to sort a set of disparate CRLs, some of which are |
2054 invalid DER or failed signature check. | 1873 invalid DER or failed signature check. |
2055 | 1874 |
2056 Validated CRLs are differentiated by thisUpdate . | 1875 Validated CRLs are differentiated by thisUpdate . |
2057 Validated CRLs are preferred over non-validated CRLs . | 1876 Validated CRLs are preferred over non-validated CRLs . |
2058 Proper DER CRLs are preferred over non-DER data . | 1877 Proper DER CRLs are preferred over non-DER data . |
2059 */ | 1878 */ |
2060 static int SortImperfectCRLs(const void* arg1, const void* arg2) | 1879 static int |
| 1880 SortImperfectCRLs(const void* arg1, const void* arg2) |
2061 { | 1881 { |
2062 CachedCrl* a, *b; | 1882 CachedCrl *a, *b; |
2063 | 1883 |
2064 a = *(CachedCrl**) arg1; | 1884 a = *(CachedCrl**)arg1; |
2065 b = *(CachedCrl**) arg2; | 1885 b = *(CachedCrl**)arg2; |
2066 | 1886 |
2067 if (!a || !b) | 1887 if (!a || !b) { |
2068 { | |
2069 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1888 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2070 PORT_Assert(0); | 1889 PORT_Assert(0); |
2071 } | 1890 } else { |
2072 else | |
2073 { | |
2074 PRBool aDecoded = PR_FALSE, bDecoded = PR_FALSE; | 1891 PRBool aDecoded = PR_FALSE, bDecoded = PR_FALSE; |
2075 if ( (PR_TRUE == a->sigValid) && (PR_TRUE == b->sigValid) ) | 1892 if ((PR_TRUE == a->sigValid) && (PR_TRUE == b->sigValid)) { |
2076 { | |
2077 /* both CRLs have been validated, choose the latest one */ | 1893 /* both CRLs have been validated, choose the latest one */ |
2078 return SortCRLsByThisUpdate(arg1, arg2); | 1894 return SortCRLsByThisUpdate(arg1, arg2); |
2079 } | 1895 } |
2080 if (PR_TRUE == a->sigValid) | 1896 if (PR_TRUE == a->sigValid) { |
2081 { | |
2082 return 1; /* a is greater than b */ | 1897 return 1; /* a is greater than b */ |
2083 } | 1898 } |
2084 if (PR_TRUE == b->sigValid) | 1899 if (PR_TRUE == b->sigValid) { |
2085 { | |
2086 return -1; /* a is not as good as b */ | 1900 return -1; /* a is not as good as b */ |
2087 } | 1901 } |
2088 aDecoded = GetOpaqueCRLFields(a->crl)->decodingError; | 1902 aDecoded = GetOpaqueCRLFields(a->crl)->decodingError; |
2089 bDecoded = GetOpaqueCRLFields(b->crl)->decodingError; | 1903 bDecoded = GetOpaqueCRLFields(b->crl)->decodingError; |
2090 /* neither CRL had its signature check pass */ | 1904 /* neither CRL had its signature check pass */ |
2091 if ( (PR_FALSE == aDecoded) && (PR_FALSE == bDecoded) ) | 1905 if ((PR_FALSE == aDecoded) && (PR_FALSE == bDecoded)) { |
2092 { | |
2093 /* both CRLs are proper DER, choose the latest one */ | 1906 /* both CRLs are proper DER, choose the latest one */ |
2094 return SortCRLsByThisUpdate(arg1, arg2); | 1907 return SortCRLsByThisUpdate(arg1, arg2); |
2095 } | 1908 } |
2096 if (PR_FALSE == aDecoded) | 1909 if (PR_FALSE == aDecoded) { |
2097 { | |
2098 return 1; /* a is better than b */ | 1910 return 1; /* a is better than b */ |
2099 } | 1911 } |
2100 if (PR_FALSE == bDecoded) | 1912 if (PR_FALSE == bDecoded) { |
2101 { | |
2102 return -1; /* a is not as good as b */ | 1913 return -1; /* a is not as good as b */ |
2103 } | 1914 } |
2104 /* both are invalid DER. sigh. */ | 1915 /* both are invalid DER. sigh. */ |
2105 } | 1916 } |
2106 /* if they are equal, or if all else fails, use pointer differences */ | 1917 /* if they are equal, or if all else fails, use pointer differences */ |
2107 PORT_Assert(a != b); /* they should never be equal */ | 1918 PORT_Assert(a != b); /* they should never be equal */ |
2108 return a>b?1:-1; | 1919 return a > b ? 1 : -1; |
2109 } | 1920 } |
2110 | 1921 |
2111 | |
2112 /* Pick best CRL to use . needs write access */ | 1922 /* Pick best CRL to use . needs write access */ |
2113 static SECStatus DPCache_SelectCRL(CRLDPCache* cache) | 1923 static SECStatus |
| 1924 DPCache_SelectCRL(CRLDPCache* cache) |
2114 { | 1925 { |
2115 PRUint32 i; | 1926 PRUint32 i; |
2116 PRBool valid = PR_TRUE; | 1927 PRBool valid = PR_TRUE; |
2117 CachedCrl* selected = NULL; | 1928 CachedCrl* selected = NULL; |
2118 | 1929 |
2119 PORT_Assert(cache); | 1930 PORT_Assert(cache); |
2120 if (!cache) | 1931 if (!cache) { |
2121 { | |
2122 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1932 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2123 return SECFailure; | 1933 return SECFailure; |
2124 } | 1934 } |
2125 /* if any invalid CRL is present, then the CRL cache is | 1935 /* if any invalid CRL is present, then the CRL cache is |
2126 considered invalid, for security reasons */ | 1936 considered invalid, for security reasons */ |
2127 for (i = 0 ; i<cache->ncrls; i++) | 1937 for (i = 0; i < cache->ncrls; i++) { |
2128 { | |
2129 if (!cache->crls[i] || !cache->crls[i]->sigChecked || | 1938 if (!cache->crls[i] || !cache->crls[i]->sigChecked || |
2130 !cache->crls[i]->sigValid) | 1939 !cache->crls[i]->sigValid) { |
2131 { | |
2132 valid = PR_FALSE; | 1940 valid = PR_FALSE; |
2133 break; | 1941 break; |
2134 } | 1942 } |
2135 } | 1943 } |
2136 if (PR_TRUE == valid) | 1944 if (PR_TRUE == valid) { |
2137 { | |
2138 /* all CRLs are valid, clear this error */ | 1945 /* all CRLs are valid, clear this error */ |
2139 cache->invalid &= (~CRL_CACHE_INVALID_CRLS); | 1946 cache->invalid &= (~CRL_CACHE_INVALID_CRLS); |
2140 } else | 1947 } else { |
2141 { | |
2142 /* some CRLs are invalid, set this error */ | 1948 /* some CRLs are invalid, set this error */ |
2143 cache->invalid |= CRL_CACHE_INVALID_CRLS; | 1949 cache->invalid |= CRL_CACHE_INVALID_CRLS; |
2144 } | 1950 } |
2145 | 1951 |
2146 if (cache->invalid) | 1952 if (cache->invalid) { |
2147 { | |
2148 /* cache is in an invalid state, so reset it */ | 1953 /* cache is in an invalid state, so reset it */ |
2149 if (cache->selected) | 1954 if (cache->selected) { |
2150 { | |
2151 cache->selected = NULL; | 1955 cache->selected = NULL; |
2152 } | 1956 } |
2153 /* also sort the CRLs imperfectly */ | 1957 /* also sort the CRLs imperfectly */ |
2154 qsort(cache->crls, cache->ncrls, sizeof(CachedCrl*), | 1958 qsort(cache->crls, cache->ncrls, sizeof(CachedCrl*), SortImperfectCRLs); |
2155 SortImperfectCRLs); | |
2156 return SECSuccess; | 1959 return SECSuccess; |
2157 } | 1960 } |
2158 /* all CRLs are good, sort them by thisUpdate */ | 1961 /* all CRLs are good, sort them by thisUpdate */ |
2159 qsort(cache->crls, cache->ncrls, sizeof(CachedCrl*), | 1962 qsort(cache->crls, cache->ncrls, sizeof(CachedCrl*), SortCRLsByThisUpdate); |
2160 SortCRLsByThisUpdate); | |
2161 | 1963 |
2162 if (cache->ncrls) | 1964 if (cache->ncrls) { |
2163 { | |
2164 /* pick the newest CRL */ | 1965 /* pick the newest CRL */ |
2165 selected = cache->crls[cache->ncrls-1]; | 1966 selected = cache->crls[cache->ncrls - 1]; |
2166 | 1967 |
2167 /* and populate the cache */ | 1968 /* and populate the cache */ |
2168 if (SECSuccess != CachedCrl_Populate(selected)) | 1969 if (SECSuccess != CachedCrl_Populate(selected)) { |
2169 { | |
2170 return SECFailure; | 1970 return SECFailure; |
2171 } | 1971 } |
2172 } | 1972 } |
2173 | 1973 |
2174 cache->selected = selected; | 1974 cache->selected = selected; |
2175 | 1975 |
2176 return SECSuccess; | 1976 return SECSuccess; |
2177 } | 1977 } |
2178 | 1978 |
2179 /* initialize a DPCache object */ | 1979 /* initialize a DPCache object */ |
2180 static SECStatus DPCache_Create(CRLDPCache** returned, CERTCertificate* issuer, | 1980 static SECStatus |
2181 const SECItem* subject, SECItem* dp) | 1981 DPCache_Create(CRLDPCache** returned, CERTCertificate* issuer, |
| 1982 const SECItem* subject, SECItem* dp) |
2182 { | 1983 { |
2183 CRLDPCache* cache = NULL; | 1984 CRLDPCache* cache = NULL; |
2184 PORT_Assert(returned); | 1985 PORT_Assert(returned); |
2185 /* issuer and dp are allowed to be NULL */ | 1986 /* issuer and dp are allowed to be NULL */ |
2186 if (!returned || !subject) | 1987 if (!returned || !subject) { |
2187 { | |
2188 PORT_Assert(0); | 1988 PORT_Assert(0); |
2189 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 1989 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2190 return SECFailure; | 1990 return SECFailure; |
2191 } | 1991 } |
2192 *returned = NULL; | 1992 *returned = NULL; |
2193 cache = PORT_ZAlloc(sizeof(CRLDPCache)); | 1993 cache = PORT_ZAlloc(sizeof(CRLDPCache)); |
2194 if (!cache) | 1994 if (!cache) { |
2195 { | |
2196 return SECFailure; | 1995 return SECFailure; |
2197 } | 1996 } |
2198 #ifdef DPC_RWLOCK | 1997 #ifdef DPC_RWLOCK |
2199 cache->lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); | 1998 cache->lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); |
2200 #else | 1999 #else |
2201 cache->lock = PR_NewLock(); | 2000 cache->lock = PR_NewLock(); |
2202 #endif | 2001 #endif |
2203 if (!cache->lock) | 2002 if (!cache->lock) { |
2204 { | 2003 PORT_Free(cache); |
2205 » PORT_Free(cache); | |
2206 return SECFailure; | 2004 return SECFailure; |
2207 } | 2005 } |
2208 if (issuer) | 2006 if (issuer) { |
2209 { | 2007 cache->dbHandle = issuer->dbhandle; |
2210 » cache->dbHandle = issuer->dbhandle; | 2008 cache->issuerDERCert = SECITEM_DupItem(&issuer->derCert); |
2211 » cache->issuerDERCert = SECITEM_DupItem(&issuer->derCert); | |
2212 } | 2009 } |
2213 cache->distributionPoint = SECITEM_DupItem(dp); | 2010 cache->distributionPoint = SECITEM_DupItem(dp); |
2214 cache->subject = SECITEM_DupItem(subject); | 2011 cache->subject = SECITEM_DupItem(subject); |
2215 cache->lastfetch = 0; | 2012 cache->lastfetch = 0; |
2216 cache->lastcheck = 0; | 2013 cache->lastcheck = 0; |
2217 *returned = cache; | 2014 *returned = cache; |
2218 return SECSuccess; | 2015 return SECSuccess; |
2219 } | 2016 } |
2220 | 2017 |
2221 /* create an issuer cache object (per CA subject ) */ | 2018 /* create an issuer cache object (per CA subject ) */ |
2222 static SECStatus IssuerCache_Create(CRLIssuerCache** returned, | 2019 static SECStatus |
2223 CERTCertificate* issuer, | 2020 IssuerCache_Create(CRLIssuerCache** returned, CERTCertificate* issuer, |
2224 const SECItem* subject, const SECItem* dp) | 2021 const SECItem* subject, const SECItem* dp) |
2225 { | 2022 { |
2226 SECStatus rv = SECSuccess; | 2023 SECStatus rv = SECSuccess; |
2227 CRLIssuerCache* cache = NULL; | 2024 CRLIssuerCache* cache = NULL; |
2228 PORT_Assert(returned); | 2025 PORT_Assert(returned); |
2229 PORT_Assert(subject); | 2026 PORT_Assert(subject); |
2230 /* issuer and dp are allowed to be NULL */ | 2027 /* issuer and dp are allowed to be NULL */ |
2231 if (!returned || !subject) | 2028 if (!returned || !subject) { |
2232 { | |
2233 PORT_Assert(0); | 2029 PORT_Assert(0); |
2234 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2030 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2235 return SECFailure; | 2031 return SECFailure; |
2236 } | 2032 } |
2237 *returned = NULL; | 2033 *returned = NULL; |
2238 cache = (CRLIssuerCache*) PORT_ZAlloc(sizeof(CRLIssuerCache)); | 2034 cache = (CRLIssuerCache*)PORT_ZAlloc(sizeof(CRLIssuerCache)); |
2239 if (!cache) | 2035 if (!cache) { |
2240 { | |
2241 return SECFailure; | 2036 return SECFailure; |
2242 } | 2037 } |
2243 cache->subject = SECITEM_DupItem(subject); | 2038 cache->subject = SECITEM_DupItem(subject); |
2244 #ifdef XCRL | 2039 #ifdef XCRL |
2245 cache->lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); | 2040 cache->lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); |
2246 if (!cache->lock) | 2041 if (!cache->lock) { |
2247 { | |
2248 rv = SECFailure; | 2042 rv = SECFailure; |
2249 } | 2043 } |
2250 if (SECSuccess == rv && issuer) | 2044 if (SECSuccess == rv && issuer) { |
2251 { | |
2252 cache->issuer = CERT_DupCertificate(issuer); | 2045 cache->issuer = CERT_DupCertificate(issuer); |
2253 if (!cache->issuer) | 2046 if (!cache->issuer) { |
2254 { | |
2255 rv = SECFailure; | 2047 rv = SECFailure; |
2256 } | 2048 } |
2257 } | 2049 } |
2258 #endif | 2050 #endif |
2259 if (SECSuccess != rv) | 2051 if (SECSuccess != rv) { |
2260 { | |
2261 PORT_Assert(SECSuccess == IssuerCache_Destroy(cache)); | 2052 PORT_Assert(SECSuccess == IssuerCache_Destroy(cache)); |
2262 return SECFailure; | 2053 return SECFailure; |
2263 } | 2054 } |
2264 *returned = cache; | 2055 *returned = cache; |
2265 return SECSuccess; | 2056 return SECSuccess; |
2266 } | 2057 } |
2267 | 2058 |
2268 /* add a DPCache to the issuer cache */ | 2059 /* add a DPCache to the issuer cache */ |
2269 static SECStatus IssuerCache_AddDP(CRLIssuerCache* cache, | 2060 static SECStatus |
2270 CERTCertificate* issuer, | 2061 IssuerCache_AddDP(CRLIssuerCache* cache, CERTCertificate* issuer, |
2271 const SECItem* subject, | 2062 const SECItem* subject, const SECItem* dp, |
2272 const SECItem* dp, | 2063 CRLDPCache** newdpc) |
2273 CRLDPCache** newdpc) | |
2274 { | 2064 { |
2275 /* now create the required DP cache object */ | 2065 /* now create the required DP cache object */ |
2276 if (!cache || !subject || !newdpc) | 2066 if (!cache || !subject || !newdpc) { |
2277 { | |
2278 PORT_Assert(0); | 2067 PORT_Assert(0); |
2279 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2068 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2280 return SECFailure; | 2069 return SECFailure; |
2281 } | 2070 } |
2282 if (!dp) | 2071 if (!dp) { |
2283 { | |
2284 /* default distribution point */ | 2072 /* default distribution point */ |
2285 SECStatus rv = DPCache_Create(&cache->dpp, issuer, subject, NULL); | 2073 SECStatus rv = DPCache_Create(&cache->dpp, issuer, subject, NULL); |
2286 if (SECSuccess == rv) | 2074 if (SECSuccess == rv) { |
2287 { | |
2288 *newdpc = cache->dpp; | 2075 *newdpc = cache->dpp; |
2289 return SECSuccess; | 2076 return SECSuccess; |
2290 } | 2077 } |
2291 } | 2078 } else { |
2292 else | |
2293 { | |
2294 /* we should never hit this until we support multiple DPs */ | 2079 /* we should never hit this until we support multiple DPs */ |
2295 PORT_Assert(dp); | 2080 PORT_Assert(dp); |
2296 /* XCRL allocate a new distribution point cache object, initialize it, | 2081 /* XCRL allocate a new distribution point cache object, initialize it, |
2297 and add it to the hash table of DPs */ | 2082 and add it to the hash table of DPs */ |
2298 } | 2083 } |
2299 return SECFailure; | 2084 return SECFailure; |
2300 } | 2085 } |
2301 | 2086 |
2302 /* add an IssuerCache to the global hash table of issuers */ | 2087 /* add an IssuerCache to the global hash table of issuers */ |
2303 static SECStatus CRLCache_AddIssuer(CRLIssuerCache* issuer) | 2088 static SECStatus |
2304 { | 2089 CRLCache_AddIssuer(CRLIssuerCache* issuer) |
| 2090 { |
2305 PORT_Assert(issuer); | 2091 PORT_Assert(issuer); |
2306 PORT_Assert(crlcache.issuers); | 2092 PORT_Assert(crlcache.issuers); |
2307 if (!issuer || !crlcache.issuers) | 2093 if (!issuer || !crlcache.issuers) { |
2308 { | |
2309 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2094 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2310 return SECFailure; | 2095 return SECFailure; |
2311 } | 2096 } |
2312 if (NULL == PL_HashTableAdd(crlcache.issuers, (void*) issuer->subject, | 2097 if (NULL == PL_HashTableAdd(crlcache.issuers, (void*)issuer->subject, |
2313 (void*) issuer)) | 2098 (void*)issuer)) { |
2314 { | |
2315 return SECFailure; | 2099 return SECFailure; |
2316 } | 2100 } |
2317 return SECSuccess; | 2101 return SECSuccess; |
2318 } | 2102 } |
2319 | 2103 |
2320 /* retrieve the issuer cache object for a given issuer subject */ | 2104 /* retrieve the issuer cache object for a given issuer subject */ |
2321 static SECStatus CRLCache_GetIssuerCache(CRLCache* cache, | 2105 static SECStatus |
2322 const SECItem* subject, | 2106 CRLCache_GetIssuerCache(CRLCache* cache, const SECItem* subject, |
2323 CRLIssuerCache** returned) | 2107 CRLIssuerCache** returned) |
2324 { | 2108 { |
2325 /* we need to look up the issuer in the hash table */ | 2109 /* we need to look up the issuer in the hash table */ |
2326 SECStatus rv = SECSuccess; | 2110 SECStatus rv = SECSuccess; |
2327 PORT_Assert(cache); | 2111 PORT_Assert(cache); |
2328 PORT_Assert(subject); | 2112 PORT_Assert(subject); |
2329 PORT_Assert(returned); | 2113 PORT_Assert(returned); |
2330 PORT_Assert(crlcache.issuers); | 2114 PORT_Assert(crlcache.issuers); |
2331 if (!cache || !subject || !returned || !crlcache.issuers) | 2115 if (!cache || !subject || !returned || !crlcache.issuers) { |
2332 { | |
2333 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2116 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2334 rv = SECFailure; | 2117 rv = SECFailure; |
2335 } | 2118 } |
2336 | 2119 |
2337 if (SECSuccess == rv) | 2120 if (SECSuccess == rv) { |
2338 { | 2121 *returned = (CRLIssuerCache*)PL_HashTableLookup(crlcache.issuers, |
2339 *returned = (CRLIssuerCache*) PL_HashTableLookup(crlcache.issuers, | 2122 (void*)subject); |
2340 (void*) subject); | |
2341 } | 2123 } |
2342 | 2124 |
2343 return rv; | 2125 return rv; |
2344 } | 2126 } |
2345 | 2127 |
2346 /* retrieve the full CRL object that best matches the content of a DPCache */ | 2128 /* retrieve the full CRL object that best matches the content of a DPCache */ |
2347 static CERTSignedCrl* GetBestCRL(CRLDPCache* cache, PRBool entries) | 2129 static CERTSignedCrl* |
| 2130 GetBestCRL(CRLDPCache* cache, PRBool entries) |
2348 { | 2131 { |
2349 CachedCrl* acrl = NULL; | 2132 CachedCrl* acrl = NULL; |
2350 | 2133 |
2351 PORT_Assert(cache); | 2134 PORT_Assert(cache); |
2352 if (!cache) | 2135 if (!cache) { |
2353 { | |
2354 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2136 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2355 return NULL; | 2137 return NULL; |
2356 } | 2138 } |
2357 | 2139 |
2358 if (0 == cache->ncrls) | 2140 if (0 == cache->ncrls) { |
2359 { | |
2360 /* empty cache*/ | 2141 /* empty cache*/ |
2361 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); | 2142 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); |
2362 return NULL; | 2143 return NULL; |
2363 } | 2144 } |
2364 | 2145 |
2365 /* if we have a valid full CRL selected, return it */ | 2146 /* if we have a valid full CRL selected, return it */ |
2366 if (cache->selected) | 2147 if (cache->selected) { |
2367 { | |
2368 return SEC_DupCrl(cache->selected->crl); | 2148 return SEC_DupCrl(cache->selected->crl); |
2369 } | 2149 } |
2370 | 2150 |
2371 /* otherwise, use latest valid DER CRL */ | 2151 /* otherwise, use latest valid DER CRL */ |
2372 acrl = cache->crls[cache->ncrls-1]; | 2152 acrl = cache->crls[cache->ncrls - 1]; |
2373 | 2153 |
2374 if (acrl && (PR_FALSE == GetOpaqueCRLFields(acrl->crl)->decodingError) ) | 2154 if (acrl && (PR_FALSE == GetOpaqueCRLFields(acrl->crl)->decodingError)) { |
2375 { | |
2376 SECStatus rv = SECSuccess; | 2155 SECStatus rv = SECSuccess; |
2377 if (PR_TRUE == entries) | 2156 if (PR_TRUE == entries) { |
2378 { | |
2379 rv = CERT_CompleteCRLDecodeEntries(acrl->crl); | 2157 rv = CERT_CompleteCRLDecodeEntries(acrl->crl); |
2380 } | 2158 } |
2381 if (SECSuccess == rv) | 2159 if (SECSuccess == rv) { |
2382 { | |
2383 return SEC_DupCrl(acrl->crl); | 2160 return SEC_DupCrl(acrl->crl); |
2384 } | 2161 } |
2385 } | 2162 } |
2386 | 2163 |
2387 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); | 2164 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); |
2388 return NULL; | 2165 return NULL; |
2389 } | 2166 } |
2390 | 2167 |
2391 /* get a particular DPCache object from an IssuerCache */ | 2168 /* get a particular DPCache object from an IssuerCache */ |
2392 static CRLDPCache* IssuerCache_GetDPCache(CRLIssuerCache* cache, const SECItem*
dp) | 2169 static CRLDPCache* |
| 2170 IssuerCache_GetDPCache(CRLIssuerCache* cache, const SECItem* dp) |
2393 { | 2171 { |
2394 CRLDPCache* dpp = NULL; | 2172 CRLDPCache* dpp = NULL; |
2395 PORT_Assert(cache); | 2173 PORT_Assert(cache); |
2396 /* XCRL for now we only support the "default" DP, ie. the | 2174 /* XCRL for now we only support the "default" DP, ie. the |
2397 full CRL. So we can return the global one without locking. In | 2175 full CRL. So we can return the global one without locking. In |
2398 the future we will have a lock */ | 2176 the future we will have a lock */ |
2399 PORT_Assert(NULL == dp); | 2177 PORT_Assert(NULL == dp); |
2400 if (!cache || dp) | 2178 if (!cache || dp) { |
2401 { | |
2402 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2179 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2403 return NULL; | 2180 return NULL; |
2404 } | 2181 } |
2405 #ifdef XCRL | 2182 #ifdef XCRL |
2406 NSSRWLock_LockRead(cache->lock); | 2183 NSSRWLock_LockRead(cache->lock); |
2407 #endif | 2184 #endif |
2408 dpp = cache->dpp; | 2185 dpp = cache->dpp; |
2409 #ifdef XCRL | 2186 #ifdef XCRL |
2410 NSSRWLock_UnlockRead(cache->lock); | 2187 NSSRWLock_UnlockRead(cache->lock); |
2411 #endif | 2188 #endif |
2412 return dpp; | 2189 return dpp; |
2413 } | 2190 } |
2414 | 2191 |
2415 /* get a DPCache object for the given issuer subject and dp | 2192 /* get a DPCache object for the given issuer subject and dp |
2416 Automatically creates the cache object if it doesn't exist yet. | 2193 Automatically creates the cache object if it doesn't exist yet. |
2417 */ | 2194 */ |
2418 SECStatus AcquireDPCache(CERTCertificate* issuer, const SECItem* subject, | 2195 SECStatus |
2419 const SECItem* dp, PRTime t, void* wincx, | 2196 AcquireDPCache(CERTCertificate* issuer, const SECItem* subject, |
2420 CRLDPCache** dpcache, PRBool* writeLocked) | 2197 const SECItem* dp, PRTime t, void* wincx, CRLDPCache** dpcache, |
| 2198 PRBool* writeLocked) |
2421 { | 2199 { |
2422 SECStatus rv = SECSuccess; | 2200 SECStatus rv = SECSuccess; |
2423 CRLIssuerCache* issuercache = NULL; | 2201 CRLIssuerCache* issuercache = NULL; |
2424 #ifdef GLOBAL_RWLOCK | 2202 #ifdef GLOBAL_RWLOCK |
2425 PRBool globalwrite = PR_FALSE; | 2203 PRBool globalwrite = PR_FALSE; |
2426 #endif | 2204 #endif |
2427 PORT_Assert(crlcache.lock); | 2205 PORT_Assert(crlcache.lock); |
2428 if (!crlcache.lock) | 2206 if (!crlcache.lock) { |
2429 { | |
2430 /* CRL cache is not initialized */ | 2207 /* CRL cache is not initialized */ |
2431 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2208 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2432 return SECFailure; | 2209 return SECFailure; |
2433 } | 2210 } |
2434 #ifdef GLOBAL_RWLOCK | 2211 #ifdef GLOBAL_RWLOCK |
2435 NSSRWLock_LockRead(crlcache.lock); | 2212 NSSRWLock_LockRead(crlcache.lock); |
2436 #else | 2213 #else |
2437 PR_Lock(crlcache.lock); | 2214 PR_Lock(crlcache.lock); |
2438 #endif | 2215 #endif |
2439 rv = CRLCache_GetIssuerCache(&crlcache, subject, &issuercache); | 2216 rv = CRLCache_GetIssuerCache(&crlcache, subject, &issuercache); |
2440 if (SECSuccess != rv) | 2217 if (SECSuccess != rv) { |
2441 { | |
2442 #ifdef GLOBAL_RWLOCK | 2218 #ifdef GLOBAL_RWLOCK |
2443 NSSRWLock_UnlockRead(crlcache.lock); | 2219 NSSRWLock_UnlockRead(crlcache.lock); |
2444 #else | 2220 #else |
2445 PR_Unlock(crlcache.lock); | 2221 PR_Unlock(crlcache.lock); |
2446 #endif | 2222 #endif |
2447 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2223 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2448 return SECFailure; | 2224 return SECFailure; |
2449 } | 2225 } |
2450 if (!issuercache) | 2226 if (!issuercache) { |
2451 { | |
2452 /* there is no cache for this issuer yet. This means this is the | 2227 /* there is no cache for this issuer yet. This means this is the |
2453 first time we look up a cert from that issuer, and we need to | 2228 first time we look up a cert from that issuer, and we need to |
2454 create the cache. */ | 2229 create the cache. */ |
2455 | 2230 |
2456 rv = IssuerCache_Create(&issuercache, issuer, subject, dp); | 2231 rv = IssuerCache_Create(&issuercache, issuer, subject, dp); |
2457 if (SECSuccess == rv && !issuercache) | 2232 if (SECSuccess == rv && !issuercache) { |
2458 { | |
2459 PORT_Assert(issuercache); | 2233 PORT_Assert(issuercache); |
2460 rv = SECFailure; | 2234 rv = SECFailure; |
2461 } | 2235 } |
2462 | 2236 |
2463 if (SECSuccess == rv) | 2237 if (SECSuccess == rv) { |
2464 { | |
2465 /* This is the first time we look up a cert of this issuer. | 2238 /* This is the first time we look up a cert of this issuer. |
2466 Create the DPCache for this DP . */ | 2239 Create the DPCache for this DP . */ |
2467 rv = IssuerCache_AddDP(issuercache, issuer, subject, dp, dpcache); | 2240 rv = IssuerCache_AddDP(issuercache, issuer, subject, dp, dpcache); |
2468 } | 2241 } |
2469 | 2242 |
2470 if (SECSuccess == rv) | 2243 if (SECSuccess == rv) { |
2471 { | |
2472 /* lock the DPCache for write to ensure the update happens in this | 2244 /* lock the DPCache for write to ensure the update happens in this |
2473 thread */ | 2245 thread */ |
2474 *writeLocked = PR_TRUE; | 2246 *writeLocked = PR_TRUE; |
2475 #ifdef DPC_RWLOCK | 2247 #ifdef DPC_RWLOCK |
2476 NSSRWLock_LockWrite((*dpcache)->lock); | 2248 NSSRWLock_LockWrite((*dpcache)->lock); |
2477 #else | 2249 #else |
2478 PR_Lock((*dpcache)->lock); | 2250 PR_Lock((*dpcache)->lock); |
2479 #endif | 2251 #endif |
2480 } | 2252 } |
2481 | 2253 |
2482 if (SECSuccess == rv) | 2254 if (SECSuccess == rv) { |
2483 { | 2255 /* now add the new issuer cache to the global hash table of |
2484 /* now add the new issuer cache to the global hash table of | 2256 issuers */ |
2485 issuers */ | |
2486 #ifdef GLOBAL_RWLOCK | 2257 #ifdef GLOBAL_RWLOCK |
2487 CRLIssuerCache* existing = NULL; | 2258 CRLIssuerCache* existing = NULL; |
2488 NSSRWLock_UnlockRead(crlcache.lock); | 2259 NSSRWLock_UnlockRead(crlcache.lock); |
2489 /* when using a r/w lock for the global cache, check if the issuer | 2260 /* when using a r/w lock for the global cache, check if the issuer |
2490 already exists before adding to the hash table */ | 2261 already exists before adding to the hash table */ |
2491 NSSRWLock_LockWrite(crlcache.lock); | 2262 NSSRWLock_LockWrite(crlcache.lock); |
2492 globalwrite = PR_TRUE; | 2263 globalwrite = PR_TRUE; |
2493 rv = CRLCache_GetIssuerCache(&crlcache, subject, &existing); | 2264 rv = CRLCache_GetIssuerCache(&crlcache, subject, &existing); |
2494 if (!existing) | 2265 if (!existing) { |
2495 { | |
2496 #endif | 2266 #endif |
2497 rv = CRLCache_AddIssuer(issuercache); | 2267 rv = CRLCache_AddIssuer(issuercache); |
2498 if (SECSuccess != rv) | 2268 if (SECSuccess != rv) { |
2499 { | |
2500 /* failure */ | 2269 /* failure */ |
2501 rv = SECFailure; | 2270 rv = SECFailure; |
2502 } | 2271 } |
2503 #ifdef GLOBAL_RWLOCK | 2272 #ifdef GLOBAL_RWLOCK |
2504 } | 2273 } else { |
2505 else | |
2506 { | |
2507 /* somebody else updated before we did */ | 2274 /* somebody else updated before we did */ |
2508 IssuerCache_Destroy(issuercache); /* destroy the new object */ | 2275 IssuerCache_Destroy(issuercache); /* destroy the new object */ |
2509 issuercache = existing; /* use the existing one */ | 2276 issuercache = existing; /* use the existing one */ |
2510 *dpcache = IssuerCache_GetDPCache(issuercache, dp); | 2277 *dpcache = IssuerCache_GetDPCache(issuercache, dp); |
2511 } | 2278 } |
2512 #endif | 2279 #endif |
2513 } | 2280 } |
2514 | 2281 |
2515 /* now unlock the global cache. We only want to lock the issuer hash | 2282 /* now unlock the global cache. We only want to lock the issuer hash |
2516 table addition. Holding it longer would hurt scalability */ | 2283 table addition. Holding it longer would hurt scalability */ |
2517 #ifdef GLOBAL_RWLOCK | 2284 #ifdef GLOBAL_RWLOCK |
2518 if (PR_TRUE == globalwrite) | 2285 if (PR_TRUE == globalwrite) { |
2519 { | |
2520 NSSRWLock_UnlockWrite(crlcache.lock); | 2286 NSSRWLock_UnlockWrite(crlcache.lock); |
2521 globalwrite = PR_FALSE; | 2287 globalwrite = PR_FALSE; |
2522 } | 2288 } else { |
2523 else | |
2524 { | |
2525 NSSRWLock_UnlockRead(crlcache.lock); | 2289 NSSRWLock_UnlockRead(crlcache.lock); |
2526 } | 2290 } |
2527 #else | 2291 #else |
2528 PR_Unlock(crlcache.lock); | 2292 PR_Unlock(crlcache.lock); |
2529 #endif | 2293 #endif |
2530 | 2294 |
2531 /* if there was a failure adding an issuer cache object, destroy it */ | 2295 /* if there was a failure adding an issuer cache object, destroy it */ |
2532 if (SECSuccess != rv && issuercache) | 2296 if (SECSuccess != rv && issuercache) { |
2533 { | 2297 if (PR_TRUE == *writeLocked) { |
2534 if (PR_TRUE == *writeLocked) | |
2535 { | |
2536 #ifdef DPC_RWLOCK | 2298 #ifdef DPC_RWLOCK |
2537 NSSRWLock_UnlockWrite((*dpcache)->lock); | 2299 NSSRWLock_UnlockWrite((*dpcache)->lock); |
2538 #else | 2300 #else |
2539 PR_Unlock((*dpcache)->lock); | 2301 PR_Unlock((*dpcache)->lock); |
2540 #endif | 2302 #endif |
2541 } | 2303 } |
2542 IssuerCache_Destroy(issuercache); | 2304 IssuerCache_Destroy(issuercache); |
2543 issuercache = NULL; | 2305 issuercache = NULL; |
2544 } | 2306 } |
2545 | 2307 |
2546 if (SECSuccess != rv) | 2308 if (SECSuccess != rv) { |
2547 { | |
2548 return SECFailure; | 2309 return SECFailure; |
2549 } | 2310 } |
2550 } else | 2311 } else { |
2551 { | |
2552 #ifdef GLOBAL_RWLOCK | 2312 #ifdef GLOBAL_RWLOCK |
2553 NSSRWLock_UnlockRead(crlcache.lock); | 2313 NSSRWLock_UnlockRead(crlcache.lock); |
2554 #else | 2314 #else |
2555 PR_Unlock(crlcache.lock); | 2315 PR_Unlock(crlcache.lock); |
2556 #endif | 2316 #endif |
2557 *dpcache = IssuerCache_GetDPCache(issuercache, dp); | 2317 *dpcache = IssuerCache_GetDPCache(issuercache, dp); |
2558 } | 2318 } |
2559 /* we now have a DPCache that we can use for lookups */ | 2319 /* we now have a DPCache that we can use for lookups */ |
2560 /* lock it for read, unless we already locked for write */ | 2320 /* lock it for read, unless we already locked for write */ |
2561 if (PR_FALSE == *writeLocked) | 2321 if (PR_FALSE == *writeLocked) { |
2562 { | |
2563 #ifdef DPC_RWLOCK | 2322 #ifdef DPC_RWLOCK |
2564 NSSRWLock_LockRead((*dpcache)->lock); | 2323 NSSRWLock_LockRead((*dpcache)->lock); |
2565 #else | 2324 #else |
2566 PR_Lock((*dpcache)->lock); | 2325 PR_Lock((*dpcache)->lock); |
2567 #endif | 2326 #endif |
2568 } | 2327 } |
2569 | 2328 |
2570 if (SECSuccess == rv) | 2329 if (SECSuccess == rv) { |
2571 { | |
2572 /* currently there is always one and only one DPCache per issuer */ | 2330 /* currently there is always one and only one DPCache per issuer */ |
2573 PORT_Assert(*dpcache); | 2331 PORT_Assert(*dpcache); |
2574 if (*dpcache) | 2332 if (*dpcache) { |
2575 { | |
2576 /* make sure the DP cache is up to date before using it */ | 2333 /* make sure the DP cache is up to date before using it */ |
2577 rv = DPCache_GetUpToDate(*dpcache, issuer, PR_FALSE == *writeLocked, | 2334 rv = DPCache_GetUpToDate(*dpcache, issuer, PR_FALSE == *writeLocked, |
2578 t, wincx); | 2335 t, wincx); |
2579 } | 2336 } else { |
2580 else | |
2581 { | |
2582 rv = SECFailure; | 2337 rv = SECFailure; |
2583 } | 2338 } |
2584 } | 2339 } |
2585 return rv; | 2340 return rv; |
2586 } | 2341 } |
2587 | 2342 |
2588 /* unlock access to the DPCache */ | 2343 /* unlock access to the DPCache */ |
2589 void ReleaseDPCache(CRLDPCache* dpcache, PRBool writeLocked) | 2344 void |
| 2345 ReleaseDPCache(CRLDPCache* dpcache, PRBool writeLocked) |
2590 { | 2346 { |
2591 if (!dpcache) | 2347 if (!dpcache) { |
2592 { | |
2593 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2348 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2594 return; | 2349 return; |
2595 } | 2350 } |
2596 #ifdef DPC_RWLOCK | 2351 #ifdef DPC_RWLOCK |
2597 if (PR_TRUE == writeLocked) | 2352 if (PR_TRUE == writeLocked) { |
2598 { | |
2599 NSSRWLock_UnlockWrite(dpcache->lock); | 2353 NSSRWLock_UnlockWrite(dpcache->lock); |
2600 } | 2354 } else { |
2601 else | |
2602 { | |
2603 NSSRWLock_UnlockRead(dpcache->lock); | 2355 NSSRWLock_UnlockRead(dpcache->lock); |
2604 } | 2356 } |
2605 #else | 2357 #else |
2606 PR_Unlock(dpcache->lock); | 2358 PR_Unlock(dpcache->lock); |
2607 #endif | 2359 #endif |
2608 } | 2360 } |
2609 | 2361 |
2610 SECStatus | 2362 SECStatus |
2611 cert_CheckCertRevocationStatus(CERTCertificate* cert, CERTCertificate* issuer, | 2363 cert_CheckCertRevocationStatus(CERTCertificate* cert, CERTCertificate* issuer, |
2612 const SECItem* dp, PRTime t, void *wincx, | 2364 const SECItem* dp, PRTime t, void* wincx, |
2613 CERTRevocationStatus *revStatus, | 2365 CERTRevocationStatus* revStatus, |
2614 CERTCRLEntryReasonCode *revReason) | 2366 CERTCRLEntryReasonCode* revReason) |
2615 { | 2367 { |
2616 PRBool lockedwrite = PR_FALSE; | 2368 PRBool lockedwrite = PR_FALSE; |
2617 SECStatus rv = SECSuccess; | 2369 SECStatus rv = SECSuccess; |
2618 CRLDPCache* dpcache = NULL; | 2370 CRLDPCache* dpcache = NULL; |
2619 CERTRevocationStatus status = certRevocationStatusRevoked; | 2371 CERTRevocationStatus status = certRevocationStatusRevoked; |
2620 CERTCRLEntryReasonCode reason = crlEntryReasonUnspecified; | 2372 CERTCRLEntryReasonCode reason = crlEntryReasonUnspecified; |
2621 CERTCrlEntry* entry = NULL; | 2373 CERTCrlEntry* entry = NULL; |
2622 dpcacheStatus ds; | 2374 dpcacheStatus ds; |
2623 | 2375 |
2624 if (!cert || !issuer) | 2376 if (!cert || !issuer) { |
2625 { | |
2626 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2377 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2627 return SECFailure; | 2378 return SECFailure; |
2628 } | 2379 } |
2629 | 2380 |
2630 if (revStatus) | 2381 if (revStatus) { |
2631 { | |
2632 *revStatus = status; | 2382 *revStatus = status; |
2633 } | 2383 } |
2634 if (revReason) | 2384 if (revReason) { |
2635 { | |
2636 *revReason = reason; | 2385 *revReason = reason; |
2637 } | 2386 } |
2638 | 2387 |
2639 if (t && secCertTimeValid != CERT_CheckCertValidTimes(issuer, t, PR_FALSE)) | 2388 if (t && |
2640 { | 2389 secCertTimeValid != CERT_CheckCertValidTimes(issuer, t, PR_FALSE)) { |
2641 /* we won't be able to check the CRL's signature if the issuer cert | 2390 /* we won't be able to check the CRL's signature if the issuer cert |
2642 is expired as of the time we are verifying. This may cause a valid | 2391 is expired as of the time we are verifying. This may cause a valid |
2643 CRL to be cached as bad. short-circuit to avoid this case. */ | 2392 CRL to be cached as bad. short-circuit to avoid this case. */ |
2644 PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE); | 2393 PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE); |
2645 return SECFailure; | 2394 return SECFailure; |
2646 } | 2395 } |
2647 | 2396 |
2648 rv = AcquireDPCache(issuer, &issuer->derSubject, dp, t, wincx, &dpcache, | 2397 rv = AcquireDPCache(issuer, &issuer->derSubject, dp, t, wincx, &dpcache, |
2649 &lockedwrite); | 2398 &lockedwrite); |
2650 PORT_Assert(SECSuccess == rv); | 2399 PORT_Assert(SECSuccess == rv); |
2651 if (SECSuccess != rv) | 2400 if (SECSuccess != rv) { |
2652 { | |
2653 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2401 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2654 return SECFailure; | 2402 return SECFailure; |
2655 } | 2403 } |
2656 /* now look up the certificate SN in the DP cache's CRL */ | 2404 /* now look up the certificate SN in the DP cache's CRL */ |
2657 ds = DPCache_Lookup(dpcache, &cert->serialNumber, &entry); | 2405 ds = DPCache_Lookup(dpcache, &cert->serialNumber, &entry); |
2658 switch (ds) | 2406 switch (ds) { |
2659 { | |
2660 case dpcacheFoundEntry: | 2407 case dpcacheFoundEntry: |
2661 PORT_Assert(entry); | 2408 PORT_Assert(entry); |
2662 /* check the time if we have one */ | 2409 /* check the time if we have one */ |
2663 if (entry->revocationDate.data && entry->revocationDate.len) | 2410 if (entry->revocationDate.data && entry->revocationDate.len) { |
2664 { | |
2665 PRTime revocationDate = 0; | 2411 PRTime revocationDate = 0; |
2666 if (SECSuccess == DER_DecodeTimeChoice(&revocationDate, | 2412 if (SECSuccess == |
2667 &entry->revocationDate)) | 2413 DER_DecodeTimeChoice(&revocationDate, |
2668 { | 2414 &entry->revocationDate)) { |
2669 /* we got a good revocation date, only consider the | 2415 /* we got a good revocation date, only consider the |
2670 certificate revoked if the time we are inquiring about | 2416 certificate revoked if the time we are inquiring about |
2671 is past the revocation date */ | 2417 is past the revocation date */ |
2672 if (t>=revocationDate) | 2418 if (t >= revocationDate) { |
2673 { | |
2674 rv = SECFailure; | 2419 rv = SECFailure; |
2675 } | 2420 } else { |
2676 else | |
2677 { | |
2678 status = certRevocationStatusValid; | 2421 status = certRevocationStatusValid; |
2679 } | 2422 } |
2680 } | 2423 } else { |
2681 else | |
2682 { | |
2683 /* invalid revocation date, consider the certificate | 2424 /* invalid revocation date, consider the certificate |
2684 permanently revoked */ | 2425 permanently revoked */ |
2685 rv = SECFailure; | 2426 rv = SECFailure; |
2686 } | 2427 } |
2687 } | 2428 } else { |
2688 else | |
2689 { | |
2690 /* no revocation date, certificate is permanently revoked */ | 2429 /* no revocation date, certificate is permanently revoked */ |
2691 rv = SECFailure; | 2430 rv = SECFailure; |
2692 } | 2431 } |
2693 if (SECFailure == rv) | 2432 if (SECFailure == rv) { |
2694 { | |
2695 (void)CERT_FindCRLEntryReasonExten(entry, &reason); | 2433 (void)CERT_FindCRLEntryReasonExten(entry, &reason); |
2696 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); | 2434 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); |
2697 } | 2435 } |
2698 break; | 2436 break; |
2699 | 2437 |
2700 case dpcacheEmpty: | 2438 case dpcacheEmpty: |
2701 /* useful for NIST policy */ | 2439 /* useful for NIST policy */ |
2702 status = certRevocationStatusUnknown; | 2440 status = certRevocationStatusUnknown; |
2703 break; | 2441 break; |
2704 | 2442 |
2705 case dpcacheNoEntry: | 2443 case dpcacheNoEntry: |
2706 status = certRevocationStatusValid; | 2444 status = certRevocationStatusValid; |
2707 break; | 2445 break; |
2708 | 2446 |
2709 case dpcacheInvalidCacheError: | 2447 case dpcacheInvalidCacheError: |
2710 /* treat it as unknown and let the caller decide based on | 2448 /* treat it as unknown and let the caller decide based on |
2711 the policy */ | 2449 the policy */ |
2712 status = certRevocationStatusUnknown; | 2450 status = certRevocationStatusUnknown; |
2713 break; | 2451 break; |
2714 | 2452 |
2715 default: | 2453 default: |
2716 /* leave status as revoked */ | 2454 /* leave status as revoked */ |
2717 break; | 2455 break; |
2718 } | 2456 } |
2719 | 2457 |
2720 ReleaseDPCache(dpcache, lockedwrite); | 2458 ReleaseDPCache(dpcache, lockedwrite); |
2721 if (revStatus) | 2459 if (revStatus) { |
2722 { | |
2723 *revStatus = status; | 2460 *revStatus = status; |
2724 } | 2461 } |
2725 if (revReason) | 2462 if (revReason) { |
2726 { | |
2727 *revReason = reason; | 2463 *revReason = reason; |
2728 } | 2464 } |
2729 return rv; | 2465 return rv; |
2730 } | 2466 } |
2731 | 2467 |
2732 /* check CRL revocation status of given certificate and issuer */ | 2468 /* check CRL revocation status of given certificate and issuer */ |
2733 SECStatus | 2469 SECStatus |
2734 CERT_CheckCRL(CERTCertificate* cert, CERTCertificate* issuer, | 2470 CERT_CheckCRL(CERTCertificate* cert, CERTCertificate* issuer, const SECItem* dp, |
2735 const SECItem* dp, PRTime t, void* wincx) | 2471 PRTime t, void* wincx) |
2736 { | 2472 { |
2737 return cert_CheckCertRevocationStatus(cert, issuer, dp, t, wincx, | 2473 return cert_CheckCertRevocationStatus(cert, issuer, dp, t, wincx, NULL, |
2738 NULL, NULL); | 2474 NULL); |
2739 } | 2475 } |
2740 | 2476 |
2741 /* retrieve full CRL object that best matches the cache status */ | 2477 /* retrieve full CRL object that best matches the cache status */ |
2742 CERTSignedCrl * | 2478 CERTSignedCrl* |
2743 SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey, int type) | 2479 SEC_FindCrlByName(CERTCertDBHandle* handle, SECItem* crlKey, int type) |
2744 { | 2480 { |
2745 CERTSignedCrl* acrl = NULL; | 2481 CERTSignedCrl* acrl = NULL; |
2746 CRLDPCache* dpcache = NULL; | 2482 CRLDPCache* dpcache = NULL; |
2747 SECStatus rv = SECSuccess; | 2483 SECStatus rv = SECSuccess; |
2748 PRBool writeLocked = PR_FALSE; | 2484 PRBool writeLocked = PR_FALSE; |
2749 | 2485 |
2750 if (!crlKey) | 2486 if (!crlKey) { |
2751 { | |
2752 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 2487 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
2753 return NULL; | 2488 return NULL; |
2754 } | 2489 } |
2755 | 2490 |
2756 rv = AcquireDPCache(NULL, crlKey, NULL, 0, NULL, &dpcache, &writeLocked); | 2491 rv = AcquireDPCache(NULL, crlKey, NULL, 0, NULL, &dpcache, &writeLocked); |
2757 if (SECSuccess == rv) | 2492 if (SECSuccess == rv) { |
2758 { | |
2759 acrl = GetBestCRL(dpcache, PR_TRUE); /* decode entries, because | 2493 acrl = GetBestCRL(dpcache, PR_TRUE); /* decode entries, because |
2760 SEC_FindCrlByName always returned fully decoded CRLs in the past */ | 2494 SEC_FindCrlByName always returned fully decoded CRLs in the past */ |
2761 ReleaseDPCache(dpcache, writeLocked); | 2495 ReleaseDPCache(dpcache, writeLocked); |
2762 } | 2496 } |
2763 return acrl; | 2497 return acrl; |
2764 } | 2498 } |
2765 | 2499 |
2766 /* invalidate the CRL cache for a given issuer, which forces a refetch of | 2500 /* invalidate the CRL cache for a given issuer, which forces a refetch of |
2767 CRL objects from PKCS#11 tokens */ | 2501 CRL objects from PKCS#11 tokens */ |
2768 void CERT_CRLCacheRefreshIssuer(CERTCertDBHandle* dbhandle, SECItem* crlKey) | 2502 void |
| 2503 CERT_CRLCacheRefreshIssuer(CERTCertDBHandle* dbhandle, SECItem* crlKey) |
2769 { | 2504 { |
2770 CRLDPCache* cache = NULL; | 2505 CRLDPCache* cache = NULL; |
2771 SECStatus rv = SECSuccess; | 2506 SECStatus rv = SECSuccess; |
2772 PRBool writeLocked = PR_FALSE; | 2507 PRBool writeLocked = PR_FALSE; |
2773 PRBool readlocked; | 2508 PRBool readlocked; |
2774 | 2509 |
2775 (void) dbhandle; /* silence compiler warnings */ | 2510 (void)dbhandle; /* silence compiler warnings */ |
2776 | 2511 |
2777 /* XCRL we will need to refresh all the DPs of the issuer in the future, | 2512 /* XCRL we will need to refresh all the DPs of the issuer in the future, |
2778 not just the default one */ | 2513 not just the default one */ |
2779 rv = AcquireDPCache(NULL, crlKey, NULL, 0, NULL, &cache, &writeLocked); | 2514 rv = AcquireDPCache(NULL, crlKey, NULL, 0, NULL, &cache, &writeLocked); |
2780 if (SECSuccess != rv) | 2515 if (SECSuccess != rv) { |
2781 { | |
2782 return; | 2516 return; |
2783 } | 2517 } |
2784 /* we need to invalidate the DPCache here */ | 2518 /* we need to invalidate the DPCache here */ |
2785 readlocked = (writeLocked == PR_TRUE? PR_FALSE : PR_TRUE); | 2519 readlocked = (writeLocked == PR_TRUE ? PR_FALSE : PR_TRUE); |
2786 DPCache_LockWrite(); | 2520 DPCache_LockWrite(); |
2787 cache->refresh = PR_TRUE; | 2521 cache->refresh = PR_TRUE; |
2788 DPCache_UnlockWrite(); | 2522 DPCache_UnlockWrite(); |
2789 ReleaseDPCache(cache, writeLocked); | 2523 ReleaseDPCache(cache, writeLocked); |
2790 return; | 2524 return; |
2791 } | 2525 } |
2792 | 2526 |
2793 /* add the specified RAM CRL object to the cache */ | 2527 /* add the specified RAM CRL object to the cache */ |
2794 SECStatus CERT_CacheCRL(CERTCertDBHandle* dbhandle, SECItem* newdercrl) | 2528 SECStatus |
| 2529 CERT_CacheCRL(CERTCertDBHandle* dbhandle, SECItem* newdercrl) |
2795 { | 2530 { |
2796 CRLDPCache* cache = NULL; | 2531 CRLDPCache* cache = NULL; |
2797 SECStatus rv = SECSuccess; | 2532 SECStatus rv = SECSuccess; |
2798 PRBool writeLocked = PR_FALSE; | 2533 PRBool writeLocked = PR_FALSE; |
2799 PRBool readlocked; | 2534 PRBool readlocked; |
2800 CachedCrl* returned = NULL; | 2535 CachedCrl* returned = NULL; |
2801 PRBool added = PR_FALSE; | 2536 PRBool added = PR_FALSE; |
2802 CERTSignedCrl* newcrl = NULL; | 2537 CERTSignedCrl* newcrl = NULL; |
2803 int realerror = 0; | 2538 int realerror = 0; |
2804 | 2539 |
2805 if (!dbhandle || !newdercrl) | 2540 if (!dbhandle || !newdercrl) { |
2806 { | |
2807 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 2541 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
2808 return SECFailure; | 2542 return SECFailure; |
2809 } | 2543 } |
2810 | 2544 |
2811 /* first decode the DER CRL to make sure it's OK */ | 2545 /* first decode the DER CRL to make sure it's OK */ |
2812 newcrl = CERT_DecodeDERCrlWithFlags(NULL, newdercrl, SEC_CRL_TYPE, | 2546 newcrl = CERT_DecodeDERCrlWithFlags(NULL, newdercrl, SEC_CRL_TYPE, |
2813 CRL_DECODE_DONT_COPY_DER | | 2547 CRL_DECODE_DONT_COPY_DER | |
2814 CRL_DECODE_SKIP_ENTRIES); | 2548 CRL_DECODE_SKIP_ENTRIES); |
2815 | 2549 |
2816 if (!newcrl) | 2550 if (!newcrl) { |
2817 { | |
2818 return SECFailure; | 2551 return SECFailure; |
2819 } | 2552 } |
2820 | 2553 |
2821 /* XXX check if it has IDP extension. If so, do not proceed and set error */ | 2554 /* XXX check if it has IDP extension. If so, do not proceed and set error */ |
2822 | 2555 |
2823 rv = AcquireDPCache(NULL, | 2556 rv = AcquireDPCache(NULL, &newcrl->crl.derName, NULL, 0, NULL, &cache, |
2824 &newcrl->crl.derName, | 2557 &writeLocked); |
2825 NULL, 0, NULL, &cache, &writeLocked); | 2558 if (SECSuccess == rv) { |
2826 if (SECSuccess == rv) | 2559 readlocked = (writeLocked == PR_TRUE ? PR_FALSE : PR_TRUE); |
2827 { | 2560 |
2828 readlocked = (writeLocked == PR_TRUE? PR_FALSE : PR_TRUE); | |
2829 | |
2830 rv = CachedCrl_Create(&returned, newcrl, CRL_OriginExplicit); | 2561 rv = CachedCrl_Create(&returned, newcrl, CRL_OriginExplicit); |
2831 if (SECSuccess == rv && returned) | 2562 if (SECSuccess == rv && returned) { |
2832 { | |
2833 DPCache_LockWrite(); | 2563 DPCache_LockWrite(); |
2834 rv = DPCache_AddCRL(cache, returned, &added); | 2564 rv = DPCache_AddCRL(cache, returned, &added); |
2835 if (PR_TRUE != added) | 2565 if (PR_TRUE != added) { |
2836 { | |
2837 realerror = PORT_GetError(); | 2566 realerror = PORT_GetError(); |
2838 CachedCrl_Destroy(returned); | 2567 CachedCrl_Destroy(returned); |
2839 returned = NULL; | 2568 returned = NULL; |
2840 } | 2569 } |
2841 DPCache_UnlockWrite(); | 2570 DPCache_UnlockWrite(); |
2842 } | 2571 } |
2843 | 2572 |
2844 ReleaseDPCache(cache, writeLocked); | 2573 ReleaseDPCache(cache, writeLocked); |
2845 | 2574 |
2846 if (!added) | 2575 if (!added) { |
2847 { | |
2848 rv = SECFailure; | 2576 rv = SECFailure; |
2849 } | 2577 } |
2850 } | 2578 } |
2851 SEC_DestroyCrl(newcrl); /* free the CRL. Either it got added to the cache | 2579 SEC_DestroyCrl(newcrl); /* free the CRL. Either it got added to the cache |
2852 and the refcount got bumped, or not, and thus we need to free its | 2580 and the refcount got bumped, or not, and thus we need to free its |
2853 RAM */ | 2581 RAM */ |
2854 if (realerror) | 2582 if (realerror) { |
2855 { | |
2856 PORT_SetError(realerror); | 2583 PORT_SetError(realerror); |
2857 } | 2584 } |
2858 return rv; | 2585 return rv; |
2859 } | 2586 } |
2860 | 2587 |
2861 /* remove the specified RAM CRL object from the cache */ | 2588 /* remove the specified RAM CRL object from the cache */ |
2862 SECStatus CERT_UncacheCRL(CERTCertDBHandle* dbhandle, SECItem* olddercrl) | 2589 SECStatus |
| 2590 CERT_UncacheCRL(CERTCertDBHandle* dbhandle, SECItem* olddercrl) |
2863 { | 2591 { |
2864 CRLDPCache* cache = NULL; | 2592 CRLDPCache* cache = NULL; |
2865 SECStatus rv = SECSuccess; | 2593 SECStatus rv = SECSuccess; |
2866 PRBool writeLocked = PR_FALSE; | 2594 PRBool writeLocked = PR_FALSE; |
2867 PRBool readlocked; | 2595 PRBool readlocked; |
2868 PRBool removed = PR_FALSE; | 2596 PRBool removed = PR_FALSE; |
2869 PRUint32 i; | 2597 PRUint32 i; |
2870 CERTSignedCrl* oldcrl = NULL; | 2598 CERTSignedCrl* oldcrl = NULL; |
2871 | 2599 |
2872 if (!dbhandle || !olddercrl) | 2600 if (!dbhandle || !olddercrl) { |
2873 { | |
2874 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 2601 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
2875 return SECFailure; | 2602 return SECFailure; |
2876 } | 2603 } |
2877 | 2604 |
2878 /* first decode the DER CRL to make sure it's OK */ | 2605 /* first decode the DER CRL to make sure it's OK */ |
2879 oldcrl = CERT_DecodeDERCrlWithFlags(NULL, olddercrl, SEC_CRL_TYPE, | 2606 oldcrl = CERT_DecodeDERCrlWithFlags(NULL, olddercrl, SEC_CRL_TYPE, |
2880 CRL_DECODE_DONT_COPY_DER | | 2607 CRL_DECODE_DONT_COPY_DER | |
2881 CRL_DECODE_SKIP_ENTRIES); | 2608 CRL_DECODE_SKIP_ENTRIES); |
2882 | 2609 |
2883 if (!oldcrl) | 2610 if (!oldcrl) { |
2884 { | |
2885 /* if this DER CRL can't decode, it can't be in the cache */ | 2611 /* if this DER CRL can't decode, it can't be in the cache */ |
2886 return SECFailure; | 2612 return SECFailure; |
2887 } | 2613 } |
2888 | 2614 |
2889 rv = AcquireDPCache(NULL, | 2615 rv = AcquireDPCache(NULL, &oldcrl->crl.derName, NULL, 0, NULL, &cache, |
2890 &oldcrl->crl.derName, | 2616 &writeLocked); |
2891 NULL, 0, NULL, &cache, &writeLocked); | 2617 if (SECSuccess == rv) { |
2892 if (SECSuccess == rv) | |
2893 { | |
2894 CachedCrl* returned = NULL; | 2618 CachedCrl* returned = NULL; |
2895 | 2619 |
2896 readlocked = (writeLocked == PR_TRUE? PR_FALSE : PR_TRUE); | 2620 readlocked = (writeLocked == PR_TRUE ? PR_FALSE : PR_TRUE); |
2897 | 2621 |
2898 rv = CachedCrl_Create(&returned, oldcrl, CRL_OriginExplicit); | 2622 rv = CachedCrl_Create(&returned, oldcrl, CRL_OriginExplicit); |
2899 if (SECSuccess == rv && returned) | 2623 if (SECSuccess == rv && returned) { |
2900 { | |
2901 DPCache_LockWrite(); | 2624 DPCache_LockWrite(); |
2902 for (i=0;i<cache->ncrls;i++) | 2625 for (i = 0; i < cache->ncrls; i++) { |
2903 { | |
2904 PRBool dupe = PR_FALSE, updated = PR_FALSE; | 2626 PRBool dupe = PR_FALSE, updated = PR_FALSE; |
2905 rv = CachedCrl_Compare(returned, cache->crls[i], | 2627 rv = CachedCrl_Compare(returned, cache->crls[i], &dupe, |
2906 &dupe, &updated); | 2628 &updated); |
2907 if (SECSuccess != rv) | 2629 if (SECSuccess != rv) { |
2908 { | |
2909 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2630 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2910 break; | 2631 break; |
2911 } | 2632 } |
2912 if (PR_TRUE == dupe) | 2633 if (PR_TRUE == dupe) { |
2913 { | |
2914 rv = DPCache_RemoveCRL(cache, i); /* got a match */ | 2634 rv = DPCache_RemoveCRL(cache, i); /* got a match */ |
2915 if (SECSuccess == rv) { | 2635 if (SECSuccess == rv) { |
2916 cache->mustchoose = PR_TRUE; | 2636 cache->mustchoose = PR_TRUE; |
2917 removed = PR_TRUE; | 2637 removed = PR_TRUE; |
2918 } | 2638 } |
2919 break; | 2639 break; |
2920 } | 2640 } |
2921 } | 2641 } |
2922 | 2642 |
2923 DPCache_UnlockWrite(); | 2643 DPCache_UnlockWrite(); |
2924 | 2644 |
2925 if (SECSuccess != CachedCrl_Destroy(returned) ) { | 2645 if (SECSuccess != CachedCrl_Destroy(returned)) { |
2926 rv = SECFailure; | 2646 rv = SECFailure; |
2927 } | 2647 } |
2928 } | 2648 } |
2929 | 2649 |
2930 ReleaseDPCache(cache, writeLocked); | 2650 ReleaseDPCache(cache, writeLocked); |
2931 } | 2651 } |
2932 if (SECSuccess != SEC_DestroyCrl(oldcrl) ) { | 2652 if (SECSuccess != SEC_DestroyCrl(oldcrl)) { |
2933 /* need to do this because object is refcounted */ | 2653 /* need to do this because object is refcounted */ |
2934 rv = SECFailure; | 2654 rv = SECFailure; |
2935 } | 2655 } |
2936 if (SECSuccess == rv && PR_TRUE != removed) | 2656 if (SECSuccess == rv && PR_TRUE != removed) { |
2937 { | |
2938 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); | 2657 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); |
2939 } | 2658 } |
2940 return rv; | 2659 return rv; |
2941 } | 2660 } |
2942 | 2661 |
2943 SECStatus cert_AcquireNamedCRLCache(NamedCRLCache** returned) | 2662 SECStatus |
| 2663 cert_AcquireNamedCRLCache(NamedCRLCache** returned) |
2944 { | 2664 { |
2945 PORT_Assert(returned); | 2665 PORT_Assert(returned); |
2946 if (!namedCRLCache.lock) | 2666 if (!namedCRLCache.lock) { |
2947 { | |
2948 PORT_Assert(0); | 2667 PORT_Assert(0); |
2949 return SECFailure; | 2668 return SECFailure; |
2950 } | 2669 } |
2951 PR_Lock(namedCRLCache.lock); | 2670 PR_Lock(namedCRLCache.lock); |
2952 *returned = &namedCRLCache; | 2671 *returned = &namedCRLCache; |
2953 return SECSuccess; | 2672 return SECSuccess; |
2954 } | 2673 } |
2955 | 2674 |
2956 /* This must be called only while cache is acquired, and the entry is only | 2675 /* This must be called only while cache is acquired, and the entry is only |
2957 * valid until cache is released. | 2676 * valid until cache is released. |
2958 */ | 2677 */ |
2959 SECStatus cert_FindCRLByGeneralName(NamedCRLCache* ncc, | 2678 SECStatus |
2960 const SECItem* canonicalizedName, | 2679 cert_FindCRLByGeneralName(NamedCRLCache* ncc, const SECItem* canonicalizedName, |
2961 NamedCRLCacheEntry** retEntry) | 2680 NamedCRLCacheEntry** retEntry) |
2962 { | 2681 { |
2963 if (!ncc || !canonicalizedName || !retEntry) | 2682 if (!ncc || !canonicalizedName || !retEntry) { |
2964 { | |
2965 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 2683 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
2966 return SECFailure; | 2684 return SECFailure; |
2967 } | 2685 } |
2968 *retEntry = (NamedCRLCacheEntry*) PL_HashTableLookup(namedCRLCache.entries, | 2686 *retEntry = (NamedCRLCacheEntry*)PL_HashTableLookup( |
2969 (void*) canonicalizedName); | 2687 namedCRLCache.entries, (void*)canonicalizedName); |
2970 return SECSuccess; | 2688 return SECSuccess; |
2971 } | 2689 } |
2972 | 2690 |
2973 SECStatus cert_ReleaseNamedCRLCache(NamedCRLCache* ncc) | 2691 SECStatus |
| 2692 cert_ReleaseNamedCRLCache(NamedCRLCache* ncc) |
2974 { | 2693 { |
2975 if (!ncc) | 2694 if (!ncc) { |
2976 { | |
2977 return SECFailure; | 2695 return SECFailure; |
2978 } | 2696 } |
2979 if (!ncc->lock) | 2697 if (!ncc->lock) { |
2980 { | |
2981 PORT_Assert(0); | 2698 PORT_Assert(0); |
2982 return SECFailure; | 2699 return SECFailure; |
2983 } | 2700 } |
2984 PR_Unlock(namedCRLCache.lock); | 2701 PR_Unlock(namedCRLCache.lock); |
2985 return SECSuccess; | 2702 return SECSuccess; |
2986 } | 2703 } |
2987 | 2704 |
2988 /* creates new named cache entry from CRL, and tries to add it to CRL cache */ | 2705 /* creates new named cache entry from CRL, and tries to add it to CRL cache */ |
2989 static SECStatus addCRLToCache(CERTCertDBHandle* dbhandle, SECItem* crl, | 2706 static SECStatus |
2990 const SECItem* canonicalizedName, | 2707 addCRLToCache(CERTCertDBHandle* dbhandle, SECItem* crl, |
2991 NamedCRLCacheEntry** newEntry) | 2708 const SECItem* canonicalizedName, NamedCRLCacheEntry** newEntry) |
2992 { | 2709 { |
2993 SECStatus rv = SECSuccess; | 2710 SECStatus rv = SECSuccess; |
2994 NamedCRLCacheEntry* entry = NULL; | 2711 NamedCRLCacheEntry* entry = NULL; |
2995 | 2712 |
2996 /* create new named entry */ | 2713 /* create new named entry */ |
2997 if (SECSuccess != NamedCRLCacheEntry_Create(newEntry) || !*newEntry) | 2714 if (SECSuccess != NamedCRLCacheEntry_Create(newEntry) || !*newEntry) { |
2998 { | |
2999 /* no need to keep unused CRL around */ | 2715 /* no need to keep unused CRL around */ |
3000 SECITEM_ZfreeItem(crl, PR_TRUE); | 2716 SECITEM_ZfreeItem(crl, PR_TRUE); |
3001 return SECFailure; | 2717 return SECFailure; |
3002 } | 2718 } |
3003 entry = *newEntry; | 2719 entry = *newEntry; |
3004 entry->crl = crl; /* named CRL cache owns DER */ | 2720 entry->crl = crl; /* named CRL cache owns DER */ |
3005 entry->lastAttemptTime = PR_Now(); | 2721 entry->lastAttemptTime = PR_Now(); |
3006 entry->canonicalizedName = SECITEM_DupItem(canonicalizedName); | 2722 entry->canonicalizedName = SECITEM_DupItem(canonicalizedName); |
3007 if (!entry->canonicalizedName) | 2723 if (!entry->canonicalizedName) { |
3008 { | |
3009 rv = NamedCRLCacheEntry_Destroy(entry); /* destroys CRL too */ | 2724 rv = NamedCRLCacheEntry_Destroy(entry); /* destroys CRL too */ |
3010 PORT_Assert(SECSuccess == rv); | 2725 PORT_Assert(SECSuccess == rv); |
3011 return SECFailure; | 2726 return SECFailure; |
3012 } | 2727 } |
3013 /* now, attempt to insert CRL into CRL cache */ | 2728 /* now, attempt to insert CRL into CRL cache */ |
3014 if (SECSuccess == CERT_CacheCRL(dbhandle, entry->crl)) | 2729 if (SECSuccess == CERT_CacheCRL(dbhandle, entry->crl)) { |
3015 { | |
3016 entry->inCRLCache = PR_TRUE; | 2730 entry->inCRLCache = PR_TRUE; |
3017 entry->successfulInsertionTime = entry->lastAttemptTime; | 2731 entry->successfulInsertionTime = entry->lastAttemptTime; |
3018 } | 2732 } else { |
3019 else | 2733 switch (PR_GetError()) { |
3020 { | |
3021 switch (PR_GetError()) | |
3022 { | |
3023 case SEC_ERROR_CRL_ALREADY_EXISTS: | 2734 case SEC_ERROR_CRL_ALREADY_EXISTS: |
3024 entry->dupe = PR_TRUE; | 2735 entry->dupe = PR_TRUE; |
3025 break; | 2736 break; |
3026 | 2737 |
3027 case SEC_ERROR_BAD_DER: | 2738 case SEC_ERROR_BAD_DER: |
3028 entry->badDER = PR_TRUE; | 2739 entry->badDER = PR_TRUE; |
3029 break; | 2740 break; |
3030 | 2741 |
3031 /* all other reasons */ | 2742 /* all other reasons */ |
3032 default: | 2743 default: |
3033 entry->unsupported = PR_TRUE; | 2744 entry->unsupported = PR_TRUE; |
3034 break; | 2745 break; |
3035 } | 2746 } |
3036 rv = SECFailure; | 2747 rv = SECFailure; |
3037 /* no need to keep unused CRL around */ | 2748 /* no need to keep unused CRL around */ |
3038 SECITEM_ZfreeItem(entry->crl, PR_TRUE); | 2749 SECITEM_ZfreeItem(entry->crl, PR_TRUE); |
3039 entry->crl = NULL; | 2750 entry->crl = NULL; |
3040 } | 2751 } |
3041 return rv; | 2752 return rv; |
3042 } | 2753 } |
3043 | 2754 |
3044 /* take ownership of CRL, and insert it into the named CRL cache | 2755 /* take ownership of CRL, and insert it into the named CRL cache |
3045 * and indexed CRL cache | 2756 * and indexed CRL cache |
3046 */ | 2757 */ |
3047 SECStatus cert_CacheCRLByGeneralName(CERTCertDBHandle* dbhandle, SECItem* crl, | 2758 SECStatus |
3048 const SECItem* canonicalizedName) | 2759 cert_CacheCRLByGeneralName(CERTCertDBHandle* dbhandle, SECItem* crl, |
| 2760 const SECItem* canonicalizedName) |
3049 { | 2761 { |
3050 NamedCRLCacheEntry* oldEntry, * newEntry = NULL; | 2762 NamedCRLCacheEntry *oldEntry, *newEntry = NULL; |
3051 NamedCRLCache* ncc = NULL; | 2763 NamedCRLCache* ncc = NULL; |
3052 SECStatus rv = SECSuccess; | 2764 SECStatus rv = SECSuccess; |
3053 | 2765 |
3054 PORT_Assert(namedCRLCache.lock); | 2766 PORT_Assert(namedCRLCache.lock); |
3055 PORT_Assert(namedCRLCache.entries); | 2767 PORT_Assert(namedCRLCache.entries); |
3056 | 2768 |
3057 if (!crl || !canonicalizedName) | 2769 if (!crl || !canonicalizedName) { |
3058 { | |
3059 PORT_Assert(0); | 2770 PORT_Assert(0); |
3060 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 2771 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
3061 return SECFailure; | 2772 return SECFailure; |
3062 } | 2773 } |
3063 | 2774 |
3064 rv = cert_AcquireNamedCRLCache(&ncc); | 2775 rv = cert_AcquireNamedCRLCache(&ncc); |
3065 PORT_Assert(SECSuccess == rv); | 2776 PORT_Assert(SECSuccess == rv); |
3066 if (SECSuccess != rv) | 2777 if (SECSuccess != rv) { |
3067 { | |
3068 SECITEM_ZfreeItem(crl, PR_TRUE); | 2778 SECITEM_ZfreeItem(crl, PR_TRUE); |
3069 return SECFailure; | 2779 return SECFailure; |
3070 } | 2780 } |
3071 rv = cert_FindCRLByGeneralName(ncc, canonicalizedName, &oldEntry); | 2781 rv = cert_FindCRLByGeneralName(ncc, canonicalizedName, &oldEntry); |
3072 PORT_Assert(SECSuccess == rv); | 2782 PORT_Assert(SECSuccess == rv); |
3073 if (SECSuccess != rv) | 2783 if (SECSuccess != rv) { |
3074 { | |
3075 rv = cert_ReleaseNamedCRLCache(ncc); | 2784 rv = cert_ReleaseNamedCRLCache(ncc); |
3076 SECITEM_ZfreeItem(crl, PR_TRUE); | 2785 SECITEM_ZfreeItem(crl, PR_TRUE); |
3077 return SECFailure; | 2786 return SECFailure; |
3078 } | 2787 } |
3079 if (SECSuccess == addCRLToCache(dbhandle, crl, canonicalizedName, | 2788 if (SECSuccess == |
3080 &newEntry) ) | 2789 addCRLToCache(dbhandle, crl, canonicalizedName, &newEntry)) { |
3081 { | 2790 if (!oldEntry) { |
3082 if (!oldEntry) | |
3083 { | |
3084 /* add new good entry to the hash table */ | 2791 /* add new good entry to the hash table */ |
3085 if (NULL == PL_HashTableAdd(namedCRLCache.entries, | 2792 if (NULL == PL_HashTableAdd(namedCRLCache.entries, |
3086 (void*) newEntry->canonicalizedName, | 2793 (void*)newEntry->canonicalizedName, |
3087 (void*) newEntry)) | 2794 (void*)newEntry)) { |
3088 { | |
3089 PORT_Assert(0); | 2795 PORT_Assert(0); |
3090 NamedCRLCacheEntry_Destroy(newEntry); | 2796 NamedCRLCacheEntry_Destroy(newEntry); |
3091 rv = SECFailure; | 2797 rv = SECFailure; |
3092 } | 2798 } |
3093 } | 2799 } else { |
3094 else | |
3095 { | |
3096 PRBool removed; | 2800 PRBool removed; |
3097 /* remove the old CRL from the cache if needed */ | 2801 /* remove the old CRL from the cache if needed */ |
3098 if (oldEntry->inCRLCache) | 2802 if (oldEntry->inCRLCache) { |
3099 { | |
3100 rv = CERT_UncacheCRL(dbhandle, oldEntry->crl); | 2803 rv = CERT_UncacheCRL(dbhandle, oldEntry->crl); |
3101 PORT_Assert(SECSuccess == rv); | 2804 PORT_Assert(SECSuccess == rv); |
3102 } | 2805 } |
3103 removed = PL_HashTableRemove(namedCRLCache.entries, | 2806 removed = PL_HashTableRemove(namedCRLCache.entries, |
3104 (void*) oldEntry->canonicalizedName); | 2807 (void*)oldEntry->canonicalizedName); |
3105 PORT_Assert(removed); | 2808 PORT_Assert(removed); |
3106 if (!removed) | 2809 if (!removed) { |
3107 { | |
3108 rv = SECFailure; | 2810 rv = SECFailure; |
3109 » » /* leak old entry since we couldn't remove it from the hash tabl
e */ | 2811 /* leak old entry since we couldn't remove it from the hash |
3110 } | 2812 * table */ |
3111 else | 2813 } else { |
3112 { | |
3113 PORT_CheckSuccess(NamedCRLCacheEntry_Destroy(oldEntry)); | 2814 PORT_CheckSuccess(NamedCRLCacheEntry_Destroy(oldEntry)); |
3114 } | 2815 } |
3115 if (NULL == PL_HashTableAdd(namedCRLCache.entries, | 2816 if (NULL == PL_HashTableAdd(namedCRLCache.entries, |
3116 (void*) newEntry->canonicalizedName, | 2817 (void*)newEntry->canonicalizedName, |
3117 (void*) newEntry)) | 2818 (void*)newEntry)) { |
3118 { | |
3119 PORT_Assert(0); | 2819 PORT_Assert(0); |
3120 rv = SECFailure; | 2820 rv = SECFailure; |
3121 } | 2821 } |
3122 } | 2822 } |
3123 } else | 2823 } else { |
3124 { | |
3125 /* error adding new CRL to cache */ | 2824 /* error adding new CRL to cache */ |
3126 if (!oldEntry) | 2825 if (!oldEntry) { |
3127 { | |
3128 /* no old cache entry, use the new one even though it's bad */ | 2826 /* no old cache entry, use the new one even though it's bad */ |
3129 if (NULL == PL_HashTableAdd(namedCRLCache.entries, | 2827 if (NULL == PL_HashTableAdd(namedCRLCache.entries, |
3130 (void*) newEntry->canonicalizedName, | 2828 (void*)newEntry->canonicalizedName, |
3131 (void*) newEntry)) | 2829 (void*)newEntry)) { |
3132 { | |
3133 PORT_Assert(0); | 2830 PORT_Assert(0); |
3134 rv = SECFailure; | 2831 rv = SECFailure; |
3135 } | 2832 } |
3136 } | 2833 } else { |
3137 else | 2834 if (oldEntry->inCRLCache) { |
3138 { | |
3139 if (oldEntry->inCRLCache) | |
3140 { | |
3141 /* previous cache entry was good, keep it and update time */ | 2835 /* previous cache entry was good, keep it and update time */ |
3142 oldEntry-> lastAttemptTime = newEntry->lastAttemptTime; | 2836 oldEntry->lastAttemptTime = newEntry->lastAttemptTime; |
3143 /* throw away new bad entry */ | 2837 /* throw away new bad entry */ |
3144 rv = NamedCRLCacheEntry_Destroy(newEntry); | 2838 rv = NamedCRLCacheEntry_Destroy(newEntry); |
3145 PORT_Assert(SECSuccess == rv); | 2839 PORT_Assert(SECSuccess == rv); |
3146 } | 2840 } else { |
3147 else | |
3148 { | |
3149 /* previous cache entry was bad, just replace it */ | 2841 /* previous cache entry was bad, just replace it */ |
3150 PRBool removed = PL_HashTableRemove(namedCRLCache.entries, | 2842 PRBool removed = PL_HashTableRemove( |
3151 (void*) oldEntry->canonicalizedName); | 2843 namedCRLCache.entries, (void*)oldEntry->canonicalizedName); |
3152 PORT_Assert(removed); | 2844 PORT_Assert(removed); |
3153 if (!removed) | 2845 if (!removed) { |
3154 { | 2846 /* leak old entry since we couldn't remove it from the hash |
3155 » » /* leak old entry since we couldn't remove it from the hash
table */ | 2847 * table */ |
3156 rv = SECFailure; | 2848 rv = SECFailure; |
3157 } | 2849 } else { |
3158 else | |
3159 { | |
3160 PORT_CheckSuccess(NamedCRLCacheEntry_Destroy(oldEntry)); | 2850 PORT_CheckSuccess(NamedCRLCacheEntry_Destroy(oldEntry)); |
3161 } | 2851 } |
3162 if (NULL == PL_HashTableAdd(namedCRLCache.entries, | 2852 if (NULL == PL_HashTableAdd(namedCRLCache.entries, |
3163 (void*) newEntry->canonicalizedName, | 2853 (void*)newEntry->canonicalizedName, |
3164 (void*) newEntry)) | 2854 (void*)newEntry)) { |
3165 { | |
3166 PORT_Assert(0); | 2855 PORT_Assert(0); |
3167 rv = SECFailure; | 2856 rv = SECFailure; |
3168 } | 2857 } |
3169 } | 2858 } |
3170 } | 2859 } |
3171 } | 2860 } |
3172 PORT_CheckSuccess(cert_ReleaseNamedCRLCache(ncc)); | 2861 PORT_CheckSuccess(cert_ReleaseNamedCRLCache(ncc)); |
3173 | 2862 |
3174 return rv; | 2863 return rv; |
3175 } | 2864 } |
3176 | 2865 |
3177 static SECStatus CachedCrl_Create(CachedCrl** returned, CERTSignedCrl* crl, | 2866 static SECStatus |
3178 CRLOrigin origin) | 2867 CachedCrl_Create(CachedCrl** returned, CERTSignedCrl* crl, CRLOrigin origin) |
3179 { | 2868 { |
3180 CachedCrl* newcrl = NULL; | 2869 CachedCrl* newcrl = NULL; |
3181 if (!returned) | 2870 if (!returned) { |
3182 { | |
3183 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2871 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
3184 return SECFailure; | 2872 return SECFailure; |
3185 } | 2873 } |
3186 newcrl = PORT_ZAlloc(sizeof(CachedCrl)); | 2874 newcrl = PORT_ZAlloc(sizeof(CachedCrl)); |
3187 if (!newcrl) | 2875 if (!newcrl) { |
3188 { | |
3189 return SECFailure; | 2876 return SECFailure; |
3190 } | 2877 } |
3191 newcrl->crl = SEC_DupCrl(crl); | 2878 newcrl->crl = SEC_DupCrl(crl); |
3192 newcrl->origin = origin; | 2879 newcrl->origin = origin; |
3193 *returned = newcrl; | 2880 *returned = newcrl; |
3194 return SECSuccess; | 2881 return SECSuccess; |
3195 } | 2882 } |
3196 | 2883 |
3197 /* empty the cache content */ | 2884 /* empty the cache content */ |
3198 static SECStatus CachedCrl_Depopulate(CachedCrl* crl) | 2885 static SECStatus |
| 2886 CachedCrl_Depopulate(CachedCrl* crl) |
3199 { | 2887 { |
3200 if (!crl) | 2888 if (!crl) { |
3201 { | |
3202 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2889 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
3203 return SECFailure; | 2890 return SECFailure; |
3204 } | 2891 } |
3205 /* destroy the hash table */ | 2892 /* destroy the hash table */ |
3206 if (crl->entries) | 2893 if (crl->entries) { |
3207 { | |
3208 PL_HashTableDestroy(crl->entries); | 2894 PL_HashTableDestroy(crl->entries); |
3209 crl->entries = NULL; | 2895 crl->entries = NULL; |
3210 } | 2896 } |
3211 | 2897 |
3212 /* free the pre buffer */ | 2898 /* free the pre buffer */ |
3213 if (crl->prebuffer) | 2899 if (crl->prebuffer) { |
3214 { | |
3215 PreAllocator_Destroy(crl->prebuffer); | 2900 PreAllocator_Destroy(crl->prebuffer); |
3216 crl->prebuffer = NULL; | 2901 crl->prebuffer = NULL; |
3217 } | 2902 } |
3218 return SECSuccess; | 2903 return SECSuccess; |
3219 } | 2904 } |
3220 | 2905 |
3221 static SECStatus CachedCrl_Destroy(CachedCrl* crl) | 2906 static SECStatus |
| 2907 CachedCrl_Destroy(CachedCrl* crl) |
3222 { | 2908 { |
3223 if (!crl) | 2909 if (!crl) { |
3224 { | |
3225 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2910 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
3226 return SECFailure; | 2911 return SECFailure; |
3227 } | 2912 } |
3228 CachedCrl_Depopulate(crl); | 2913 CachedCrl_Depopulate(crl); |
3229 SEC_DestroyCrl(crl->crl); | 2914 SEC_DestroyCrl(crl->crl); |
3230 PORT_Free(crl); | 2915 PORT_Free(crl); |
3231 return SECSuccess; | 2916 return SECSuccess; |
3232 } | 2917 } |
3233 | 2918 |
3234 /* create hash table of CRL entries */ | 2919 /* create hash table of CRL entries */ |
3235 static SECStatus CachedCrl_Populate(CachedCrl* crlobject) | 2920 static SECStatus |
| 2921 CachedCrl_Populate(CachedCrl* crlobject) |
3236 { | 2922 { |
3237 SECStatus rv = SECFailure; | 2923 SECStatus rv = SECFailure; |
3238 CERTCrlEntry** crlEntry = NULL; | 2924 CERTCrlEntry** crlEntry = NULL; |
3239 PRUint32 numEntries = 0; | 2925 PRUint32 numEntries = 0; |
3240 | 2926 |
3241 if (!crlobject) | 2927 if (!crlobject) { |
3242 { | |
3243 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 2928 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
3244 return SECFailure; | 2929 return SECFailure; |
3245 } | 2930 } |
3246 /* complete the entry decoding . XXX thread-safety of CRL object */ | 2931 /* complete the entry decoding . XXX thread-safety of CRL object */ |
3247 rv = CERT_CompleteCRLDecodeEntries(crlobject->crl); | 2932 rv = CERT_CompleteCRLDecodeEntries(crlobject->crl); |
3248 if (SECSuccess != rv) | 2933 if (SECSuccess != rv) { |
3249 { | |
3250 crlobject->unbuildable = PR_TRUE; /* don't try to build this again */ | 2934 crlobject->unbuildable = PR_TRUE; /* don't try to build this again */ |
3251 return SECFailure; | 2935 return SECFailure; |
3252 } | 2936 } |
3253 | 2937 |
3254 if (crlobject->entries && crlobject->prebuffer) | 2938 if (crlobject->entries && crlobject->prebuffer) { |
3255 { | |
3256 /* cache is already built */ | 2939 /* cache is already built */ |
3257 return SECSuccess; | 2940 return SECSuccess; |
3258 } | 2941 } |
3259 | 2942 |
3260 /* build the hash table from the full CRL */ | 2943 /* build the hash table from the full CRL */ |
3261 /* count CRL entries so we can pre-allocate space for hash table entries */ | 2944 /* count CRL entries so we can pre-allocate space for hash table entries */ |
3262 for (crlEntry = crlobject->crl->crl.entries; crlEntry && *crlEntry; | 2945 for (crlEntry = crlobject->crl->crl.entries; crlEntry && *crlEntry; |
3263 crlEntry++) | 2946 crlEntry++) { |
3264 { | |
3265 numEntries++; | 2947 numEntries++; |
3266 } | 2948 } |
3267 crlobject->prebuffer = PreAllocator_Create(numEntries*sizeof(PLHashEntry)); | 2949 crlobject->prebuffer = |
| 2950 PreAllocator_Create(numEntries * sizeof(PLHashEntry)); |
3268 PORT_Assert(crlobject->prebuffer); | 2951 PORT_Assert(crlobject->prebuffer); |
3269 if (!crlobject->prebuffer) | 2952 if (!crlobject->prebuffer) { |
3270 { | |
3271 return SECFailure; | 2953 return SECFailure; |
3272 } | 2954 } |
3273 /* create a new hash table */ | 2955 /* create a new hash table */ |
3274 crlobject->entries = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, | 2956 crlobject->entries = |
3275 PL_CompareValues, &preAllocOps, crlobject->prebuffer); | 2957 PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, PL_CompareValues, |
| 2958 &preAllocOps, crlobject->prebuffer); |
3276 PORT_Assert(crlobject->entries); | 2959 PORT_Assert(crlobject->entries); |
3277 if (!crlobject->entries) | 2960 if (!crlobject->entries) { |
3278 { | |
3279 return SECFailure; | 2961 return SECFailure; |
3280 } | 2962 } |
3281 /* add all serial numbers to the hash table */ | 2963 /* add all serial numbers to the hash table */ |
3282 for (crlEntry = crlobject->crl->crl.entries; crlEntry && *crlEntry; | 2964 for (crlEntry = crlobject->crl->crl.entries; crlEntry && *crlEntry; |
3283 crlEntry++) | 2965 crlEntry++) { |
3284 { | |
3285 PL_HashTableAdd(crlobject->entries, &(*crlEntry)->serialNumber, | 2966 PL_HashTableAdd(crlobject->entries, &(*crlEntry)->serialNumber, |
3286 *crlEntry); | 2967 *crlEntry); |
3287 } | 2968 } |
3288 | 2969 |
3289 return SECSuccess; | 2970 return SECSuccess; |
3290 } | 2971 } |
3291 | 2972 |
3292 /* returns true if there are CRLs from PKCS#11 slots */ | 2973 /* returns true if there are CRLs from PKCS#11 slots */ |
3293 static PRBool DPCache_HasTokenCRLs(CRLDPCache* cache) | 2974 static PRBool |
| 2975 DPCache_HasTokenCRLs(CRLDPCache* cache) |
3294 { | 2976 { |
3295 PRBool answer = PR_FALSE; | 2977 PRBool answer = PR_FALSE; |
3296 PRUint32 i; | 2978 PRUint32 i; |
3297 for (i=0;i<cache->ncrls;i++) | 2979 for (i = 0; i < cache->ncrls; i++) { |
3298 { | 2980 if (cache->crls[i] && (CRL_OriginToken == cache->crls[i]->origin)) { |
3299 if (cache->crls[i] && (CRL_OriginToken == cache->crls[i]->origin) ) | |
3300 { | |
3301 answer = PR_TRUE; | 2981 answer = PR_TRUE; |
3302 break; | 2982 break; |
3303 } | 2983 } |
3304 } | 2984 } |
3305 return answer; | 2985 return answer; |
3306 } | 2986 } |
3307 | 2987 |
3308 /* are these CRLs the same, as far as the cache is concerned ? */ | 2988 /* are these CRLs the same, as far as the cache is concerned ? */ |
3309 /* are these CRLs the same token object but with different DER ? | 2989 /* are these CRLs the same token object but with different DER ? |
3310 This can happen if the DER CRL got updated in the token, but the PKCS#11 | 2990 This can happen if the DER CRL got updated in the token, but the PKCS#11 |
3311 object ID did not change. NSS softoken has the unfortunate property to | 2991 object ID did not change. NSS softoken has the unfortunate property to |
3312 never change the object ID for CRL objects. */ | 2992 never change the object ID for CRL objects. */ |
3313 static SECStatus CachedCrl_Compare(CachedCrl* a, CachedCrl* b, PRBool* isDupe, | 2993 static SECStatus |
3314 PRBool* isUpdated) | 2994 CachedCrl_Compare(CachedCrl* a, CachedCrl* b, PRBool* isDupe, PRBool* isUpdated) |
3315 { | 2995 { |
3316 PORT_Assert(a); | 2996 PORT_Assert(a); |
3317 PORT_Assert(b); | 2997 PORT_Assert(b); |
3318 PORT_Assert(isDupe); | 2998 PORT_Assert(isDupe); |
3319 PORT_Assert(isUpdated); | 2999 PORT_Assert(isUpdated); |
3320 if (!a || !b || !isDupe || !isUpdated || !a->crl || !b->crl) | 3000 if (!a || !b || !isDupe || !isUpdated || !a->crl || !b->crl) { |
3321 { | |
3322 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 3001 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
3323 return SECFailure; | 3002 return SECFailure; |
3324 } | 3003 } |
3325 | 3004 |
3326 *isDupe = *isUpdated = PR_FALSE; | 3005 *isDupe = *isUpdated = PR_FALSE; |
3327 | 3006 |
3328 if (a == b) | 3007 if (a == b) { |
3329 { | |
3330 /* dupe */ | 3008 /* dupe */ |
3331 *isDupe = PR_TRUE; | 3009 *isDupe = PR_TRUE; |
3332 *isUpdated = PR_FALSE; | 3010 *isUpdated = PR_FALSE; |
3333 return SECSuccess; | 3011 return SECSuccess; |
3334 } | 3012 } |
3335 if (b->origin != a->origin) | 3013 if (b->origin != a->origin) { |
3336 { | |
3337 /* CRLs of different origins are not considered dupes, | 3014 /* CRLs of different origins are not considered dupes, |
3338 and can't be updated either */ | 3015 and can't be updated either */ |
3339 return SECSuccess; | 3016 return SECSuccess; |
3340 } | 3017 } |
3341 if (CRL_OriginToken == b->origin) | 3018 if (CRL_OriginToken == b->origin) { |
3342 { | |
3343 /* for token CRLs, slot and PKCS#11 object handle must match for CRL | 3019 /* for token CRLs, slot and PKCS#11 object handle must match for CRL |
3344 to truly be a dupe */ | 3020 to truly be a dupe */ |
3345 if ( (b->crl->slot == a->crl->slot) && | 3021 if ((b->crl->slot == a->crl->slot) && |
3346 (b->crl->pkcs11ID == a->crl->pkcs11ID) ) | 3022 (b->crl->pkcs11ID == a->crl->pkcs11ID)) { |
3347 { | |
3348 /* ASN.1 DER needs to match for dupe check */ | 3023 /* ASN.1 DER needs to match for dupe check */ |
3349 /* could optimize by just checking a few fields like thisUpdate */ | 3024 /* could optimize by just checking a few fields like thisUpdate */ |
3350 if ( SECEqual == SECITEM_CompareItem(b->crl->derCrl, | 3025 if (SECEqual == |
3351 a->crl->derCrl) ) | 3026 SECITEM_CompareItem(b->crl->derCrl, a->crl->derCrl)) { |
3352 { | |
3353 *isDupe = PR_TRUE; | 3027 *isDupe = PR_TRUE; |
3354 } | 3028 } else { |
3355 else | |
3356 { | |
3357 *isUpdated = PR_TRUE; | 3029 *isUpdated = PR_TRUE; |
3358 } | 3030 } |
3359 } | 3031 } |
3360 return SECSuccess; | 3032 return SECSuccess; |
3361 } | 3033 } |
3362 if (CRL_OriginExplicit == b->origin) | 3034 if (CRL_OriginExplicit == b->origin) { |
3363 { | |
3364 /* We need to make sure this is the same object that the user provided | 3035 /* We need to make sure this is the same object that the user provided |
3365 to CERT_CacheCRL previously. That API takes a SECItem*, thus, we | 3036 to CERT_CacheCRL previously. That API takes a SECItem*, thus, we |
3366 just do a pointer comparison here. | 3037 just do a pointer comparison here. |
3367 */ | 3038 */ |
3368 if (b->crl->derCrl == a->crl->derCrl) | 3039 if (b->crl->derCrl == a->crl->derCrl) { |
3369 { | |
3370 *isDupe = PR_TRUE; | 3040 *isDupe = PR_TRUE; |
3371 } | 3041 } |
3372 } | 3042 } |
3373 return SECSuccess; | 3043 return SECSuccess; |
3374 } | 3044 } |
OLD | NEW |