Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Side by Side Diff: nss/lib/certdb/crl.c

Issue 1843333003: Update NSPR to 4.12 and NSS to 3.23 on iOS (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 }
OLDNEW
« no previous file with comments | « nss/lib/certdb/certxutl.c ('k') | nss/lib/certdb/genname.h » ('j') | nss/lib/util/secoid.c » ('J')

Powered by Google App Engine
This is Rietveld 408576698