Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/certdb/stanpcertdb.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 #include "prtime.h" | |
6 | |
7 #include "cert.h" | |
8 #include "certi.h" | |
9 #include "certdb.h" | |
10 #include "secitem.h" | |
11 #include "secder.h" | |
12 | |
13 /* Call to PK11_FreeSlot below */ | |
14 | |
15 #include "secasn1.h" | |
16 #include "secerr.h" | |
17 #include "nssilock.h" | |
18 #include "prmon.h" | |
19 #include "base64.h" | |
20 #include "sechash.h" | |
21 #include "plhash.h" | |
22 #include "pk11func.h" /* sigh */ | |
23 | |
24 #include "nsspki.h" | |
25 #include "pki.h" | |
26 #include "pkim.h" | |
27 #include "pki3hack.h" | |
28 #include "ckhelper.h" | |
29 #include "base.h" | |
30 #include "pkistore.h" | |
31 #include "dev3hack.h" | |
32 #include "dev.h" | |
33 | |
34 PRBool | |
35 SEC_CertNicknameConflict(const char *nickname, const SECItem *derSubject, | |
36 CERTCertDBHandle *handle) | |
37 { | |
38 CERTCertificate *cert; | |
39 PRBool conflict = PR_FALSE; | |
40 | |
41 cert=CERT_FindCertByNickname(handle, nickname); | |
42 | |
43 if (!cert) { | |
44 return conflict; | |
45 } | |
46 | |
47 conflict = !SECITEM_ItemsAreEqual(derSubject,&cert->derSubject); | |
48 CERT_DestroyCertificate(cert); | |
49 return conflict; | |
50 } | |
51 | |
52 SECStatus | |
53 SEC_DeletePermCertificate(CERTCertificate *cert) | |
54 { | |
55 PRStatus nssrv; | |
56 NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); | |
57 NSSCertificate *c = STAN_GetNSSCertificate(cert); | |
58 CERTCertTrust *certTrust; | |
59 | |
60 if (c == NULL) { | |
61 /* error code is set */ | |
62 return SECFailure; | |
63 } | |
64 | |
65 certTrust = nssTrust_GetCERTCertTrustForCert(c, cert); | |
66 if (certTrust) { | |
67 NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c); | |
68 if (nssTrust) { | |
69 nssrv = STAN_DeleteCertTrustMatchingSlot(c); | |
70 if (nssrv != PR_SUCCESS) { | |
71 CERT_MapStanError(); | |
72 } | |
73 /* This call always returns PR_SUCCESS! */ | |
74 (void) nssTrust_Destroy(nssTrust); | |
75 } | |
76 } | |
77 | |
78 /* get rid of the token instances */ | |
79 nssrv = NSSCertificate_DeleteStoredObject(c, NULL); | |
80 | |
81 /* get rid of the cache entry */ | |
82 nssTrustDomain_LockCertCache(td); | |
83 nssTrustDomain_RemoveCertFromCacheLOCKED(td, c); | |
84 nssTrustDomain_UnlockCertCache(td); | |
85 | |
86 return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; | |
87 } | |
88 | |
89 SECStatus | |
90 CERT_GetCertTrust(const CERTCertificate *cert, CERTCertTrust *trust) | |
91 { | |
92 SECStatus rv; | |
93 CERT_LockCertTrust(cert); | |
94 if ( cert->trust == NULL ) { | |
95 rv = SECFailure; | |
96 } else { | |
97 *trust = *cert->trust; | |
98 rv = SECSuccess; | |
99 } | |
100 CERT_UnlockCertTrust(cert); | |
101 return(rv); | |
102 } | |
103 | |
104 extern const NSSError NSS_ERROR_NO_ERROR; | |
105 extern const NSSError NSS_ERROR_INTERNAL_ERROR; | |
106 extern const NSSError NSS_ERROR_NO_MEMORY; | |
107 extern const NSSError NSS_ERROR_INVALID_POINTER; | |
108 extern const NSSError NSS_ERROR_INVALID_ARENA; | |
109 extern const NSSError NSS_ERROR_INVALID_ARENA_MARK; | |
110 extern const NSSError NSS_ERROR_DUPLICATE_POINTER; | |
111 extern const NSSError NSS_ERROR_POINTER_NOT_REGISTERED; | |
112 extern const NSSError NSS_ERROR_TRACKER_NOT_EMPTY; | |
113 extern const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED; | |
114 extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD; | |
115 extern const NSSError NSS_ERROR_VALUE_TOO_LARGE; | |
116 extern const NSSError NSS_ERROR_UNSUPPORTED_TYPE; | |
117 extern const NSSError NSS_ERROR_BUFFER_TOO_SHORT; | |
118 extern const NSSError NSS_ERROR_INVALID_ATOB_CONTEXT; | |
119 extern const NSSError NSS_ERROR_INVALID_BASE64; | |
120 extern const NSSError NSS_ERROR_INVALID_BTOA_CONTEXT; | |
121 extern const NSSError NSS_ERROR_INVALID_ITEM; | |
122 extern const NSSError NSS_ERROR_INVALID_STRING; | |
123 extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER; | |
124 extern const NSSError NSS_ERROR_INVALID_ASN1DECODER; | |
125 extern const NSSError NSS_ERROR_INVALID_BER; | |
126 extern const NSSError NSS_ERROR_INVALID_ATAV; | |
127 extern const NSSError NSS_ERROR_INVALID_ARGUMENT; | |
128 extern const NSSError NSS_ERROR_INVALID_UTF8; | |
129 extern const NSSError NSS_ERROR_INVALID_NSSOID; | |
130 extern const NSSError NSS_ERROR_UNKNOWN_ATTRIBUTE; | |
131 extern const NSSError NSS_ERROR_NOT_FOUND; | |
132 extern const NSSError NSS_ERROR_INVALID_PASSWORD; | |
133 extern const NSSError NSS_ERROR_USER_CANCELED; | |
134 extern const NSSError NSS_ERROR_MAXIMUM_FOUND; | |
135 extern const NSSError NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND; | |
136 extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE; | |
137 extern const NSSError NSS_ERROR_HASH_COLLISION; | |
138 extern const NSSError NSS_ERROR_DEVICE_ERROR; | |
139 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; | |
140 extern const NSSError NSS_ERROR_BUSY; | |
141 extern const NSSError NSS_ERROR_ALREADY_INITIALIZED; | |
142 extern const NSSError NSS_ERROR_PKCS11; | |
143 | |
144 | |
145 /* Look at the stan error stack and map it to NSS 3 errors */ | |
146 #define STAN_MAP_ERROR(x,y) \ | |
147 else if (error == (x)) { \ | |
148 secError = y; \ | |
149 } \ | |
150 | |
151 /* | |
152 * map Stan errors into NSS errors | |
153 * This function examines the stan error stack and automatically sets | |
154 * PORT_SetError(); to the appropriate SEC_ERROR value. | |
155 */ | |
156 void | |
157 CERT_MapStanError() | |
158 { | |
159 PRInt32 *errorStack; | |
160 NSSError error, prevError; | |
161 int secError; | |
162 int i; | |
163 | |
164 error = 0; | |
165 | |
166 errorStack = NSS_GetErrorStack(); | |
167 if (errorStack == 0) { | |
168 PORT_SetError(0); | |
169 return; | |
170 } | |
171 error = prevError = CKR_GENERAL_ERROR; | |
172 /* get the 'top 2' error codes from the stack */ | |
173 for (i=0; errorStack[i]; i++) { | |
174 prevError = error; | |
175 error = errorStack[i]; | |
176 } | |
177 if (error == NSS_ERROR_PKCS11) { | |
178 /* map it */ | |
179 secError = PK11_MapError(prevError); | |
180 } | |
181 STAN_MAP_ERROR(NSS_ERROR_NO_ERROR, 0) | |
182 STAN_MAP_ERROR(NSS_ERROR_NO_MEMORY, SEC_ERROR_NO_MEMORY) | |
183 STAN_MAP_ERROR(NSS_ERROR_INVALID_BASE64, SEC_ERROR_BAD_DATA) | |
184 STAN_MAP_ERROR(NSS_ERROR_INVALID_BER, SEC_ERROR_BAD_DER) | |
185 STAN_MAP_ERROR(NSS_ERROR_INVALID_ATAV, SEC_ERROR_INVALID_AVA) | |
186 STAN_MAP_ERROR(NSS_ERROR_INVALID_PASSWORD,SEC_ERROR_BAD_PASSWORD) | |
187 STAN_MAP_ERROR(NSS_ERROR_BUSY, SEC_ERROR_BUSY) | |
188 STAN_MAP_ERROR(NSS_ERROR_DEVICE_ERROR, SEC_ERROR_IO) | |
189 STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND, | |
190 SEC_ERROR_UNKNOWN_ISSUER) | |
191 STAN_MAP_ERROR(NSS_ERROR_INVALID_CERTIFICATE, SEC_ERROR_CERT_NOT_VALID) | |
192 STAN_MAP_ERROR(NSS_ERROR_INVALID_UTF8, SEC_ERROR_BAD_DATA) | |
193 STAN_MAP_ERROR(NSS_ERROR_INVALID_NSSOID, SEC_ERROR_BAD_DATA) | |
194 | |
195 /* these are library failure for lack of a better error code */ | |
196 STAN_MAP_ERROR(NSS_ERROR_NOT_FOUND, SEC_ERROR_LIBRARY_FAILURE) | |
197 STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_IN_CACHE, | |
198 SEC_ERROR_LIBRARY_FAILURE) | |
199 STAN_MAP_ERROR(NSS_ERROR_MAXIMUM_FOUND, SEC_ERROR_LIBRARY_FAILURE) | |
200 STAN_MAP_ERROR(NSS_ERROR_USER_CANCELED, SEC_ERROR_LIBRARY_FAILURE) | |
201 STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_INITIALIZED, | |
202 SEC_ERROR_LIBRARY_FAILURE) | |
203 STAN_MAP_ERROR(NSS_ERROR_ALREADY_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE) | |
204 STAN_MAP_ERROR(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD, | |
205 SEC_ERROR_LIBRARY_FAILURE) | |
206 STAN_MAP_ERROR(NSS_ERROR_HASH_COLLISION, SEC_ERROR_LIBRARY_FAILURE) | |
207 | |
208 STAN_MAP_ERROR(NSS_ERROR_INTERNAL_ERROR, SEC_ERROR_LIBRARY_FAILURE) | |
209 | |
210 /* these are all invalid arguments */ | |
211 STAN_MAP_ERROR(NSS_ERROR_INVALID_ARGUMENT, SEC_ERROR_INVALID_ARGS) | |
212 STAN_MAP_ERROR(NSS_ERROR_INVALID_POINTER, SEC_ERROR_INVALID_ARGS) | |
213 STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA, SEC_ERROR_INVALID_ARGS) | |
214 STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA_MARK, SEC_ERROR_INVALID_ARGS) | |
215 STAN_MAP_ERROR(NSS_ERROR_DUPLICATE_POINTER, SEC_ERROR_INVALID_ARGS) | |
216 STAN_MAP_ERROR(NSS_ERROR_POINTER_NOT_REGISTERED, SEC_ERROR_INVALID_ARGS) | |
217 STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_EMPTY, SEC_ERROR_INVALID_ARGS) | |
218 STAN_MAP_ERROR(NSS_ERROR_VALUE_TOO_LARGE, SEC_ERROR_INVALID_ARGS) | |
219 STAN_MAP_ERROR(NSS_ERROR_UNSUPPORTED_TYPE, SEC_ERROR_INVALID_ARGS) | |
220 STAN_MAP_ERROR(NSS_ERROR_BUFFER_TOO_SHORT, SEC_ERROR_INVALID_ARGS) | |
221 STAN_MAP_ERROR(NSS_ERROR_INVALID_ATOB_CONTEXT, SEC_ERROR_INVALID_ARGS) | |
222 STAN_MAP_ERROR(NSS_ERROR_INVALID_BTOA_CONTEXT, SEC_ERROR_INVALID_ARGS) | |
223 STAN_MAP_ERROR(NSS_ERROR_INVALID_ITEM, SEC_ERROR_INVALID_ARGS) | |
224 STAN_MAP_ERROR(NSS_ERROR_INVALID_STRING, SEC_ERROR_INVALID_ARGS) | |
225 STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1ENCODER, SEC_ERROR_INVALID_ARGS) | |
226 STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1DECODER, SEC_ERROR_INVALID_ARGS) | |
227 STAN_MAP_ERROR(NSS_ERROR_UNKNOWN_ATTRIBUTE, SEC_ERROR_INVALID_ARGS) | |
228 else { | |
229 secError = SEC_ERROR_LIBRARY_FAILURE; | |
230 } | |
231 PORT_SetError(secError); | |
232 } | |
233 | |
234 | |
235 | |
236 SECStatus | |
237 CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert, | |
238 CERTCertTrust *trust) | |
239 { | |
240 SECStatus rv = SECSuccess; | |
241 PRStatus ret; | |
242 | |
243 ret = STAN_ChangeCertTrust(cert, trust); | |
244 if (ret != PR_SUCCESS) { | |
245 rv = SECFailure; | |
246 CERT_MapStanError(); | |
247 } | |
248 return rv; | |
249 } | |
250 | |
251 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; | |
252 | |
253 SECStatus | |
254 __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, | |
255 CERTCertTrust *trust) | |
256 { | |
257 NSSUTF8 *stanNick; | |
258 PK11SlotInfo *slot; | |
259 NSSToken *internal; | |
260 NSSCryptoContext *context; | |
261 nssCryptokiObject *permInstance; | |
262 NSSCertificate *c = STAN_GetNSSCertificate(cert); | |
263 nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; | |
264 nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; | |
265 SECStatus rv; | |
266 PRStatus ret; | |
267 | |
268 if (c == NULL) { | |
269 CERT_MapStanError(); | |
270 return SECFailure; | |
271 } | |
272 | |
273 context = c->object.cryptoContext; | |
274 if (!context) { | |
275 PORT_SetError(SEC_ERROR_ADDING_CERT); | |
276 return SECFailure; /* wasn't a temp cert */ | |
277 } | |
278 stanNick = nssCertificate_GetNickname(c, NULL); | |
279 if (stanNick && nickname && strcmp(nickname, stanNick) != 0) { | |
280 /* different: take the new nickname */ | |
281 cert->nickname = NULL; | |
282 nss_ZFreeIf(stanNick); | |
283 stanNick = NULL; | |
284 } | |
285 if (!stanNick && nickname) { | |
286 /* Either there was no nickname yet, or we have a new nickname */ | |
287 stanNick = nssUTF8_Duplicate((NSSUTF8 *)nickname, NULL); | |
288 } /* else: old stanNick is identical to new nickname */ | |
289 /* Delete the temp instance */ | |
290 nssCertificateStore_Lock(context->certStore, &lockTrace); | |
291 nssCertificateStore_RemoveCertLOCKED(context->certStore, c); | |
292 nssCertificateStore_Unlock(context->certStore, &lockTrace, &unlockTrace); | |
293 c->object.cryptoContext = NULL; | |
294 /* Import the perm instance onto the internal token */ | |
295 slot = PK11_GetInternalKeySlot(); | |
296 internal = PK11Slot_GetNSSToken(slot); | |
297 permInstance = nssToken_ImportCertificate(internal, NULL, | |
298 NSSCertificateType_PKIX, | |
299 &c->id, | |
300 stanNick, | |
301 &c->encoding, | |
302 &c->issuer, | |
303 &c->subject, | |
304 &c->serial, | |
305 cert->emailAddr, | |
306 PR_TRUE); | |
307 nss_ZFreeIf(stanNick); | |
308 stanNick = NULL; | |
309 PK11_FreeSlot(slot); | |
310 if (!permInstance) { | |
311 if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) { | |
312 PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); | |
313 } | |
314 return SECFailure; | |
315 } | |
316 nssPKIObject_AddInstance(&c->object, permInstance); | |
317 nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1); | |
318 /* reset the CERTCertificate fields */ | |
319 cert->nssCertificate = NULL; | |
320 cert = STAN_GetCERTCertificateOrRelease(c); /* should return same pointer */ | |
321 if (!cert) { | |
322 CERT_MapStanError(); | |
323 return SECFailure; | |
324 } | |
325 cert->istemp = PR_FALSE; | |
326 cert->isperm = PR_TRUE; | |
327 if (!trust) { | |
328 return SECSuccess; | |
329 } | |
330 ret = STAN_ChangeCertTrust(cert, trust); | |
331 rv = SECSuccess; | |
332 if (ret != PR_SUCCESS) { | |
333 rv = SECFailure; | |
334 CERT_MapStanError(); | |
335 } | |
336 return rv; | |
337 } | |
338 | |
339 SECStatus | |
340 CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, | |
341 CERTCertTrust *trust) | |
342 { | |
343 return __CERT_AddTempCertToPerm(cert, nickname, trust); | |
344 } | |
345 | |
346 CERTCertificate * | |
347 CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, | |
348 char *nickname, PRBool isperm, PRBool copyDER) | |
349 { | |
350 NSSCertificate *c; | |
351 CERTCertificate *cc; | |
352 NSSCertificate *tempCert = NULL; | |
353 nssPKIObject *pkio; | |
354 NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext(); | |
355 NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain(); | |
356 if (!isperm) { | |
357 NSSDER encoding; | |
358 NSSITEM_FROM_SECITEM(&encoding, derCert); | |
359 /* First, see if it is already a temp cert */ | |
360 c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC, | |
361 &encoding); | |
362 if (!c) { | |
363 /* Then, see if it is already a perm cert */ | |
364 c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, | |
365 &encoding); | |
366 } | |
367 if (c) { | |
368 /* actually, that search ends up going by issuer/serial, | |
369 * so it is still possible to return a cert with the same | |
370 * issuer/serial but a different encoding, and we're | |
371 * going to reject that | |
372 */ | |
373 if (!nssItem_Equal(&c->encoding, &encoding, NULL)) { | |
374 nssCertificate_Destroy(c); | |
375 PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); | |
376 cc = NULL; | |
377 } else { | |
378 cc = STAN_GetCERTCertificateOrRelease(c); | |
379 if (cc == NULL) { | |
380 CERT_MapStanError(); | |
381 } | |
382 } | |
383 return cc; | |
384 } | |
385 } | |
386 pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor); | |
387 if (!pkio) { | |
388 CERT_MapStanError(); | |
389 return NULL; | |
390 } | |
391 c = nss_ZNEW(pkio->arena, NSSCertificate); | |
392 if (!c) { | |
393 CERT_MapStanError(); | |
394 nssPKIObject_Destroy(pkio); | |
395 return NULL; | |
396 } | |
397 c->object = *pkio; | |
398 if (copyDER) { | |
399 nssItem_Create(c->object.arena, &c->encoding, | |
400 derCert->len, derCert->data); | |
401 } else { | |
402 NSSITEM_FROM_SECITEM(&c->encoding, derCert); | |
403 } | |
404 /* Forces a decoding of the cert in order to obtain the parts used | |
405 * below | |
406 */ | |
407 /* 'c' is not adopted here, if we fail loser frees what has been | |
408 * allocated so far for 'c' */ | |
409 cc = STAN_GetCERTCertificate(c); | |
410 if (!cc) { | |
411 CERT_MapStanError(); | |
412 goto loser; | |
413 } | |
414 nssItem_Create(c->object.arena, | |
415 &c->issuer, cc->derIssuer.len, cc->derIssuer.data); | |
416 nssItem_Create(c->object.arena, | |
417 &c->subject, cc->derSubject.len, cc->derSubject.data); | |
418 if (PR_TRUE) { | |
419 /* CERTCertificate stores serial numbers decoded. I need the DER | |
420 * here. sigh. | |
421 */ | |
422 SECItem derSerial = { 0 }; | |
423 CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial); | |
424 if (!derSerial.data) goto loser; | |
425 nssItem_Create(c->object.arena, &c->serial, derSerial.len, derSerial.data); | |
426 PORT_Free(derSerial.data); | |
427 } | |
428 if (nickname) { | |
429 c->object.tempName = nssUTF8_Create(c->object.arena, | |
430 nssStringType_UTF8String, | |
431 (NSSUTF8 *)nickname, | |
432 PORT_Strlen(nickname)); | |
433 } | |
434 if (cc->emailAddr && cc->emailAddr[0]) { | |
435 c->email = nssUTF8_Create(c->object.arena, | |
436 nssStringType_PrintableString, | |
437 (NSSUTF8 *)cc->emailAddr, | |
438 PORT_Strlen(cc->emailAddr)); | |
439 } | |
440 | |
441 tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c); | |
442 if (!tempCert) { | |
443 CERT_MapStanError(); | |
444 goto loser; | |
445 } | |
446 /* destroy our copy */ | |
447 NSSCertificate_Destroy(c); | |
448 /* and use the stored entry */ | |
449 c = tempCert; | |
450 cc = STAN_GetCERTCertificateOrRelease(c); | |
451 if (!cc) { | |
452 /* STAN_GetCERTCertificateOrRelease destroys c on failure. */ | |
453 CERT_MapStanError(); | |
454 return NULL; | |
455 } | |
456 | |
457 cc->istemp = PR_TRUE; | |
458 cc->isperm = PR_FALSE; | |
459 return cc; | |
460 loser: | |
461 /* Perhaps this should be nssCertificate_Destroy(c) */ | |
462 nssPKIObject_Destroy(&c->object); | |
463 return NULL; | |
464 } | |
465 | |
466 /* This symbol is exported for backward compatibility. */ | |
467 CERTCertificate * | |
468 __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, | |
469 char *nickname, PRBool isperm, PRBool copyDER) | |
470 { | |
471 return CERT_NewTempCertificate(handle, derCert, nickname, | |
472 isperm, copyDER); | |
473 } | |
474 | |
475 /* maybe all the wincx's should be some const for internal token login? */ | |
476 CERTCertificate * | |
477 CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN) | |
478 { | |
479 PK11SlotInfo *slot; | |
480 CERTCertificate *cert; | |
481 | |
482 cert = PK11_FindCertByIssuerAndSN(&slot,issuerAndSN,NULL); | |
483 if (cert && slot) { | |
484 PK11_FreeSlot(slot); | |
485 } | |
486 | |
487 return cert; | |
488 } | |
489 | |
490 static NSSCertificate * | |
491 get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp) | |
492 { | |
493 NSSUsage usage; | |
494 NSSCertificate *arr[3]; | |
495 if (!ct) { | |
496 return nssCertificate_AddRef(cp); | |
497 } else if (!cp) { | |
498 return nssCertificate_AddRef(ct); | |
499 } | |
500 arr[0] = ct; | |
501 arr[1] = cp; | |
502 arr[2] = NULL; | |
503 usage.anyUsage = PR_TRUE; | |
504 return nssCertificateArray_FindBestCertificate(arr, NULL, &usage, NULL); | |
505 } | |
506 | |
507 CERTCertificate * | |
508 CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name) | |
509 { | |
510 NSSCertificate *cp, *ct, *c; | |
511 NSSDER subject; | |
512 NSSUsage usage; | |
513 NSSCryptoContext *cc; | |
514 NSSITEM_FROM_SECITEM(&subject, name); | |
515 usage.anyUsage = PR_TRUE; | |
516 cc = STAN_GetDefaultCryptoContext(); | |
517 ct = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject, | |
518 NULL, &usage, NULL); | |
519 cp = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject, | |
520 NULL, &usage, NULL); | |
521 c = get_best_temp_or_perm(ct, cp); | |
522 if (ct) { | |
523 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); | |
524 } | |
525 if (cp) { | |
526 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(cp)); | |
527 } | |
528 return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; | |
529 } | |
530 | |
531 CERTCertificate * | |
532 CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID) | |
533 { | |
534 CERTCertList *list; | |
535 CERTCertificate *cert = NULL; | |
536 CERTCertListNode *node, *head; | |
537 | |
538 list = CERT_CreateSubjectCertList(NULL,handle,name,0,PR_FALSE); | |
539 if (list == NULL) return NULL; | |
540 | |
541 node = head = CERT_LIST_HEAD(list); | |
542 if (head) { | |
543 do { | |
544 if (node->cert && | |
545 SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID) ) { | |
546 cert = CERT_DupCertificate(node->cert); | |
547 goto done; | |
548 } | |
549 node = CERT_LIST_NEXT(node); | |
550 } while (node && head != node); | |
551 } | |
552 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); | |
553 done: | |
554 if (list) { | |
555 CERT_DestroyCertList(list); | |
556 } | |
557 return cert; | |
558 } | |
559 | |
560 CERTCertificate * | |
561 CERT_FindCertByNickname(CERTCertDBHandle *handle, const char *nickname) | |
562 { | |
563 NSSCryptoContext *cc; | |
564 NSSCertificate *c, *ct; | |
565 CERTCertificate *cert; | |
566 NSSUsage usage; | |
567 usage.anyUsage = PR_TRUE; | |
568 cc = STAN_GetDefaultCryptoContext(); | |
569 ct = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname, | |
570 NULL, &usage, NULL); | |
571 cert = PK11_FindCertFromNickname(nickname, NULL); | |
572 c = NULL; | |
573 if (cert) { | |
574 c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); | |
575 CERT_DestroyCertificate(cert); | |
576 if (ct) { | |
577 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); | |
578 } | |
579 } else { | |
580 c = ct; | |
581 } | |
582 return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; | |
583 } | |
584 | |
585 CERTCertificate * | |
586 CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert) | |
587 { | |
588 NSSCryptoContext *cc; | |
589 NSSCertificate *c; | |
590 NSSDER encoding; | |
591 NSSITEM_FROM_SECITEM(&encoding, derCert); | |
592 cc = STAN_GetDefaultCryptoContext(); | |
593 c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding); | |
594 if (!c) { | |
595 c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, | |
596 &encoding); | |
597 if (!c) return NULL; | |
598 } | |
599 return STAN_GetCERTCertificateOrRelease(c); | |
600 } | |
601 | |
602 static CERTCertificate * | |
603 common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, | |
604 const char *name, | |
605 PRBool anyUsage, | |
606 SECCertUsage lookingForUsage) | |
607 { | |
608 NSSCryptoContext *cc; | |
609 NSSCertificate *c, *ct; | |
610 CERTCertificate *cert = NULL; | |
611 NSSUsage usage; | |
612 CERTCertList *certlist; | |
613 | |
614 if (NULL == name) { | |
615 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
616 return NULL; | |
617 } | |
618 | |
619 usage.anyUsage = anyUsage; | |
620 | |
621 if (!anyUsage) { | |
622 usage.nss3lookingForCA = PR_FALSE; | |
623 usage.nss3usage = lookingForUsage; | |
624 } | |
625 | |
626 cc = STAN_GetDefaultCryptoContext(); | |
627 ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, | |
628 NULL, &usage, NULL); | |
629 if (!ct && PORT_Strchr(name, '@') != NULL) { | |
630 char* lowercaseName = CERT_FixupEmailAddr(name); | |
631 if (lowercaseName) { | |
632 ct = NSSCryptoContext_FindBestCertificateByEmail(cc, lowercaseName, | |
633 NULL, &usage, NULL); | |
634 PORT_Free(lowercaseName); | |
635 } | |
636 } | |
637 | |
638 if (anyUsage) { | |
639 cert = PK11_FindCertFromNickname(name, NULL); | |
640 } | |
641 else { | |
642 if (ct) { | |
643 /* Does ct really have the required usage? */ | |
644 nssDecodedCert *dc; | |
645 dc = nssCertificate_GetDecoding(ct); | |
646 if (!dc->matchUsage(dc, &usage)) { | |
647 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); | |
648 ct = NULL; | |
649 } | |
650 } | |
651 | |
652 certlist = PK11_FindCertsFromNickname(name, NULL); | |
653 if (certlist) { | |
654 SECStatus rv = CERT_FilterCertListByUsage(certlist, | |
655 lookingForUsage, | |
656 PR_FALSE); | |
657 if (SECSuccess == rv && | |
658 !CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist)) { | |
659 cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert); | |
660 } | |
661 CERT_DestroyCertList(certlist); | |
662 } | |
663 } | |
664 | |
665 if (cert) { | |
666 c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert)); | |
667 CERT_DestroyCertificate(cert); | |
668 if (ct) { | |
669 CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct)); | |
670 } | |
671 } else { | |
672 c = ct; | |
673 } | |
674 return c ? STAN_GetCERTCertificateOrRelease(c) : NULL; | |
675 } | |
676 | |
677 CERTCertificate * | |
678 CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name) | |
679 { | |
680 return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, | |
681 PR_TRUE, 0); | |
682 } | |
683 | |
684 CERTCertificate * | |
685 CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle, | |
686 const char *name, | |
687 SECCertUsage lookingForUsage) | |
688 { | |
689 return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, | |
690 PR_FALSE, | |
691 lookingForUsage); | |
692 } | |
693 | |
694 static void | |
695 add_to_subject_list(CERTCertList *certList, CERTCertificate *cert, | |
696 PRBool validOnly, PRTime sorttime) | |
697 { | |
698 SECStatus secrv; | |
699 if (!validOnly || | |
700 CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE) | |
701 == secCertTimeValid) { | |
702 secrv = CERT_AddCertToListSorted(certList, cert, | |
703 CERT_SortCBValidity, | |
704 (void *)&sorttime); | |
705 if (secrv != SECSuccess) { | |
706 CERT_DestroyCertificate(cert); | |
707 } | |
708 } else { | |
709 CERT_DestroyCertificate(cert); | |
710 } | |
711 } | |
712 | |
713 CERTCertList * | |
714 CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle, | |
715 const SECItem *name, PRTime sorttime, | |
716 PRBool validOnly) | |
717 { | |
718 NSSCryptoContext *cc; | |
719 NSSCertificate **tSubjectCerts, **pSubjectCerts; | |
720 NSSCertificate **ci; | |
721 CERTCertificate *cert; | |
722 NSSDER subject; | |
723 PRBool myList = PR_FALSE; | |
724 cc = STAN_GetDefaultCryptoContext(); | |
725 NSSITEM_FROM_SECITEM(&subject, name); | |
726 /* Collect both temp and perm certs for the subject */ | |
727 tSubjectCerts = NSSCryptoContext_FindCertificatesBySubject(cc, | |
728 &subject, | |
729 NULL, | |
730 0, | |
731 NULL); | |
732 pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle, | |
733 &subject, | |
734 NULL, | |
735 0, | |
736 NULL); | |
737 if (!tSubjectCerts && !pSubjectCerts) { | |
738 return NULL; | |
739 } | |
740 if (certList == NULL) { | |
741 certList = CERT_NewCertList(); | |
742 myList = PR_TRUE; | |
743 if (!certList) goto loser; | |
744 } | |
745 /* Iterate over the matching temp certs. Add them to the list */ | |
746 ci = tSubjectCerts; | |
747 while (ci && *ci) { | |
748 cert = STAN_GetCERTCertificateOrRelease(*ci); | |
749 /* *ci may be invalid at this point, don't reference it again */ | |
750 if (cert) { | |
751 /* NOTE: add_to_subject_list adopts the incoming cert. */ | |
752 add_to_subject_list(certList, cert, validOnly, sorttime); | |
753 } | |
754 ci++; | |
755 } | |
756 /* Iterate over the matching perm certs. Add them to the list */ | |
757 ci = pSubjectCerts; | |
758 while (ci && *ci) { | |
759 cert = STAN_GetCERTCertificateOrRelease(*ci); | |
760 /* *ci may be invalid at this point, don't reference it again */ | |
761 if (cert) { | |
762 /* NOTE: add_to_subject_list adopts the incoming cert. */ | |
763 add_to_subject_list(certList, cert, validOnly, sorttime); | |
764 } | |
765 ci++; | |
766 } | |
767 /* all the references have been adopted or freed at this point, just | |
768 * free the arrays now */ | |
769 nss_ZFreeIf(tSubjectCerts); | |
770 nss_ZFreeIf(pSubjectCerts); | |
771 return certList; | |
772 loser: | |
773 /* need to free the references in tSubjectCerts and pSubjectCerts! */ | |
774 nssCertificateArray_Destroy(tSubjectCerts); | |
775 nssCertificateArray_Destroy(pSubjectCerts); | |
776 if (myList && certList != NULL) { | |
777 CERT_DestroyCertList(certList); | |
778 } | |
779 return NULL; | |
780 } | |
781 | |
782 void | |
783 CERT_DestroyCertificate(CERTCertificate *cert) | |
784 { | |
785 if ( cert ) { | |
786 /* don't use STAN_GetNSSCertificate because we don't want to | |
787 * go to the trouble of translating the CERTCertificate into | |
788 * an NSSCertificate just to destroy it. If it hasn't been done | |
789 * yet, don't do it at all. | |
790 */ | |
791 NSSCertificate *tmp = cert->nssCertificate; | |
792 if (tmp) { | |
793 /* delete the NSSCertificate */ | |
794 NSSCertificate_Destroy(tmp); | |
795 } else if (cert->arena) { | |
796 PORT_FreeArena(cert->arena, PR_FALSE); | |
797 } | |
798 } | |
799 return; | |
800 } | |
801 | |
802 int | |
803 CERT_GetDBContentVersion(CERTCertDBHandle *handle) | |
804 { | |
805 /* should read the DB content version from the pkcs #11 device */ | |
806 return 0; | |
807 } | |
808 | |
809 SECStatus | |
810 certdb_SaveSingleProfile(CERTCertificate *cert, const char *emailAddr, | |
811 SECItem *emailProfile, SECItem *profileTime) | |
812 { | |
813 PRTime oldtime; | |
814 PRTime newtime; | |
815 SECStatus rv = SECFailure; | |
816 PRBool saveit; | |
817 SECItem oldprof, oldproftime; | |
818 SECItem *oldProfile = NULL; | |
819 SECItem *oldProfileTime = NULL; | |
820 PK11SlotInfo *slot = NULL; | |
821 NSSCertificate *c; | |
822 NSSCryptoContext *cc; | |
823 nssSMIMEProfile *stanProfile = NULL; | |
824 PRBool freeOldProfile = PR_FALSE; | |
825 | |
826 c = STAN_GetNSSCertificate(cert); | |
827 if (!c) return SECFailure; | |
828 cc = c->object.cryptoContext; | |
829 if (cc != NULL) { | |
830 stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c); | |
831 if (stanProfile) { | |
832 PORT_Assert(stanProfile->profileData); | |
833 SECITEM_FROM_NSSITEM(&oldprof, stanProfile->profileData); | |
834 oldProfile = &oldprof; | |
835 SECITEM_FROM_NSSITEM(&oldproftime, stanProfile->profileTime); | |
836 oldProfileTime = &oldproftime; | |
837 } | |
838 } else { | |
839 oldProfile = PK11_FindSMimeProfile(&slot, (char *)emailAddr, | |
840 &cert->derSubject, &oldProfileTime); | |
841 freeOldProfile = PR_TRUE; | |
842 } | |
843 | |
844 saveit = PR_FALSE; | |
845 | |
846 /* both profileTime and emailProfile have to exist or not exist */ | |
847 if ( emailProfile == NULL ) { | |
848 profileTime = NULL; | |
849 } else if ( profileTime == NULL ) { | |
850 emailProfile = NULL; | |
851 } | |
852 | |
853 if ( oldProfileTime == NULL ) { | |
854 saveit = PR_TRUE; | |
855 } else { | |
856 /* there was already a profile for this email addr */ | |
857 if ( profileTime ) { | |
858 /* we have an old and new profile - save whichever is more recent*/ | |
859 if ( oldProfileTime->len == 0 ) { | |
860 /* always replace if old entry doesn't have a time */ | |
861 oldtime = LL_MININT; | |
862 } else { | |
863 rv = DER_UTCTimeToTime(&oldtime, oldProfileTime); | |
864 if ( rv != SECSuccess ) { | |
865 goto loser; | |
866 } | |
867 } | |
868 | |
869 rv = DER_UTCTimeToTime(&newtime, profileTime); | |
870 if ( rv != SECSuccess ) { | |
871 goto loser; | |
872 } | |
873 | |
874 if ( LL_CMP(newtime, >, oldtime ) ) { | |
875 /* this is a newer profile, save it and cert */ | |
876 saveit = PR_TRUE; | |
877 } | |
878 } else { | |
879 saveit = PR_TRUE; | |
880 } | |
881 } | |
882 | |
883 | |
884 if (saveit) { | |
885 if (cc) { | |
886 if (stanProfile) { | |
887 /* stanProfile is already stored in the crypto context, | |
888 * overwrite the data | |
889 */ | |
890 NSSArena *arena = stanProfile->object.arena; | |
891 stanProfile->profileTime = nssItem_Create(arena, | |
892 NULL, | |
893 profileTime->len, | |
894 profileTime->data); | |
895 stanProfile->profileData = nssItem_Create(arena, | |
896 NULL, | |
897 emailProfile->len, | |
898 emailProfile->data); | |
899 } else if (profileTime && emailProfile) { | |
900 PRStatus nssrv; | |
901 NSSItem profTime, profData; | |
902 NSSITEM_FROM_SECITEM(&profTime, profileTime); | |
903 NSSITEM_FROM_SECITEM(&profData, emailProfile); | |
904 stanProfile = nssSMIMEProfile_Create(c, &profTime, &profData); | |
905 if (!stanProfile) goto loser; | |
906 nssrv = nssCryptoContext_ImportSMIMEProfile(cc, stanProfile); | |
907 rv = (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; | |
908 } | |
909 } else { | |
910 rv = PK11_SaveSMimeProfile(slot, (char *)emailAddr, | |
911 &cert->derSubject, emailProfile, profileTime); | |
912 } | |
913 } else { | |
914 rv = SECSuccess; | |
915 } | |
916 | |
917 loser: | |
918 if (oldProfile && freeOldProfile) { | |
919 SECITEM_FreeItem(oldProfile,PR_TRUE); | |
920 } | |
921 if (oldProfileTime && freeOldProfile) { | |
922 SECITEM_FreeItem(oldProfileTime,PR_TRUE); | |
923 } | |
924 if (stanProfile) { | |
925 nssSMIMEProfile_Destroy(stanProfile); | |
926 } | |
927 if (slot) { | |
928 PK11_FreeSlot(slot); | |
929 } | |
930 | |
931 return(rv); | |
932 } | |
933 | |
934 /* | |
935 * | |
936 * Manage S/MIME profiles | |
937 * | |
938 */ | |
939 | |
940 SECStatus | |
941 CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, | |
942 SECItem *profileTime) | |
943 { | |
944 const char *emailAddr; | |
945 SECStatus rv; | |
946 | |
947 if (!cert) { | |
948 return SECFailure; | |
949 } | |
950 | |
951 if (cert->slot && !PK11_IsInternal(cert->slot)) { | |
952 /* this cert comes from an external source, we need to add it | |
953 to the cert db before creating an S/MIME profile */ | |
954 PK11SlotInfo* internalslot = PK11_GetInternalKeySlot(); | |
955 if (!internalslot) { | |
956 return SECFailure; | |
957 } | |
958 rv = PK11_ImportCert(internalslot, cert, | |
959 CK_INVALID_HANDLE, NULL, PR_FALSE); | |
960 | |
961 PK11_FreeSlot(internalslot); | |
962 if (rv != SECSuccess ) { | |
963 return SECFailure; | |
964 } | |
965 } | |
966 | |
967 if (cert->slot && cert->isperm && CERT_IsUserCert(cert) && | |
968 (!emailProfile || !emailProfile->len)) { | |
969 /* Don't clobber emailProfile for user certs. */ | |
970 return SECSuccess; | |
971 } | |
972 | |
973 for (emailAddr = CERT_GetFirstEmailAddress(cert); emailAddr != NULL; | |
974 emailAddr = CERT_GetNextEmailAddress(cert,emailAddr)) { | |
975 rv = certdb_SaveSingleProfile(cert,emailAddr,emailProfile,profileTime); | |
976 if (rv != SECSuccess) { | |
977 return SECFailure; | |
978 } | |
979 } | |
980 return SECSuccess; | |
981 | |
982 } | |
983 | |
984 | |
985 SECItem * | |
986 CERT_FindSMimeProfile(CERTCertificate *cert) | |
987 { | |
988 PK11SlotInfo *slot = NULL; | |
989 NSSCertificate *c; | |
990 NSSCryptoContext *cc; | |
991 SECItem *rvItem = NULL; | |
992 | |
993 if (!cert || !cert->emailAddr || !cert->emailAddr[0]) { | |
994 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
995 return NULL; | |
996 } | |
997 c = STAN_GetNSSCertificate(cert); | |
998 if (!c) return NULL; | |
999 cc = c->object.cryptoContext; | |
1000 if (cc != NULL) { | |
1001 nssSMIMEProfile *stanProfile; | |
1002 stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c); | |
1003 if (stanProfile) { | |
1004 rvItem = SECITEM_AllocItem(NULL, NULL, | |
1005 stanProfile->profileData->size); | |
1006 if (rvItem) { | |
1007 rvItem->data = stanProfile->profileData->data; | |
1008 } | |
1009 nssSMIMEProfile_Destroy(stanProfile); | |
1010 } | |
1011 return rvItem; | |
1012 } | |
1013 rvItem = | |
1014 PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL); | |
1015 if (slot) { | |
1016 PK11_FreeSlot(slot); | |
1017 } | |
1018 return rvItem; | |
1019 } | |
1020 | |
1021 /* | |
1022 * deprecated functions that are now just stubs. | |
1023 */ | |
1024 /* | |
1025 * Close the database | |
1026 */ | |
1027 void | |
1028 __CERT_ClosePermCertDB(CERTCertDBHandle *handle) | |
1029 { | |
1030 PORT_Assert("CERT_ClosePermCertDB is Deprecated" == NULL); | |
1031 return; | |
1032 } | |
1033 | |
1034 SECStatus | |
1035 CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname, | |
1036 PRBool readOnly) | |
1037 { | |
1038 PORT_Assert("CERT_OpenCertDBFilename is Deprecated" == NULL); | |
1039 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
1040 return SECFailure; | |
1041 } | |
1042 | |
1043 SECItem * | |
1044 SECKEY_HashPassword(char *pw, SECItem *salt) | |
1045 { | |
1046 PORT_Assert("SECKEY_HashPassword is Deprecated" == NULL); | |
1047 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
1048 return NULL; | |
1049 } | |
1050 | |
1051 SECStatus | |
1052 __CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, | |
1053 SECItem *derSubject, | |
1054 void *cb, void *cbarg) | |
1055 { | |
1056 PORT_Assert("CERT_TraversePermCertsForSubject is Deprecated" == NULL); | |
1057 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
1058 return SECFailure; | |
1059 } | |
1060 | |
1061 | |
1062 SECStatus | |
1063 __CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, | |
1064 void *cb, void *cbarg) | |
1065 { | |
1066 PORT_Assert("CERT_TraversePermCertsForNickname is Deprecated" == NULL); | |
1067 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
1068 return SECFailure; | |
1069 } | |
1070 | |
1071 | |
1072 |