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