comparison nss/lib/certhigh/certhigh.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 #include "nspr.h"
5 #include "secerr.h"
6 #include "secasn1.h"
7 #include "seccomon.h"
8 #include "pk11func.h"
9 #include "certdb.h"
10 #include "certt.h"
11 #include "cert.h"
12 #include "certxutl.h"
13
14 #include "nsspki.h"
15 #include "pki.h"
16 #include "pkit.h"
17 #include "pkitm.h"
18 #include "pki3hack.h"
19
20
21 PRBool
22 CERT_MatchNickname(char *name1, char *name2) {
23 char *nickname1= NULL;
24 char *nickname2 = NULL;
25 char *token1;
26 char *token2;
27 char *token = NULL;
28 int len;
29
30 /* first deal with the straight comparison */
31 if (PORT_Strcmp(name1, name2) == 0) {
32 return PR_TRUE;
33 }
34 /* we need to handle the case where one name has an explicit token and the other
35 * doesn't */
36 token1 = PORT_Strchr(name1,':');
37 token2 = PORT_Strchr(name2,':');
38 if ((token1 && token2) || (!token1 && !token2)) {
39 /* either both token names are specified or neither are, not match */
40 return PR_FALSE;
41 }
42 if (token1) {
43 token=name1;
44 nickname1=token1;
45 nickname2=name2;
46 } else {
47 token=name2;
48 nickname1=token2;
49 nickname2=name1;
50 }
51 len = nickname1-token;
52 nickname1++;
53 if (PORT_Strcmp(nickname1,nickname2) != 0) {
54 return PR_FALSE;
55 }
56 /* compare the other token with the internal slot here */
57 return PR_TRUE;
58 }
59
60 /*
61 * Find all user certificates that match the given criteria.
62 *
63 * "handle" - database to search
64 * "usage" - certificate usage to match
65 * "oneCertPerName" - if set then only return the "best" cert per
66 * name
67 * "validOnly" - only return certs that are curently valid
68 * "proto_win" - window handle passed to pkcs11
69 */
70 CERTCertList *
71 CERT_FindUserCertsByUsage(CERTCertDBHandle *handle,
72 SECCertUsage usage,
73 PRBool oneCertPerName,
74 PRBool validOnly,
75 void *proto_win)
76 {
77 CERTCertNicknames *nicknames = NULL;
78 char **nnptr;
79 int nn;
80 CERTCertificate *cert = NULL;
81 CERTCertList *certList = NULL;
82 SECStatus rv;
83 PRTime time;
84 CERTCertListNode *node = NULL;
85 CERTCertListNode *freenode = NULL;
86 int n;
87
88 time = PR_Now();
89
90 nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER,
91 proto_win);
92
93 if ( ( nicknames == NULL ) || ( nicknames->numnicknames == 0 ) ) {
94 goto loser;
95 }
96
97 nnptr = nicknames->nicknames;
98 nn = nicknames->numnicknames;
99
100 while ( nn > 0 ) {
101 cert = NULL;
102 /* use the pk11 call so that we pick up any certs on tokens,
103 * which may require login
104 */
105 if ( proto_win != NULL ) {
106 cert = PK11_FindCertFromNickname(*nnptr,proto_win);
107 }
108
109 /* Sigh, It turns out if the cert is already in the temp db, because
110 * it's in the perm db, then the nickname lookup doesn't work.
111 * since we already have the cert here, though, than we can just call
112 * CERT_CreateSubjectCertList directly. For those cases where we didn't
113 * find the cert in pkcs #11 (because we didn't have a password arg,
114 * or because the nickname is for a peer, server, or CA cert, then we
115 * go look the cert up.
116 */
117 if (cert == NULL) {
118 cert = CERT_FindCertByNickname(handle,*nnptr);
119 }
120
121 if ( cert != NULL ) {
122 /* collect certs for this nickname, sorting them into the list */
123 certList = CERT_CreateSubjectCertList(certList, handle,
124 &cert->derSubject, time, validOnly);
125
126 CERT_FilterCertListForUserCerts(certList);
127
128 /* drop the extra reference */
129 CERT_DestroyCertificate(cert);
130 }
131
132 nnptr++;
133 nn--;
134 }
135
136 /* remove certs with incorrect usage */
137 rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
138
139 if ( rv != SECSuccess ) {
140 goto loser;
141 }
142
143 /* remove any extra certs for each name */
144 if ( oneCertPerName ) {
145 PRBool *flags;
146
147 nn = nicknames->numnicknames;
148 nnptr = nicknames->nicknames;
149
150 flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn);
151 if ( flags == NULL ) {
152 goto loser;
153 }
154
155 node = CERT_LIST_HEAD(certList);
156
157 /* treverse all certs in the list */
158 while ( !CERT_LIST_END(node, certList) ) {
159
160 /* find matching nickname index */
161 for ( n = 0; n < nn; n++ ) {
162 if ( CERT_MatchNickname(nnptr[n], node->cert->nickname) ) {
163 /* We found a match. If this is the first one, then
164 * set the flag and move on to the next cert. If this
165 * is not the first one then delete it from the list.
166 */
167 if ( flags[n] ) {
168 /* We have already seen a cert with this nickname,
169 * so delete this one.
170 */
171 freenode = node;
172 node = CERT_LIST_NEXT(node);
173 CERT_RemoveCertListNode(freenode);
174 } else {
175 /* keep the first cert for each nickname, but set the
176 * flag so we know to delete any others with the same
177 * nickname.
178 */
179 flags[n] = PR_TRUE;
180 node = CERT_LIST_NEXT(node);
181 }
182 break;
183 }
184 }
185 if ( n == nn ) {
186 /* if we get here it means that we didn't find a matching
187 * nickname, which should not happen.
188 */
189 PORT_Assert(0);
190 node = CERT_LIST_NEXT(node);
191 }
192 }
193 PORT_Free(flags);
194 }
195
196 goto done;
197
198 loser:
199 if ( certList != NULL ) {
200 CERT_DestroyCertList(certList);
201 certList = NULL;
202 }
203
204 done:
205 if ( nicknames != NULL ) {
206 CERT_FreeNicknames(nicknames);
207 }
208
209 return(certList);
210 }
211
212 /*
213 * Find a user certificate that matchs the given criteria.
214 *
215 * "handle" - database to search
216 * "nickname" - nickname to match
217 * "usage" - certificate usage to match
218 * "validOnly" - only return certs that are curently valid
219 * "proto_win" - window handle passed to pkcs11
220 */
221 CERTCertificate *
222 CERT_FindUserCertByUsage(CERTCertDBHandle *handle,
223 const char *nickname,
224 SECCertUsage usage,
225 PRBool validOnly,
226 void *proto_win)
227 {
228 CERTCertificate *cert = NULL;
229 CERTCertList *certList = NULL;
230 SECStatus rv;
231 PRTime time;
232
233 time = PR_Now();
234
235 /* use the pk11 call so that we pick up any certs on tokens,
236 * which may require login
237 */
238 /* XXX - why is this restricted? */
239 if ( proto_win != NULL ) {
240 cert = PK11_FindCertFromNickname(nickname,proto_win);
241 }
242
243
244 /* sigh, There are still problems find smart cards from the temp
245 * db. This will get smart cards working again. The real fix
246 * is to make sure we can search the temp db by their token nickname.
247 */
248 if (cert == NULL) {
249 cert = CERT_FindCertByNickname(handle,nickname);
250 }
251
252 if ( cert != NULL ) {
253 unsigned int requiredKeyUsage;
254 unsigned int requiredCertType;
255
256 rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE,
257 &requiredKeyUsage, &requiredCertType);
258 if ( rv != SECSuccess ) {
259 /* drop the extra reference */
260 CERT_DestroyCertificate(cert);
261 cert = NULL;
262 goto loser;
263 }
264 /* If we already found the right cert, just return it */
265 if ( (!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE)
266 == secCertTimeValid) &&
267 (CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) &&
268 (cert->nsCertType & requiredCertType) &&
269 CERT_IsUserCert(cert) ) {
270 return(cert);
271 }
272
273 /* collect certs for this nickname, sorting them into the list */
274 certList = CERT_CreateSubjectCertList(certList, handle,
275 &cert->derSubject, time, validOnly);
276
277 CERT_FilterCertListForUserCerts(certList);
278
279 /* drop the extra reference */
280 CERT_DestroyCertificate(cert);
281 cert = NULL;
282 }
283
284 if ( certList == NULL ) {
285 goto loser;
286 }
287
288 /* remove certs with incorrect usage */
289 rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
290
291 if ( rv != SECSuccess ) {
292 goto loser;
293 }
294
295 if ( ! CERT_LIST_END(CERT_LIST_HEAD(certList), certList) ) {
296 cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
297 }
298
299 loser:
300 if ( certList != NULL ) {
301 CERT_DestroyCertList(certList);
302 }
303
304 return(cert);
305 }
306
307 CERTCertList *
308 CERT_MatchUserCert(CERTCertDBHandle *handle,
309 SECCertUsage usage,
310 int nCANames, char **caNames,
311 void *proto_win)
312 {
313 CERTCertList *certList = NULL;
314 SECStatus rv;
315
316 certList = CERT_FindUserCertsByUsage(handle, usage, PR_TRUE, PR_TRUE,
317 proto_win);
318 if ( certList == NULL ) {
319 goto loser;
320 }
321
322 rv = CERT_FilterCertListByCANames(certList, nCANames, caNames, usage);
323 if ( rv != SECSuccess ) {
324 goto loser;
325 }
326
327 goto done;
328
329 loser:
330 if ( certList != NULL ) {
331 CERT_DestroyCertList(certList);
332 certList = NULL;
333 }
334
335 done:
336
337 return(certList);
338 }
339
340
341 typedef struct stringNode {
342 struct stringNode *next;
343 char *string;
344 } stringNode;
345
346 static PRStatus
347 CollectNicknames( NSSCertificate *c, void *data)
348 {
349 CERTCertNicknames *names;
350 PRBool saveit = PR_FALSE;
351 stringNode *node;
352 int len;
353 #ifdef notdef
354 NSSTrustDomain *td;
355 NSSTrust *trust;
356 #endif
357 char *stanNickname;
358 char *nickname = NULL;
359
360 names = (CERTCertNicknames *)data;
361
362 stanNickname = nssCertificate_GetNickname(c,NULL);
363
364 if ( stanNickname ) {
365 nss_ZFreeIf(stanNickname);
366 stanNickname = NULL;
367 if (names->what == SEC_CERT_NICKNAMES_USER) {
368 saveit = NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL);
369 }
370 #ifdef notdef
371 else {
372 td = NSSCertificate_GetTrustDomain(c);
373 if (!td) {
374 return PR_SUCCESS;
375 }
376 trust = nssTrustDomain_FindTrustForCertificate(td,c);
377
378 switch(names->what) {
379 case SEC_CERT_NICKNAMES_ALL:
380 if ((trust->sslFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||
381 (trust->emailFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||
382 (trust->objectSigningFlags &
383 (CERTDB_VALID_CA|CERTDB_VALID_PEER))) {
384 saveit = PR_TRUE;
385 }
386
387 break;
388 case SEC_CERT_NICKNAMES_SERVER:
389 if ( trust->sslFlags & CERTDB_VALID_PEER ) {
390 saveit = PR_TRUE;
391 }
392
393 break;
394 case SEC_CERT_NICKNAMES_CA:
395 if (((trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA)||
396 ((trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA) ||
397 ((trust->objectSigningFlags & CERTDB_VALID_CA )
398 == CERTDB_VALID_CA)) {
399 saveit = PR_TRUE;
400 }
401 break;
402 }
403 }
404 #endif
405 }
406
407 /* traverse the list of collected nicknames and make sure we don't make
408 * a duplicate
409 */
410 if ( saveit ) {
411 nickname = STAN_GetCERTCertificateName(NULL, c);
412 /* nickname can only be NULL here if we are having memory
413 * alloc problems */
414 if (nickname == NULL) {
415 return PR_FAILURE;
416 }
417 node = (stringNode *)names->head;
418 while ( node != NULL ) {
419 if ( PORT_Strcmp(nickname, node->string) == 0 ) {
420 /* if the string matches, then don't save this one */
421 saveit = PR_FALSE;
422 break;
423 }
424 node = node->next;
425 }
426 }
427
428 if ( saveit ) {
429
430 /* allocate the node */
431 node = (stringNode*)PORT_ArenaAlloc(names->arena, sizeof(stringNode));
432 if ( node == NULL ) {
433 PORT_Free(nickname);
434 return PR_FAILURE;
435 }
436
437 /* copy the string */
438 len = PORT_Strlen(nickname) + 1;
439 node->string = (char*)PORT_ArenaAlloc(names->arena, len);
440 if ( node->string == NULL ) {
441 PORT_Free(nickname);
442 return PR_FAILURE;
443 }
444 PORT_Memcpy(node->string, nickname, len);
445
446 /* link it into the list */
447 node->next = (stringNode *)names->head;
448 names->head = (void *)node;
449
450 /* bump the count */
451 names->numnicknames++;
452 }
453
454 if (nickname) PORT_Free(nickname);
455 return(PR_SUCCESS);
456 }
457
458 CERTCertNicknames *
459 CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx)
460 {
461 PLArenaPool *arena;
462 CERTCertNicknames *names;
463 int i;
464 stringNode *node;
465
466 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
467 if ( arena == NULL ) {
468 PORT_SetError(SEC_ERROR_NO_MEMORY);
469 return(NULL);
470 }
471
472 names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
473 if ( names == NULL ) {
474 goto loser;
475 }
476
477 names->arena = arena;
478 names->head = NULL;
479 names->numnicknames = 0;
480 names->nicknames = NULL;
481 names->what = what;
482 names->totallen = 0;
483
484 /* make sure we are logged in */
485 (void) pk11_TraverseAllSlots(NULL, NULL, PR_TRUE, wincx);
486
487 NSSTrustDomain_TraverseCertificates(handle,
488 CollectNicknames, (void *)names);
489 if ( names->numnicknames ) {
490 names->nicknames = (char**)PORT_ArenaAlloc(arena,
491 names->numnicknames * sizeof(char *));
492
493 if ( names->nicknames == NULL ) {
494 goto loser;
495 }
496
497 node = (stringNode *)names->head;
498
499 for ( i = 0; i < names->numnicknames; i++ ) {
500 PORT_Assert(node != NULL);
501
502 names->nicknames[i] = node->string;
503 names->totallen += PORT_Strlen(node->string);
504 node = node->next;
505 }
506
507 PORT_Assert(node == NULL);
508 }
509
510 return(names);
511
512 loser:
513 PORT_FreeArena(arena, PR_FALSE);
514 return(NULL);
515 }
516
517 void
518 CERT_FreeNicknames(CERTCertNicknames *nicknames)
519 {
520 PORT_FreeArena(nicknames->arena, PR_FALSE);
521
522 return;
523 }
524
525 /* [ FROM pcertdb.c ] */
526
527 typedef struct dnameNode {
528 struct dnameNode *next;
529 SECItem name;
530 } dnameNode;
531
532 void
533 CERT_FreeDistNames(CERTDistNames *names)
534 {
535 PORT_FreeArena(names->arena, PR_FALSE);
536
537 return;
538 }
539
540 static SECStatus
541 CollectDistNames( CERTCertificate *cert, SECItem *k, void *data)
542 {
543 CERTDistNames *names;
544 PRBool saveit = PR_FALSE;
545 CERTCertTrust trust;
546 dnameNode *node;
547 int len;
548
549 names = (CERTDistNames *)data;
550
551 if ( CERT_GetCertTrust(cert, &trust) == SECSuccess ) {
552 /* only collect names of CAs trusted for issuing SSL clients */
553 if ( trust.sslFlags & CERTDB_TRUSTED_CLIENT_CA ) {
554 saveit = PR_TRUE;
555 }
556 }
557
558 if ( saveit ) {
559 /* allocate the node */
560 node = (dnameNode*)PORT_ArenaAlloc(names->arena, sizeof(dnameNode));
561 if ( node == NULL ) {
562 return(SECFailure);
563 }
564
565 /* copy the name */
566 node->name.len = len = cert->derSubject.len;
567 node->name.type = siBuffer;
568 node->name.data = (unsigned char*)PORT_ArenaAlloc(names->arena, len);
569 if ( node->name.data == NULL ) {
570 return(SECFailure);
571 }
572 PORT_Memcpy(node->name.data, cert->derSubject.data, len);
573
574 /* link it into the list */
575 node->next = (dnameNode *)names->head;
576 names->head = (void *)node;
577
578 /* bump the count */
579 names->nnames++;
580 }
581
582 return(SECSuccess);
583 }
584
585 /*
586 * Return all of the CAs that are "trusted" for SSL.
587 */
588 CERTDistNames *
589 CERT_DupDistNames(CERTDistNames *orig)
590 {
591 PLArenaPool *arena;
592 CERTDistNames *names;
593 int i;
594 SECStatus rv;
595
596 /* allocate an arena to use */
597 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
598 if (arena == NULL) {
599 PORT_SetError(SEC_ERROR_NO_MEMORY);
600 return(NULL);
601 }
602
603 /* allocate the header structure */
604 names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
605 if (names == NULL) {
606 goto loser;
607 }
608
609 /* initialize the header struct */
610 names->arena = arena;
611 names->head = NULL;
612 names->nnames = orig->nnames;
613 names->names = NULL;
614
615 /* construct the array from the list */
616 if (orig->nnames) {
617 names->names = (SECItem*)PORT_ArenaNewArray(arena, SECItem,
618 orig->nnames);
619 if (names->names == NULL) {
620 goto loser;
621 }
622 for (i = 0; i < orig->nnames; i++) {
623 rv = SECITEM_CopyItem(arena, &names->names[i], &orig->names[i]);
624 if (rv != SECSuccess) {
625 goto loser;
626 }
627 }
628 }
629 return(names);
630
631 loser:
632 PORT_FreeArena(arena, PR_FALSE);
633 return(NULL);
634 }
635
636 CERTDistNames *
637 CERT_GetSSLCACerts(CERTCertDBHandle *handle)
638 {
639 PLArenaPool *arena;
640 CERTDistNames *names;
641 int i;
642 SECStatus rv;
643 dnameNode *node;
644
645 /* allocate an arena to use */
646 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
647 if ( arena == NULL ) {
648 PORT_SetError(SEC_ERROR_NO_MEMORY);
649 return(NULL);
650 }
651
652 /* allocate the header structure */
653 names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
654 if ( names == NULL ) {
655 goto loser;
656 }
657
658 /* initialize the header struct */
659 names->arena = arena;
660 names->head = NULL;
661 names->nnames = 0;
662 names->names = NULL;
663
664 /* collect the names from the database */
665 rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL);
666 if ( rv ) {
667 goto loser;
668 }
669
670 /* construct the array from the list */
671 if ( names->nnames ) {
672 names->names = (SECItem*)PORT_ArenaAlloc(arena, names->nnames * sizeof(SECItem));
673
674 if ( names->names == NULL ) {
675 goto loser;
676 }
677
678 node = (dnameNode *)names->head;
679
680 for ( i = 0; i < names->nnames; i++ ) {
681 PORT_Assert(node != NULL);
682
683 names->names[i] = node->name;
684 node = node->next;
685 }
686
687 PORT_Assert(node == NULL);
688 }
689
690 return(names);
691
692 loser:
693 PORT_FreeArena(arena, PR_FALSE);
694 return(NULL);
695 }
696
697 CERTDistNames *
698 CERT_DistNamesFromCertList(CERTCertList *certList)
699 {
700 CERTDistNames * dnames = NULL;
701 PLArenaPool * arena;
702 CERTCertListNode *node = NULL;
703 SECItem * names = NULL;
704 int listLen = 0, i = 0;
705
706 if (certList == NULL) {
707 PORT_SetError(SEC_ERROR_INVALID_ARGS);
708 return NULL;
709 }
710
711 node = CERT_LIST_HEAD(certList);
712 while ( ! CERT_LIST_END(node, certList) ) {
713 listLen += 1;
714 node = CERT_LIST_NEXT(node);
715 }
716
717 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
718 if (arena == NULL) goto loser;
719 dnames = PORT_ArenaZNew(arena, CERTDistNames);
720 if (dnames == NULL) goto loser;
721
722 dnames->arena = arena;
723 dnames->nnames = listLen;
724 dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, listLen);
725 if (names == NULL) goto loser;
726
727 node = CERT_LIST_HEAD(certList);
728 while ( ! CERT_LIST_END(node, certList) ) {
729 CERTCertificate *cert = node->cert;
730 SECStatus rv = SECITEM_CopyItem(arena, &names[i++], &cert->derSubject);
731 if (rv == SECFailure) {
732 goto loser;
733 }
734 node = CERT_LIST_NEXT(node);
735 }
736 return dnames;
737 loser:
738 if (arena) {
739 PORT_FreeArena(arena, PR_FALSE);
740 }
741 return NULL;
742 }
743
744 CERTDistNames *
745 CERT_DistNamesFromNicknames(CERTCertDBHandle *handle, char **nicknames,
746 int nnames)
747 {
748 CERTDistNames *dnames = NULL;
749 PLArenaPool *arena;
750 int i, rv;
751 SECItem *names = NULL;
752 CERTCertificate *cert = NULL;
753
754 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
755 if (arena == NULL) goto loser;
756 dnames = PORT_ArenaZNew(arena, CERTDistNames);
757 if (dnames == NULL) goto loser;
758
759 dnames->arena = arena;
760 dnames->nnames = nnames;
761 dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, nnames);
762 if (names == NULL) goto loser;
763
764 for (i = 0; i < nnames; i++) {
765 cert = CERT_FindCertByNicknameOrEmailAddr(handle, nicknames[i]);
766 if (cert == NULL) goto loser;
767 rv = SECITEM_CopyItem(arena, &names[i], &cert->derSubject);
768 if (rv == SECFailure) goto loser;
769 CERT_DestroyCertificate(cert);
770 }
771 return dnames;
772
773 loser:
774 if (cert != NULL)
775 CERT_DestroyCertificate(cert);
776 if (arena != NULL)
777 PORT_FreeArena(arena, PR_FALSE);
778 return NULL;
779 }
780
781 /* [ from pcertdb.c - calls Ascii to Name ] */
782 /*
783 * Lookup a certificate in the database by name
784 */
785 CERTCertificate *
786 CERT_FindCertByNameString(CERTCertDBHandle *handle, char *nameStr)
787 {
788 CERTName *name;
789 SECItem *nameItem;
790 CERTCertificate *cert = NULL;
791 PLArenaPool *arena = NULL;
792
793 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
794
795 if ( arena == NULL ) {
796 goto loser;
797 }
798
799 name = CERT_AsciiToName(nameStr);
800
801 if ( name ) {
802 nameItem = SEC_ASN1EncodeItem (arena, NULL, (void *)name,
803 CERT_NameTemplate);
804 if ( nameItem != NULL ) {
805 cert = CERT_FindCertByName(handle, nameItem);
806 }
807 CERT_DestroyName(name);
808 }
809
810 loser:
811 if ( arena ) {
812 PORT_FreeArena(arena, PR_FALSE);
813 }
814
815 return(cert);
816 }
817
818 /* From certv3.c */
819
820 CERTCrlDistributionPoints *
821 CERT_FindCRLDistributionPoints (CERTCertificate *cert)
822 {
823 SECItem encodedExtenValue;
824 SECStatus rv;
825 CERTCrlDistributionPoints *dps;
826
827 encodedExtenValue.data = NULL;
828 encodedExtenValue.len = 0;
829
830 rv = cert_FindExtension(cert->extensions, SEC_OID_X509_CRL_DIST_POINTS,
831 &encodedExtenValue);
832 if ( rv != SECSuccess ) {
833 return (NULL);
834 }
835
836 dps = CERT_DecodeCRLDistributionPoints(cert->arena, &encodedExtenValue);
837
838 PORT_Free(encodedExtenValue.data);
839
840 return dps;
841 }
842
843 /* From crl.c */
844 CERTSignedCrl * CERT_ImportCRL
845 (CERTCertDBHandle *handle, SECItem *derCRL, char *url, int type, void *wincx)
846 {
847 CERTSignedCrl* retCrl = NULL;
848 PK11SlotInfo* slot = PK11_GetInternalKeySlot();
849 retCrl = PK11_ImportCRL(slot, derCRL, url, type, wincx,
850 CRL_IMPORT_DEFAULT_OPTIONS, NULL, CRL_DECODE_DEFAULT_OPTIONS);
851 PK11_FreeSlot(slot);
852
853 return retCrl;
854 }
855
856 /* From certdb.c */
857 static SECStatus
858 cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted)
859 {
860 SECStatus rv;
861 SECItem *derCert;
862 CERTCertificate *cert = NULL;
863 CERTCertificate *newcert = NULL;
864 CERTCertDBHandle *handle;
865 CERTCertTrust trust;
866 PRBool isca;
867 char *nickname;
868 unsigned int certtype;
869
870 handle = CERT_GetDefaultCertDB();
871
872 while (numcerts--) {
873 derCert = certs;
874 certs++;
875
876 /* decode my certificate */
877 /* This use is ok -- only looks at decoded parts, calls NewTemp later */
878 newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
879 if ( newcert == NULL ) {
880 goto loser;
881 }
882
883 if (!trusted) {
884 /* make sure that cert is valid */
885 rv = CERT_CertTimesValid(newcert);
886 if ( rv == SECFailure ) {
887 goto endloop;
888 }
889 }
890
891 /* does it have the CA extension */
892
893 /*
894 * Make sure that if this is an intermediate CA in the chain that
895 * it was given permission by its signer to be a CA.
896 */
897 isca = CERT_IsCACert(newcert, &certtype);
898
899 if ( !isca ) {
900 if (!trusted) {
901 goto endloop;
902 }
903 trust.sslFlags = CERTDB_VALID_CA;
904 trust.emailFlags = CERTDB_VALID_CA;
905 trust.objectSigningFlags = CERTDB_VALID_CA;
906 } else {
907 /* SSL ca's must have the ssl bit set */
908 if ( ( certUsage == certUsageSSLCA ) &&
909 (( certtype & NS_CERT_TYPE_SSL_CA ) != NS_CERT_TYPE_SSL_CA )) {
910 goto endloop;
911 }
912
913 /* it passed all of the tests, so lets add it to the database */
914 /* mark it as a CA */
915 PORT_Memset((void *)&trust, 0, sizeof(trust));
916 switch ( certUsage ) {
917 case certUsageSSLCA:
918 trust.sslFlags = CERTDB_VALID_CA;
919 break;
920 case certUsageUserCertImport:
921 if ((certtype & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
922 trust.sslFlags = CERTDB_VALID_CA;
923 }
924 if ((certtype & NS_CERT_TYPE_EMAIL_CA)
925 == NS_CERT_TYPE_EMAIL_CA ) {
926 trust.emailFlags = CERTDB_VALID_CA;
927 }
928 if ( ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) ==
929 NS_CERT_TYPE_OBJECT_SIGNING_CA ) {
930 trust.objectSigningFlags = CERTDB_VALID_CA;
931 }
932 break;
933 default:
934 PORT_Assert(0);
935 break;
936 }
937 }
938
939 cert = CERT_NewTempCertificate(handle, derCert, NULL,
940 PR_FALSE, PR_FALSE);
941 if ( cert == NULL ) {
942 goto loser;
943 }
944
945 /* if the cert is temp, make it perm; otherwise we're done */
946 if (cert->istemp) {
947 /* get a default nickname for it */
948 nickname = CERT_MakeCANickname(cert);
949
950 rv = CERT_AddTempCertToPerm(cert, nickname, &trust);
951
952 /* free the nickname */
953 if ( nickname ) {
954 PORT_Free(nickname);
955 }
956 } else {
957 rv = SECSuccess;
958 }
959
960 CERT_DestroyCertificate(cert);
961 cert = NULL;
962
963 if ( rv != SECSuccess ) {
964 goto loser;
965 }
966
967 endloop:
968 if ( newcert ) {
969 CERT_DestroyCertificate(newcert);
970 newcert = NULL;
971 }
972
973 }
974
975 rv = SECSuccess;
976 goto done;
977 loser:
978 rv = SECFailure;
979 done:
980
981 if ( newcert ) {
982 CERT_DestroyCertificate(newcert);
983 newcert = NULL;
984 }
985
986 if ( cert ) {
987 CERT_DestroyCertificate(cert);
988 cert = NULL;
989 }
990
991 return(rv);
992 }
993
994 SECStatus
995 CERT_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage)
996 {
997 return cert_ImportCAChain(certs, numcerts, certUsage, PR_FALSE);
998 }
999
1000 SECStatus
1001 CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage) {
1002 return cert_ImportCAChain(certs, numcerts, certUsage, PR_TRUE);
1003 }
1004
1005 /* Moved from certdb.c */
1006 /*
1007 ** CERT_CertChainFromCert
1008 **
1009 ** Construct a CERTCertificateList consisting of the given certificate and all
1010 ** of the issuer certs until we either get to a self-signed cert or can't find
1011 ** an issuer. Since we don't know how many certs are in the chain we have to
1012 ** build a linked list first as we count them.
1013 */
1014
1015 typedef struct certNode {
1016 struct certNode *next;
1017 CERTCertificate *cert;
1018 } certNode;
1019
1020 CERTCertificateList *
1021 CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage,
1022 PRBool includeRoot)
1023 {
1024 CERTCertificateList *chain = NULL;
1025 NSSCertificate **stanChain;
1026 NSSCertificate *stanCert;
1027 PLArenaPool *arena;
1028 NSSUsage nssUsage;
1029 int i, len;
1030 NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
1031 NSSCryptoContext *cc = STAN_GetDefaultCryptoContext();
1032
1033 stanCert = STAN_GetNSSCertificate(cert);
1034 if (!stanCert) {
1035 /* error code is set */
1036 return NULL;
1037 }
1038 nssUsage.anyUsage = PR_FALSE;
1039 nssUsage.nss3usage = usage;
1040 nssUsage.nss3lookingForCA = PR_FALSE;
1041 stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL, NULL,
1042 CERT_MAX_CERT_CHAIN, NULL, NULL, td, cc);
1043 if (!stanChain) {
1044 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
1045 return NULL;
1046 }
1047
1048 len = 0;
1049 stanCert = stanChain[0];
1050 while (stanCert) {
1051 stanCert = stanChain[++len];
1052 }
1053
1054 arena = PORT_NewArena(4096);
1055 if (arena == NULL) {
1056 goto loser;
1057 }
1058
1059 chain = (CERTCertificateList *)PORT_ArenaAlloc(arena,
1060 sizeof(CERTCertificateList));
1061 if (!chain) goto loser;
1062 chain->certs = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
1063 if (!chain->certs) goto loser;
1064 i = 0;
1065 stanCert = stanChain[i];
1066 while (stanCert) {
1067 SECItem derCert;
1068 CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
1069 if (!cCert) {
1070 goto loser;
1071 }
1072 derCert.len = (unsigned int)stanCert->encoding.size;
1073 derCert.data = (unsigned char *)stanCert->encoding.data;
1074 derCert.type = siBuffer;
1075 SECITEM_CopyItem(arena, &chain->certs[i], &derCert);
1076 stanCert = stanChain[++i];
1077 if (!stanCert && !cCert->isRoot) {
1078 /* reached the end of the chain, but the final cert is
1079 * not a root. Don't discard it.
1080 */
1081 includeRoot = PR_TRUE;
1082 }
1083 CERT_DestroyCertificate(cCert);
1084 }
1085 if ( !includeRoot && len > 1) {
1086 chain->len = len - 1;
1087 } else {
1088 chain->len = len;
1089 }
1090
1091 chain->arena = arena;
1092 nss_ZFreeIf(stanChain);
1093 return chain;
1094 loser:
1095 i = 0;
1096 stanCert = stanChain[i];
1097 while (stanCert) {
1098 CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
1099 if (cCert) {
1100 CERT_DestroyCertificate(cCert);
1101 }
1102 stanCert = stanChain[++i];
1103 }
1104 nss_ZFreeIf(stanChain);
1105 if (arena) {
1106 PORT_FreeArena(arena, PR_FALSE);
1107 }
1108 return NULL;
1109 }
1110
1111 /* Builds a CERTCertificateList holding just one DER-encoded cert, namely
1112 ** the one for the cert passed as an argument.
1113 */
1114 CERTCertificateList *
1115 CERT_CertListFromCert(CERTCertificate *cert)
1116 {
1117 CERTCertificateList *chain = NULL;
1118 int rv;
1119 PLArenaPool *arena;
1120
1121 /* arena for SecCertificateList */
1122 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1123 if (arena == NULL) goto no_memory;
1124
1125 /* build the CERTCertificateList */
1126 chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList));
1127 if (chain == NULL) goto no_memory;
1128 chain->certs = (SECItem*)PORT_ArenaAlloc(arena, 1 * sizeof(SECItem));
1129 if (chain->certs == NULL) goto no_memory;
1130 rv = SECITEM_CopyItem(arena, chain->certs, &(cert->derCert));
1131 if (rv < 0) goto loser;
1132 chain->len = 1;
1133 chain->arena = arena;
1134
1135 return chain;
1136
1137 no_memory:
1138 PORT_SetError(SEC_ERROR_NO_MEMORY);
1139 loser:
1140 if (arena != NULL) {
1141 PORT_FreeArena(arena, PR_FALSE);
1142 }
1143 return NULL;
1144 }
1145
1146 CERTCertificateList *
1147 CERT_DupCertList(const CERTCertificateList * oldList)
1148 {
1149 CERTCertificateList *newList = NULL;
1150 PLArenaPool *arena = NULL;
1151 SECItem *newItem;
1152 SECItem *oldItem;
1153 int len = oldList->len;
1154 int rv;
1155
1156 /* arena for SecCertificateList */
1157 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1158 if (arena == NULL)
1159 goto no_memory;
1160
1161 /* now build the CERTCertificateList */
1162 newList = PORT_ArenaNew(arena, CERTCertificateList);
1163 if (newList == NULL)
1164 goto no_memory;
1165 newList->arena = arena;
1166 newItem = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
1167 if (newItem == NULL)
1168 goto no_memory;
1169 newList->certs = newItem;
1170 newList->len = len;
1171
1172 for (oldItem = oldList->certs; len > 0; --len, ++newItem, ++oldItem) {
1173 rv = SECITEM_CopyItem(arena, newItem, oldItem);
1174 if (rv < 0)
1175 goto loser;
1176 }
1177 return newList;
1178
1179 no_memory:
1180 PORT_SetError(SEC_ERROR_NO_MEMORY);
1181 loser:
1182 if (arena != NULL) {
1183 PORT_FreeArena(arena, PR_FALSE);
1184 }
1185 return NULL;
1186 }
1187
1188 void
1189 CERT_DestroyCertificateList(CERTCertificateList *list)
1190 {
1191 PORT_FreeArena(list->arena, PR_FALSE);
1192 }
1193
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)