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

Side by Side Diff: nss/lib/certhigh/certhigh.c

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

Powered by Google App Engine
This is Rietveld 408576698