1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2000
19 * the Initial Developer. All Rights Reserved.
22 * Ian McGreer <mcgreer@netscape.com>
23 * Javier Delgadillo <javi@netscape.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsNSSComponent.h"
40 #include "nsNSSCertificateDB.h"
42 #include "nsNSSCertificate.h"
43 #include "nsNSSHelper.h"
44 #include "nsNSSCertHelper.h"
45 #include "nsNSSCertCache.h"
47 #include "nsICertificateDialogs.h"
48 #include "nsNSSCertTrust.h"
49 #include "nsILocalFile.h"
50 #include "nsPKCS12Blob.h"
51 #include "nsPK11TokenDB.h"
52 #include "nsOCSPResponder.h"
53 #include "nsReadableUtils.h"
54 #include "nsIMutableArray.h"
55 #include "nsArrayUtils.h"
56 #include "nsNSSShutDown.h"
57 #include "nsIPrefService.h"
58 #include "nsIPrefBranch.h"
59 #include "nsComponentManagerUtils.h"
60 #include "nsIPrompt.h"
61 #include "nsIProxyObjectManager.h"
62 #include "nsProxiedService.h"
79 extern PRLogModuleInfo
* gPIPNSSLog
;
82 #include "nsNSSCleaner.h"
83 NSSCleanupAutoPtrClass(CERTCertificate
, CERT_DestroyCertificate
)
84 NSSCleanupAutoPtrClass(CERTCertList
, CERT_DestroyCertList
)
85 NSSCleanupAutoPtrClass(CERTCertificateList
, CERT_DestroyCertificateList
)
86 NSSCleanupAutoPtrClass(PK11SlotInfo
, PK11_FreeSlot
)
88 static NS_DEFINE_CID(kNSSComponentCID
, NS_NSSCOMPONENT_CID
);
91 NS_IMPL_THREADSAFE_ISUPPORTS2(nsNSSCertificateDB
, nsIX509CertDB
, nsIX509CertDB2
)
93 nsNSSCertificateDB::nsNSSCertificateDB()
97 nsNSSCertificateDB::~nsNSSCertificateDB()
102 nsNSSCertificateDB::FindCertByNickname(nsISupports
*aToken
,
103 const nsAString
&nickname
,
104 nsIX509Cert
**_rvCert
)
106 nsNSSShutDownPreventionLock locker
;
107 CERTCertificate
*cert
= NULL
;
108 char *asciiname
= NULL
;
109 NS_ConvertUTF16toUTF8
aUtf8Nickname(nickname
);
110 asciiname
= const_cast<char*>(aUtf8Nickname
.get());
111 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("Getting \"%s\"\n", asciiname
));
113 // what it should be, but for now...
115 cert
= PK11_FindCertFromNickname(asciiname
, NULL
);
117 cert
= CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname
);
120 cert
= PK11_FindCertFromNickname(asciiname
, NULL
);
122 cert
= CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname
);
125 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("got it\n"));
126 nsCOMPtr
<nsIX509Cert
> pCert
= new nsNSSCertificate(cert
);
127 CERT_DestroyCertificate(cert
);
133 return NS_ERROR_FAILURE
;
137 nsNSSCertificateDB::FindCertByDBKey(const char *aDBkey
, nsISupports
*aToken
,
140 nsNSSShutDownPreventionLock locker
;
141 SECItem keyItem
= {siBuffer
, nsnull
, 0};
143 CERTIssuerAndSN issuerSN
;
144 unsigned long moduleID
,slotID
;
146 if (!aDBkey
|| !*aDBkey
)
147 return NS_ERROR_INVALID_ARG
;
149 dummy
= NSSBase64_DecodeBuffer(nsnull
, &keyItem
, aDBkey
,
150 (PRUint32
)PL_strlen(aDBkey
));
151 if (!dummy
|| keyItem
.len
< NS_NSS_LONG
*4) {
152 PR_FREEIF(keyItem
.data
);
153 return NS_ERROR_INVALID_ARG
;
156 CERTCertificate
*cert
;
157 // someday maybe we can speed up the search using the moduleID and slotID
158 moduleID
= NS_NSS_GET_LONG(keyItem
.data
);
159 slotID
= NS_NSS_GET_LONG(&keyItem
.data
[NS_NSS_LONG
]);
161 // build the issuer/SN structure
162 issuerSN
.serialNumber
.len
= NS_NSS_GET_LONG(&keyItem
.data
[NS_NSS_LONG
*2]);
163 issuerSN
.derIssuer
.len
= NS_NSS_GET_LONG(&keyItem
.data
[NS_NSS_LONG
*3]);
164 if (issuerSN
.serialNumber
.len
== 0 || issuerSN
.derIssuer
.len
== 0
165 || issuerSN
.serialNumber
.len
+ issuerSN
.derIssuer
.len
166 != keyItem
.len
- NS_NSS_LONG
*4) {
167 PR_FREEIF(keyItem
.data
);
168 return NS_ERROR_INVALID_ARG
;
170 issuerSN
.serialNumber
.data
= &keyItem
.data
[NS_NSS_LONG
*4];
171 issuerSN
.derIssuer
.data
= &keyItem
.data
[NS_NSS_LONG
*4+
172 issuerSN
.serialNumber
.len
];
174 cert
= CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerSN
);
175 PR_FREEIF(keyItem
.data
);
177 nsNSSCertificate
*nssCert
= new nsNSSCertificate(cert
);
178 CERT_DestroyCertificate(cert
);
179 if (nssCert
== nsnull
)
180 return NS_ERROR_OUT_OF_MEMORY
;
182 *_cert
= static_cast<nsIX509Cert
*>(nssCert
);
188 nsNSSCertificateDB::FindCertNicknames(nsISupports
*aToken
,
191 PRUnichar
***_certNames
)
193 nsNSSShutDownPreventionLock locker
;
194 nsresult rv
= NS_ERROR_FAILURE
;
196 * obtain the cert list from NSS
198 CERTCertList
*certList
= NULL
;
199 PK11CertListType pk11type
;
201 // this would seem right, but it didn't work...
202 // oh, I know why - bonks out on internal slot certs
203 if (aType
== nsIX509Cert::USER_CERT
)
204 pk11type
= PK11CertListUser
;
207 pk11type
= PK11CertListUnique
;
208 certList
= PK11_ListCerts(pk11type
, NULL
);
212 * get list of cert names from list of certs
213 * XXX also cull the list (NSS only distinguishes based on user/non-user
215 getCertNames(certList
, aType
, _count
, _certNames
);
222 CERT_DestroyCertList(certList
);
226 SECStatus PR_CALLBACK
227 collect_certs(void *arg
, SECItem
**certs
, int numcerts
)
229 CERTDERCerts
*collectArgs
;
233 collectArgs
= (CERTDERCerts
*)arg
;
235 collectArgs
->numcerts
= numcerts
;
236 collectArgs
->rawCerts
= (SECItem
*) PORT_ArenaZAlloc(collectArgs
->arena
,
237 sizeof(SECItem
) * numcerts
);
238 if ( collectArgs
->rawCerts
== NULL
)
241 cert
= collectArgs
->rawCerts
;
243 while ( numcerts
-- ) {
244 rv
= SECITEM_CopyItem(collectArgs
->arena
, cert
, *certs
);
245 if ( rv
== SECFailure
)
255 nsNSSCertificateDB::getCertsFromPackage(PRArenaPool
*arena
, PRUint8
*data
,
258 nsNSSShutDownPreventionLock locker
;
259 CERTDERCerts
*collectArgs
=
260 (CERTDERCerts
*)PORT_ArenaZAlloc(arena
, sizeof(CERTDERCerts
));
261 if ( collectArgs
== nsnull
)
264 collectArgs
->arena
= arena
;
265 SECStatus sec_rv
= CERT_DecodeCertPackage(reinterpret_cast<char *>(data
),
266 length
, collect_certs
,
267 (void *)collectArgs
);
268 if (sec_rv
!= SECSuccess
)
275 nsNSSCertificateDB::handleCACertDownload(nsIArray
*x509Certs
,
276 nsIInterfaceRequestor
*ctx
)
278 // First thing we have to do is figure out which certificate we're
279 // gonna present to the user. The CA may have sent down a list of
280 // certs which may or may not be a chained list of certs. Until
281 // the day we can design some solid UI for the general case, we'll
282 // code to the > 90% case. That case is where a CA sends down a
283 // list that is a hierarchy whose root is either the first or
284 // the last cert. What we're gonna do is compare the first
285 // 2 entries, if the second was signed by the first, we assume
286 // the root cert is the first cert and display it. Otherwise,
287 // we compare the last 2 entries, if the second to last cert was
288 // signed by the last cert, then we assume the last cert is the
289 // root and display it.
291 nsNSSShutDownPreventionLock locker
;
295 x509Certs
->GetLength(&numCerts
);
296 NS_ASSERTION(numCerts
> 0, "Didn't get any certs to import.");
298 return NS_OK
; // Nothing to import, so nothing to do.
300 nsCOMPtr
<nsIX509Cert
> certToShow
;
301 nsCOMPtr
<nsISupports
> isupports
;
302 PRUint32 selCertIndex
;
304 // There's only one cert, so let's show it.
306 certToShow
= do_QueryElementAt(x509Certs
, selCertIndex
);
308 nsCOMPtr
<nsIX509Cert
> cert0
; // first cert
309 nsCOMPtr
<nsIX509Cert
> cert1
; // second cert
310 nsCOMPtr
<nsIX509Cert
> certn_2
; // second to last cert
311 nsCOMPtr
<nsIX509Cert
> certn_1
; // last cert
313 cert0
= do_QueryElementAt(x509Certs
, 0);
314 cert1
= do_QueryElementAt(x509Certs
, 1);
315 certn_2
= do_QueryElementAt(x509Certs
, numCerts
-2);
316 certn_1
= do_QueryElementAt(x509Certs
, numCerts
-1);
318 nsXPIDLString cert0SubjectName
;
319 nsXPIDLString cert1IssuerName
;
320 nsXPIDLString certn_2IssuerName
;
321 nsXPIDLString certn_1SubjectName
;
323 cert0
->GetSubjectName(cert0SubjectName
);
324 cert1
->GetIssuerName(cert1IssuerName
);
325 certn_2
->GetIssuerName(certn_2IssuerName
);
326 certn_1
->GetSubjectName(certn_1SubjectName
);
328 if (cert1IssuerName
.Equals(cert0SubjectName
)) {
329 // In this case, the first cert in the list signed the second,
330 // so the first cert is the root. Let's display it.
334 if (certn_2IssuerName
.Equals(certn_1SubjectName
)) {
335 // In this case the last cert has signed the second to last cert.
336 // The last cert is the root, so let's display it.
337 selCertIndex
= numCerts
-1;
338 certToShow
= certn_1
;
340 // It's not a chain, so let's just show the first one in the
348 return NS_ERROR_FAILURE
;
350 nsCOMPtr
<nsICertificateDialogs
> dialogs
;
351 nsresult rv
= ::getNSSDialogs(getter_AddRefs(dialogs
),
352 NS_GET_IID(nsICertificateDialogs
),
353 NS_CERTIFICATEDIALOGS_CONTRACTID
);
359 rv
=certToShow
->GetRawDER(&der
.len
, (PRUint8
**)&der
.data
);
364 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("Creating temp cert\n"));
365 CERTCertificate
*tmpCert
;
366 CERTCertDBHandle
*certdb
= CERT_GetDefaultCertDB();
367 tmpCert
= CERT_FindCertByDERCert(certdb
, &der
);
369 tmpCert
= CERT_NewTempCertificate(certdb
, &der
,
370 nsnull
, PR_FALSE
, PR_TRUE
);
372 nsMemory::Free(der
.data
);
377 NS_ERROR("Couldn't create cert from DER blob\n");
378 return NS_ERROR_FAILURE
;
381 CERTCertificateCleaner
tmpCertCleaner(tmpCert
);
383 if (!CERT_IsCACert(tmpCert
, NULL
)) {
384 DisplayCertificateAlert(ctx
, "NotACACert", certToShow
);
385 return NS_ERROR_FAILURE
;
388 if (tmpCert
->isperm
) {
389 DisplayCertificateAlert(ctx
, "CaCertExists", certToShow
);
390 return NS_ERROR_FAILURE
;
395 rv
= dialogs
->ConfirmDownloadCACert(ctx
, certToShow
, &trustBits
, &allows
);
400 return NS_ERROR_NOT_AVAILABLE
;
402 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("trust is %d\n", trustBits
));
403 nsXPIDLCString nickname
;
404 nickname
.Adopt(CERT_MakeCANickname(tmpCert
));
406 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("Created nick \"%s\"\n", nickname
.get()));
408 nsNSSCertTrust trust
;
410 trust
.AddCATrust(!!(trustBits
& nsIX509CertDB::TRUSTED_SSL
),
411 !!(trustBits
& nsIX509CertDB::TRUSTED_EMAIL
),
412 !!(trustBits
& nsIX509CertDB::TRUSTED_OBJSIGN
));
414 SECStatus srv
= CERT_AddTempCertToPerm(tmpCert
,
415 const_cast<char*>(nickname
.get()),
418 if (srv
!= SECSuccess
)
419 return NS_ERROR_FAILURE
;
421 // Import additional delivered certificates that can be verified.
423 // build a CertList for filtering
424 CERTCertList
*certList
= CERT_NewCertList();
425 if (certList
== NULL
) {
426 return NS_ERROR_FAILURE
;
429 CERTCertListCleaner
listCleaner(certList
);
431 // get all remaining certs into temp store
433 for (PRUint32 i
=0; i
<numCerts
; i
++) {
434 if (i
== selCertIndex
) {
435 // we already processed that one
439 certToShow
= do_QueryElementAt(x509Certs
, i
);
440 certToShow
->GetRawDER(&der
.len
, (PRUint8
**)&der
.data
);
442 CERTCertificate
*tmpCert2
=
443 CERT_NewTempCertificate(certdb
, &der
, nsnull
, PR_FALSE
, PR_TRUE
);
445 nsMemory::Free(der
.data
);
450 NS_ASSERTION(0, "Couldn't create temp cert from DER blob\n");
451 continue; // Let's try to import the rest of 'em
454 CERT_AddCertToListTail(certList
, tmpCert2
);
457 return ImportValidCACertsInList(certList
, ctx
);
461 * [noscript] void importCertificates(in charPtr data, in unsigned long length,
462 * in unsigned long type,
463 * in nsIInterfaceRequestor ctx);
466 nsNSSCertificateDB::ImportCertificates(PRUint8
* data
, PRUint32 length
,
468 nsIInterfaceRequestor
*ctx
)
471 nsNSSShutDownPreventionLock locker
;
474 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
476 return NS_ERROR_OUT_OF_MEMORY
;
478 CERTDERCerts
*certCollection
= getCertsFromPackage(arena
, data
, length
);
479 if (!certCollection
) {
480 PORT_FreeArena(arena
, PR_FALSE
);
481 return NS_ERROR_FAILURE
;
483 nsCOMPtr
<nsIMutableArray
> array
=
484 do_CreateInstance(NS_ARRAY_CONTRACTID
, &nsrv
);
485 if (NS_FAILED(nsrv
)) {
486 PORT_FreeArena(arena
, PR_FALSE
);
490 // Now let's create some certs to work with
491 nsCOMPtr
<nsIX509Cert
> x509Cert
;
492 nsNSSCertificate
*nssCert
;
494 for (int i
=0; i
<certCollection
->numcerts
; i
++) {
495 currItem
= &certCollection
->rawCerts
[i
];
496 nssCert
= nsNSSCertificate::ConstructFromDER((char*)currItem
->data
, currItem
->len
);
498 return NS_ERROR_FAILURE
;
499 x509Cert
= do_QueryInterface((nsIX509Cert
*)nssCert
);
500 array
->AppendElement(x509Cert
, PR_FALSE
);
503 case nsIX509Cert::CA_CERT
:
504 nsrv
= handleCACertDownload(array
, ctx
);
507 // We only deal with import CA certs in this method currently.
508 nsrv
= NS_ERROR_FAILURE
;
511 PORT_FreeArena(arena
, PR_FALSE
);
517 * [noscript] void importEmailCertificates(in charPtr data, in unsigned long length,
518 * in nsIInterfaceRequestor ctx);
521 nsNSSCertificateDB::ImportEmailCertificate(PRUint8
* data
, PRUint32 length
,
522 nsIInterfaceRequestor
*ctx
)
525 nsNSSShutDownPreventionLock locker
;
526 SECStatus srv
= SECFailure
;
527 nsresult nsrv
= NS_OK
;
528 CERTCertDBHandle
*certdb
;
529 CERTCertificate
**certArray
= NULL
;
530 CERTCertList
*certList
= NULL
;
531 CERTCertListNode
*node
;
533 SECCertUsage certusage
;
538 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
540 return NS_ERROR_OUT_OF_MEMORY
;
542 CERTDERCerts
*certCollection
= getCertsFromPackage(arena
, data
, length
);
543 if (!certCollection
) {
544 PORT_FreeArena(arena
, PR_FALSE
);
545 return NS_ERROR_FAILURE
;
548 certdb
= CERT_GetDefaultCertDB();
549 certusage
= certUsageEmailRecipient
;
551 numcerts
= certCollection
->numcerts
;
553 rawArray
= (SECItem
**) PORT_Alloc(sizeof(SECItem
*) * numcerts
);
555 nsrv
= NS_ERROR_FAILURE
;
559 for (i
=0; i
< numcerts
; i
++) {
560 rawArray
[i
] = &certCollection
->rawCerts
[i
];
563 srv
= CERT_ImportCerts(certdb
, certusage
, numcerts
, rawArray
,
564 &certArray
, PR_FALSE
, PR_FALSE
, NULL
);
569 if (srv
!= SECSuccess
) {
570 nsrv
= NS_ERROR_FAILURE
;
574 // build a CertList for filtering
575 certList
= CERT_NewCertList();
576 if (certList
== NULL
) {
577 nsrv
= NS_ERROR_FAILURE
;
580 for (i
=0; i
< numcerts
; i
++) {
581 CERTCertificate
*cert
= certArray
[i
];
583 cert
= CERT_DupCertificate(cert
);
585 CERT_AddCertToListTail(certList
, cert
);
588 /* go down the remaining list of certs and verify that they have
589 * valid chains, then import them.
592 for (node
= CERT_LIST_HEAD(certList
);
593 !CERT_LIST_END(node
,certList
);
594 node
= CERT_LIST_NEXT(node
)) {
596 bool alert_and_skip
= false;
602 if (CERT_VerifyCert(certdb
, node
->cert
,
603 PR_TRUE
, certusage
, now
, ctx
, NULL
) != SECSuccess
) {
604 alert_and_skip
= true;
607 CERTCertificateList
*certChain
= nsnull
;
608 CERTCertificateListCleaner
chainCleaner(certChain
);
610 if (!alert_and_skip
) {
611 certChain
= CERT_CertChainFromCert(node
->cert
, certusage
, PR_FALSE
);
613 alert_and_skip
= true;
617 if (alert_and_skip
) {
618 nsCOMPtr
<nsIX509Cert
> certToShow
= new nsNSSCertificate(node
->cert
);
619 DisplayCertificateAlert(ctx
, "NotImportingUnverifiedCert", certToShow
);
624 * CertChain returns an array of SECItems, import expects an array of
625 * SECItem pointers. Create the SECItem Pointers from the array of
628 rawArray
= (SECItem
**) PORT_Alloc(certChain
->len
* sizeof(SECItem
*));
632 for (i
=0; i
< certChain
->len
; i
++) {
633 rawArray
[i
] = &certChain
->certs
[i
];
635 CERT_ImportCerts(certdb
, certusage
, certChain
->len
,
636 rawArray
, NULL
, PR_TRUE
, PR_FALSE
, NULL
);
638 CERT_SaveSMimeProfile(node
->cert
, NULL
, NULL
);
645 CERT_DestroyCertArray(certArray
, numcerts
);
648 CERT_DestroyCertList(certList
);
651 PORT_FreeArena(arena
, PR_TRUE
);
656 nsNSSCertificateDB::ImportServerCertificate(PRUint8
* data
, PRUint32 length
,
657 nsIInterfaceRequestor
*ctx
)
660 nsNSSShutDownPreventionLock locker
;
661 SECStatus srv
= SECFailure
;
662 nsresult nsrv
= NS_OK
;
663 CERTCertificate
* cert
;
664 SECItem
**rawCerts
= nsnull
;
667 nsNSSCertTrust trust
;
668 char *serverNickname
= nsnull
;
670 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
672 return NS_ERROR_OUT_OF_MEMORY
;
674 CERTDERCerts
*certCollection
= getCertsFromPackage(arena
, data
, length
);
675 if (!certCollection
) {
676 PORT_FreeArena(arena
, PR_FALSE
);
677 return NS_ERROR_FAILURE
;
679 cert
= CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection
->rawCerts
,
680 (char *)NULL
, PR_FALSE
, PR_TRUE
);
682 nsrv
= NS_ERROR_FAILURE
;
685 numcerts
= certCollection
->numcerts
;
686 rawCerts
= (SECItem
**) PORT_Alloc(sizeof(SECItem
*) * numcerts
);
688 nsrv
= NS_ERROR_FAILURE
;
692 for ( i
= 0; i
< numcerts
; i
++ ) {
693 rawCerts
[i
] = &certCollection
->rawCerts
[i
];
696 serverNickname
= nsNSSCertificate::defaultServerNickname(cert
);
697 srv
= CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageSSLServer
,
698 numcerts
, rawCerts
, NULL
, PR_TRUE
, PR_FALSE
,
700 PR_FREEIF(serverNickname
);
701 if ( srv
!= SECSuccess
) {
702 nsrv
= NS_ERROR_FAILURE
;
706 trust
.SetValidServerPeer();
707 srv
= CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert
, trust
.GetTrust());
708 if ( srv
!= SECSuccess
) {
709 nsrv
= NS_ERROR_FAILURE
;
715 CERT_DestroyCertificate(cert
);
717 PORT_FreeArena(arena
, PR_TRUE
);
722 nsNSSCertificateDB::ImportValidCACerts(int numCACerts
, SECItem
*CACerts
, nsIInterfaceRequestor
*ctx
)
724 CERTCertList
*certList
= NULL
;
727 // build a CertList for filtering
728 certList
= CERT_NewCertList();
729 if (certList
== NULL
) {
730 return NS_ERROR_FAILURE
;
733 CERTCertListCleaner
listCleaner(certList
);
735 // get all certs into temp store
736 SECStatus srv
= SECFailure
;
737 CERTCertificate
**certArray
= NULL
;
739 rawArray
= (SECItem
**) PORT_Alloc(sizeof(SECItem
*) * numCACerts
);
741 return NS_ERROR_FAILURE
;
744 for (int i
=0; i
< numCACerts
; i
++) {
745 rawArray
[i
] = &CACerts
[i
];
748 srv
= CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA
, numCACerts
, rawArray
,
749 &certArray
, PR_FALSE
, PR_TRUE
, NULL
);
754 if (srv
!= SECSuccess
) {
755 return NS_ERROR_FAILURE
;
758 for (int i2
=0; i2
< numCACerts
; i2
++) {
759 CERTCertificate
*cacert
= certArray
[i2
];
761 cacert
= CERT_DupCertificate(cacert
);
763 CERT_AddCertToListTail(certList
, cacert
);
766 CERT_DestroyCertArray(certArray
, numCACerts
);
768 return ImportValidCACertsInList(certList
, ctx
);
772 nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList
*certList
, nsIInterfaceRequestor
*ctx
)
776 /* filter out the certs we don't want */
777 SECStatus srv
= CERT_FilterCertListByUsage(certList
, certUsageAnyCA
, PR_TRUE
);
778 if (srv
!= SECSuccess
) {
779 return NS_ERROR_FAILURE
;
782 /* go down the remaining list of certs and verify that they have
783 * valid chains, if yes, then import.
785 PRTime now
= PR_Now();
786 CERTCertListNode
*node
;
787 for (node
= CERT_LIST_HEAD(certList
);
788 !CERT_LIST_END(node
,certList
);
789 node
= CERT_LIST_NEXT(node
)) {
791 bool alert_and_skip
= false;
793 if (CERT_VerifyCert(CERT_GetDefaultCertDB(), node
->cert
,
794 PR_TRUE
, certUsageVerifyCA
, now
, ctx
, NULL
) != SECSuccess
) {
795 alert_and_skip
= true;
798 CERTCertificateList
*certChain
= nsnull
;
799 CERTCertificateListCleaner
chainCleaner(certChain
);
801 if (!alert_and_skip
) {
802 certChain
= CERT_CertChainFromCert(node
->cert
, certUsageAnyCA
, PR_FALSE
);
804 alert_and_skip
= true;
808 if (alert_and_skip
) {
809 nsCOMPtr
<nsIX509Cert
> certToShow
= new nsNSSCertificate(node
->cert
);
810 DisplayCertificateAlert(ctx
, "NotImportingUnverifiedCert", certToShow
);
815 * CertChain returns an array of SECItems, import expects an array of
816 * SECItem pointers. Create the SECItem Pointers from the array of
819 rawArray
= (SECItem
**) PORT_Alloc(certChain
->len
* sizeof(SECItem
*));
823 for (int i
=0; i
< certChain
->len
; i
++) {
824 rawArray
[i
] = &certChain
->certs
[i
];
826 CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA
, certChain
->len
,
827 rawArray
, NULL
, PR_TRUE
, PR_TRUE
, NULL
);
835 void nsNSSCertificateDB::DisplayCertificateAlert(nsIInterfaceRequestor
*ctx
,
836 const char *stringID
,
837 nsIX509Cert
*certToShow
)
839 nsPSMUITracker tracker
;
840 if (!tracker
.isUIForbidden()) {
842 nsCOMPtr
<nsIInterfaceRequestor
> my_cxt
= ctx
;
844 my_cxt
= new PipUIContext();
846 // This shall be replaced by embedding ovverridable prompts
847 // as discussed in bug 310446, and should make use of certToShow.
850 nsCOMPtr
<nsINSSComponent
> nssComponent(do_GetService(kNSSComponentCID
, &rv
));
851 if (NS_SUCCEEDED(rv
)) {
852 nsAutoString tmpMessage
;
853 nssComponent
->GetPIPNSSBundleString(stringID
, tmpMessage
);
855 // The interface requestor object may not be safe, so proxy the call to get
858 nsCOMPtr
<nsIInterfaceRequestor
> proxiedCallbacks
;
859 NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD
,
860 NS_GET_IID(nsIInterfaceRequestor
),
863 getter_AddRefs(proxiedCallbacks
));
865 nsCOMPtr
<nsIPrompt
> prompt (do_GetInterface(proxiedCallbacks
));
869 // Finally, get a proxy for the nsIPrompt
871 nsCOMPtr
<nsIPrompt
> proxyPrompt
;
872 NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD
,
873 NS_GET_IID(nsIPrompt
),
876 getter_AddRefs(proxyPrompt
));
878 proxyPrompt
->Alert(nsnull
, tmpMessage
.get());
885 nsNSSCertificateDB::ImportUserCertificate(PRUint8
*data
, PRUint32 length
, nsIInterfaceRequestor
*ctx
)
887 nsNSSShutDownPreventionLock locker
;
889 nsCAutoString nickname
;
890 nsresult rv
= NS_ERROR_FAILURE
;
893 CERTDERCerts
* collectArgs
;
895 CERTCertificate
* cert
=NULL
;
897 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
898 if ( arena
== NULL
) {
902 collectArgs
= getCertsFromPackage(arena
, data
, length
);
907 cert
= CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs
->rawCerts
,
908 (char *)NULL
, PR_FALSE
, PR_TRUE
);
913 slot
= PK11_KeyForCertExists(cert
, NULL
, ctx
);
914 if ( slot
== NULL
) {
915 nsCOMPtr
<nsIX509Cert
> certToShow
= new nsNSSCertificate(cert
);
916 DisplayCertificateAlert(ctx
, "UserCertIgnoredNoPrivateKey", certToShow
);
921 /* pick a nickname for the cert */
922 if (cert
->nickname
) {
923 /* sigh, we need a call to look up other certs with this subject and
924 * identify nicknames from them. We can no longer walk down internal
925 * database structures rjr */
926 nickname
= cert
->nickname
;
929 get_default_nickname(cert
, ctx
, nickname
);
932 /* user wants to import the cert */
934 char *cast_const_away
= const_cast<char*>(nickname
.get());
935 slot
= PK11_ImportCertForKey(cert
, cast_const_away
, ctx
);
943 nsCOMPtr
<nsIX509Cert
> certToShow
= new nsNSSCertificate(cert
);
944 DisplayCertificateAlert(ctx
, "UserCertImported", certToShow
);
948 numCACerts
= collectArgs
->numcerts
- 1;
950 CACerts
= collectArgs
->rawCerts
+1;
951 rv
= ImportValidCACerts(numCACerts
, CACerts
, ctx
);
956 PORT_FreeArena(arena
, PR_FALSE
);
959 CERT_DestroyCertificate(cert
);
965 * void deleteCertificate(in nsIX509Cert aCert);
968 nsNSSCertificateDB::DeleteCertificate(nsIX509Cert
*aCert
)
970 nsNSSShutDownPreventionLock locker
;
971 nsCOMPtr
<nsIX509Cert2
> nssCert
= do_QueryInterface(aCert
);
972 CERTCertificate
*cert
= nssCert
->GetCert();
973 if (!cert
) return NS_ERROR_FAILURE
;
974 CERTCertificateCleaner
certCleaner(cert
);
975 SECStatus srv
= SECSuccess
;
978 nssCert
->GetCertType(&certType
);
979 if (NS_FAILED(nssCert
->MarkForPermDeletion()))
981 return NS_ERROR_FAILURE
;
984 if (cert
->slot
&& certType
!= nsIX509Cert::USER_CERT
) {
985 // To delete a cert of a slot (builtin, most likely), mark it as
986 // completely untrusted. This way we keep a copy cached in the
987 // local database, and next time we try to load it off of the
988 // external token/slot, we'll know not to trust it. We don't
989 // want to do that with user certs, because a user may re-store
990 // the cert onto the card again at which point we *will* want to
991 // trust that cert if it chains up properly.
992 nsNSSCertTrust
trust(0, 0, 0);
993 srv
= CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
994 cert
, trust
.GetTrust());
996 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("cert deleted: %d", srv
));
997 return (srv
) ? NS_ERROR_FAILURE
: NS_OK
;
1001 * void setCertTrust(in nsIX509Cert cert,
1002 * in unsigned long type,
1003 * in unsigned long trust);
1006 nsNSSCertificateDB::SetCertTrust(nsIX509Cert
*cert
,
1010 nsNSSShutDownPreventionLock locker
;
1012 nsNSSCertTrust trust
;
1013 nsCOMPtr
<nsIX509Cert2
> pipCert
= do_QueryInterface(cert
);
1015 return NS_ERROR_FAILURE
;
1016 CERTCertificate
*nsscert
= pipCert
->GetCert();
1017 CERTCertificateCleaner
certCleaner(nsscert
);
1018 if (type
== nsIX509Cert::CA_CERT
) {
1019 // always start with untrusted and move up
1021 trust
.AddCATrust(!!(trusted
& nsIX509CertDB::TRUSTED_SSL
),
1022 !!(trusted
& nsIX509CertDB::TRUSTED_EMAIL
),
1023 !!(trusted
& nsIX509CertDB::TRUSTED_OBJSIGN
));
1024 srv
= CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
1027 } else if (type
== nsIX509Cert::SERVER_CERT
) {
1028 // always start with untrusted and move up
1029 trust
.SetValidPeer();
1030 trust
.AddPeerTrust(trusted
& nsIX509CertDB::TRUSTED_SSL
, 0, 0);
1031 srv
= CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
1034 } else if (type
== nsIX509Cert::EMAIL_CERT
) {
1035 // always start with untrusted and move up
1036 trust
.SetValidPeer();
1037 trust
.AddPeerTrust(0, !!(trusted
& nsIX509CertDB::TRUSTED_EMAIL
), 0);
1038 srv
= CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
1042 // ignore user certs
1045 return (srv
) ? NS_ERROR_FAILURE
: NS_OK
;
1049 nsNSSCertificateDB::IsCertTrusted(nsIX509Cert
*cert
,
1054 NS_ENSURE_ARG_POINTER(_isTrusted
);
1055 *_isTrusted
= PR_FALSE
;
1057 nsNSSShutDownPreventionLock locker
;
1059 nsCOMPtr
<nsIX509Cert2
> pipCert
= do_QueryInterface(cert
);
1060 CERTCertificate
*nsscert
= pipCert
->GetCert();
1061 CERTCertTrust nsstrust
;
1062 srv
= CERT_GetCertTrust(nsscert
, &nsstrust
);
1063 if (srv
!= SECSuccess
)
1064 return NS_ERROR_FAILURE
;
1066 nsNSSCertTrust
trust(&nsstrust
);
1067 CERT_DestroyCertificate(nsscert
);
1068 if (certType
== nsIX509Cert::CA_CERT
) {
1069 if (trustType
& nsIX509CertDB::TRUSTED_SSL
) {
1070 *_isTrusted
= trust
.HasTrustedCA(PR_TRUE
, PR_FALSE
, PR_FALSE
);
1071 } else if (trustType
& nsIX509CertDB::TRUSTED_EMAIL
) {
1072 *_isTrusted
= trust
.HasTrustedCA(PR_FALSE
, PR_TRUE
, PR_FALSE
);
1073 } else if (trustType
& nsIX509CertDB::TRUSTED_OBJSIGN
) {
1074 *_isTrusted
= trust
.HasTrustedCA(PR_FALSE
, PR_FALSE
, PR_TRUE
);
1076 return NS_ERROR_FAILURE
;
1078 } else if (certType
== nsIX509Cert::SERVER_CERT
) {
1079 if (trustType
& nsIX509CertDB::TRUSTED_SSL
) {
1080 *_isTrusted
= trust
.HasTrustedPeer(PR_TRUE
, PR_FALSE
, PR_FALSE
);
1081 } else if (trustType
& nsIX509CertDB::TRUSTED_EMAIL
) {
1082 *_isTrusted
= trust
.HasTrustedPeer(PR_FALSE
, PR_TRUE
, PR_FALSE
);
1083 } else if (trustType
& nsIX509CertDB::TRUSTED_OBJSIGN
) {
1084 *_isTrusted
= trust
.HasTrustedPeer(PR_FALSE
, PR_FALSE
, PR_TRUE
);
1086 return NS_ERROR_FAILURE
;
1088 } else if (certType
== nsIX509Cert::EMAIL_CERT
) {
1089 if (trustType
& nsIX509CertDB::TRUSTED_SSL
) {
1090 *_isTrusted
= trust
.HasTrustedPeer(PR_TRUE
, PR_FALSE
, PR_FALSE
);
1091 } else if (trustType
& nsIX509CertDB::TRUSTED_EMAIL
) {
1092 *_isTrusted
= trust
.HasTrustedPeer(PR_FALSE
, PR_TRUE
, PR_FALSE
);
1093 } else if (trustType
& nsIX509CertDB::TRUSTED_OBJSIGN
) {
1094 *_isTrusted
= trust
.HasTrustedPeer(PR_FALSE
, PR_FALSE
, PR_TRUE
);
1096 return NS_ERROR_FAILURE
;
1098 } /* user: ignore */
1104 nsNSSCertificateDB::ImportCertsFromFile(nsISupports
*aToken
,
1105 nsILocalFile
*aFile
,
1108 NS_ENSURE_ARG(aFile
);
1110 case nsIX509Cert::CA_CERT
:
1111 case nsIX509Cert::EMAIL_CERT
:
1112 case nsIX509Cert::SERVER_CERT
:
1117 // not supported (yet)
1118 return NS_ERROR_FAILURE
;
1122 PRFileDesc
*fd
= nsnull
;
1124 rv
= aFile
->OpenNSPRFileDesc(PR_RDONLY
, 0, &fd
);
1130 return NS_ERROR_FAILURE
;
1132 PRFileInfo file_info
;
1133 if (PR_SUCCESS
!= PR_GetOpenFileInfo(fd
, &file_info
))
1134 return NS_ERROR_FAILURE
;
1136 unsigned char *buf
= new unsigned char[file_info
.size
];
1138 return NS_ERROR_OUT_OF_MEMORY
;
1140 PRInt32 bytes_obtained
= PR_Read(fd
, buf
, file_info
.size
);
1143 if (bytes_obtained
!= file_info
.size
)
1144 rv
= NS_ERROR_FAILURE
;
1146 nsCOMPtr
<nsIInterfaceRequestor
> cxt
= new PipUIContext();
1149 case nsIX509Cert::CA_CERT
:
1150 rv
= ImportCertificates(buf
, bytes_obtained
, aType
, cxt
);
1153 case nsIX509Cert::SERVER_CERT
:
1154 rv
= ImportServerCertificate(buf
, bytes_obtained
, cxt
);
1157 case nsIX509Cert::EMAIL_CERT
:
1158 rv
= ImportEmailCertificate(buf
, bytes_obtained
, cxt
);
1171 nsNSSCertificateDB::ImportPKCS12File(nsISupports
*aToken
,
1172 nsILocalFile
*aFile
)
1174 NS_ENSURE_ARG(aFile
);
1176 nsCOMPtr
<nsIPK11Token
> token
= do_QueryInterface(aToken
);
1178 blob
.SetToken(token
);
1180 return blob
.ImportFromFile(aFile
);
1184 nsNSSCertificateDB::ExportPKCS12File(nsISupports
*aToken
,
1185 nsILocalFile
*aFile
,
1187 nsIX509Cert
**certs
)
1188 //const PRUnichar **aCertNames)
1190 nsNSSShutDownPreventionLock locker
;
1191 NS_ENSURE_ARG(aFile
);
1193 if (count
== 0) return NS_OK
;
1194 nsCOMPtr
<nsIPK11Token
> localRef
;
1196 PK11SlotInfo
*keySlot
= PK11_GetInternalKeySlot();
1197 NS_ASSERTION(keySlot
,"Failed to get the internal key slot");
1198 localRef
= new nsPK11Token(keySlot
);
1199 PK11_FreeSlot(keySlot
);
1202 localRef
= do_QueryInterface(aToken
);
1204 blob
.SetToken(localRef
);
1205 //blob.LoadCerts(aCertNames, count);
1206 //return blob.ExportToFile(aFile);
1207 return blob
.ExportToFile(aFile
, certs
, count
);
1211 static SECStatus PR_CALLBACK
1212 GetOCSPResponders (CERTCertificate
*aCert
,
1216 nsIMutableArray
*array
= static_cast<nsIMutableArray
*>(aArg
);
1217 PRUnichar
* nn
= nsnull
;
1218 PRUnichar
* url
= nsnull
;
1219 char *serviceURL
= nsnull
;
1220 char *nickname
= nsnull
;
1224 // Are we interested in this cert //
1225 if (!nsOCSPResponder::IncludeCert(aCert
)) {
1229 // Get the AIA and nickname //
1230 serviceURL
= CERT_GetOCSPAuthorityInfoAccessLocation(aCert
);
1232 url
= ToNewUnicode(NS_ConvertUTF8toUTF16(serviceURL
));
1233 PORT_Free(serviceURL
);
1236 nickname
= aCert
->nickname
;
1237 nn
= ToNewUnicode(NS_ConvertUTF8toUTF16(nickname
));
1239 nsCOMPtr
<nsIOCSPResponder
> new_entry
= new nsOCSPResponder(nn
, url
);
1241 nsMemory::Free(url
);
1243 // Sort the items according to nickname //
1244 rv
= array
->GetLength(&count
);
1245 for (i
=0; i
< count
; ++i
) {
1246 nsCOMPtr
<nsIOCSPResponder
> entry
= do_QueryElementAt(array
, i
);
1247 if (nsOCSPResponder::CompareEntries(new_entry
, entry
) < 0) {
1248 array
->InsertElementAt(new_entry
, i
, PR_FALSE
);
1253 array
->AppendElement(new_entry
, PR_FALSE
);
1263 * Export a set of certs and keys from the database to a PKCS#12 file.
1266 nsNSSCertificateDB::GetOCSPResponders(nsIArray
** aResponders
)
1268 nsNSSShutDownPreventionLock locker
;
1270 nsCOMPtr
<nsIMutableArray
> respondersArray
=
1271 do_CreateInstance(NS_ARRAY_CONTRACTID
);
1272 if (!respondersArray
) {
1273 return NS_ERROR_OUT_OF_MEMORY
;
1276 sec_rv
= PK11_TraverseSlotCerts(::GetOCSPResponders
,
1279 if (sec_rv
!= SECSuccess
) {
1283 *aResponders
= respondersArray
;
1284 NS_IF_ADDREF(*aResponders
);
1287 return NS_ERROR_FAILURE
;
1291 * NSS Helper Routines (private to nsNSSCertificateDB)
1294 #define DELIM '\001'
1299 * Converts a CERTCertList to a list of certificate names
1302 nsNSSCertificateDB::getCertNames(CERTCertList
*certList
,
1305 PRUnichar
***_certNames
)
1307 nsNSSShutDownPreventionLock locker
;
1309 CERTCertListNode
*node
;
1310 PRUint32 numcerts
= 0, i
=0;
1311 PRUnichar
**tmpArray
= NULL
;
1312 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("List of certs %d:\n", type
));
1313 for (node
= CERT_LIST_HEAD(certList
);
1314 !CERT_LIST_END(node
, certList
);
1315 node
= CERT_LIST_NEXT(node
)) {
1316 if (getCertType(node
->cert
) == type
) {
1320 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("num certs: %d\n", numcerts
));
1321 int nc
= (numcerts
== 0) ? 1 : numcerts
;
1322 tmpArray
= (PRUnichar
**)nsMemory::Alloc(sizeof(PRUnichar
*) * nc
);
1323 if (numcerts
== 0) goto finish
;
1324 for (node
= CERT_LIST_HEAD(certList
);
1325 !CERT_LIST_END(node
, certList
);
1326 node
= CERT_LIST_NEXT(node
)) {
1327 if (getCertType(node
->cert
) == type
) {
1328 nsNSSCertificate
pipCert(node
->cert
);
1330 char *namestr
= NULL
;
1331 nsAutoString certstr
;
1332 rv
= pipCert
.GetDbKey(&dbkey
);
1333 nsAutoString keystr
= NS_ConvertASCIItoUTF16(dbkey
);
1335 if (type
== nsIX509Cert::EMAIL_CERT
) {
1336 namestr
= node
->cert
->emailAddr
;
1338 namestr
= node
->cert
->nickname
;
1340 char *sc
= strchr(namestr
, ':');
1341 if (sc
) *sc
= DELIM
;
1344 if (!namestr
) namestr
= "";
1345 nsAutoString certname
= NS_ConvertASCIItoUTF16(namestr
);
1346 certstr
.Append(PRUnichar(DELIM
));
1347 certstr
+= certname
;
1348 certstr
.Append(PRUnichar(DELIM
));
1350 tmpArray
[i
++] = ToNewUnicode(certstr
);
1355 *_certNames
= tmpArray
;
1358 /* somewhat follows logic of cert_list_include_cert from PSM 1.x */
1362 nsNSSCertificateDB::GetIsOcspOn(PRBool
*aOcspOn
)
1364 nsCOMPtr
<nsIPrefBranch
> pref
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
1366 PRInt32 ocspEnabled
;
1367 pref
->GetIntPref("security.OCSP.enabled", &ocspEnabled
);
1368 *aOcspOn
= ( ocspEnabled
== 0 ) ? PR_FALSE
: PR_TRUE
;
1372 /* nsIX509Cert getDefaultEmailEncryptionCert (); */
1374 nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString
&aNickname
, nsIX509Cert
**_retval
)
1377 return NS_ERROR_FAILURE
;
1381 if (aNickname
.IsEmpty())
1384 nsNSSShutDownPreventionLock locker
;
1385 nsresult rv
= NS_OK
;
1386 CERTCertificate
*cert
= 0;
1387 nsCOMPtr
<nsIInterfaceRequestor
> ctx
= new PipUIContext();
1388 nsNSSCertificate
*nssCert
= nsnull
;
1389 char *asciiname
= NULL
;
1390 NS_ConvertUTF16toUTF8
aUtf8Nickname(aNickname
);
1391 asciiname
= const_cast<char*>(aUtf8Nickname
.get());
1393 /* Find a good cert in the user's database */
1394 cert
= CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), asciiname
,
1395 certUsageEmailRecipient
, PR_TRUE
, ctx
);
1397 if (!cert
) { goto loser
; }
1399 nssCert
= new nsNSSCertificate(cert
);
1400 if (nssCert
== nsnull
) {
1401 rv
= NS_ERROR_OUT_OF_MEMORY
;
1405 *_retval
= static_cast<nsIX509Cert
*>(nssCert
);
1408 if (cert
) CERT_DestroyCertificate(cert
);
1412 /* nsIX509Cert getDefaultEmailSigningCert (); */
1414 nsNSSCertificateDB::FindEmailSigningCert(const nsAString
&aNickname
, nsIX509Cert
**_retval
)
1417 return NS_ERROR_FAILURE
;
1421 if (aNickname
.IsEmpty())
1424 nsNSSShutDownPreventionLock locker
;
1425 nsresult rv
= NS_OK
;
1426 CERTCertificate
*cert
= 0;
1427 nsCOMPtr
<nsIInterfaceRequestor
> ctx
= new PipUIContext();
1428 nsNSSCertificate
*nssCert
= nsnull
;
1429 char *asciiname
= NULL
;
1430 NS_ConvertUTF16toUTF8
aUtf8Nickname(aNickname
);
1431 asciiname
= const_cast<char*>(aUtf8Nickname
.get());
1433 /* Find a good cert in the user's database */
1434 cert
= CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), asciiname
,
1435 certUsageEmailSigner
, PR_TRUE
, ctx
);
1437 if (!cert
) { goto loser
; }
1439 nssCert
= new nsNSSCertificate(cert
);
1440 if (nssCert
== nsnull
) {
1441 rv
= NS_ERROR_OUT_OF_MEMORY
;
1445 *_retval
= static_cast<nsIX509Cert
*>(nssCert
);
1448 if (cert
) CERT_DestroyCertificate(cert
);
1453 nsNSSCertificateDB::FindCertByEmailAddress(nsISupports
*aToken
, const char *aEmailAddress
, nsIX509Cert
**_retval
)
1455 nsNSSShutDownPreventionLock locker
;
1456 CERTCertificate
*any_cert
= CERT_FindCertByNicknameOrEmailAddr(CERT_GetDefaultCertDB(), (char*)aEmailAddress
);
1458 return NS_ERROR_FAILURE
;
1460 CERTCertificateCleaner
certCleaner(any_cert
);
1462 // any_cert now contains a cert with the right subject, but it might not have the correct usage
1463 CERTCertList
*certlist
= CERT_CreateSubjectCertList(
1464 nsnull
, CERT_GetDefaultCertDB(), &any_cert
->derSubject
, PR_Now(), PR_TRUE
);
1466 return NS_ERROR_FAILURE
;
1468 CERTCertListCleaner
listCleaner(certlist
);
1470 if (SECSuccess
!= CERT_FilterCertListByUsage(certlist
, certUsageEmailRecipient
, PR_FALSE
))
1471 return NS_ERROR_FAILURE
;
1473 if (CERT_LIST_END(CERT_LIST_HEAD(certlist
), certlist
))
1474 return NS_ERROR_FAILURE
;
1476 nsNSSCertificate
*nssCert
= new nsNSSCertificate(CERT_LIST_HEAD(certlist
)->cert
);
1478 return NS_ERROR_OUT_OF_MEMORY
;
1481 *_retval
= static_cast<nsIX509Cert
*>(nssCert
);
1485 /* nsIX509Cert constructX509FromBase64 (in string base64); */
1487 nsNSSCertificateDB::ConstructX509FromBase64(const char * base64
, nsIX509Cert
**_retval
)
1490 return NS_ERROR_FAILURE
;
1493 nsNSSShutDownPreventionLock locker
;
1494 PRUint32 len
= PL_strlen(base64
);
1497 /* Compute length adjustment */
1498 if (base64
[len
-1] == '=') {
1500 if (base64
[len
-2] == '=') adjust
++;
1503 nsresult rv
= NS_OK
;
1505 PRInt32 lengthDER
= 0;
1507 certDER
= PL_Base64Decode(base64
, len
, NULL
);
1508 if (!certDER
|| !*certDER
) {
1509 rv
= NS_ERROR_ILLEGAL_VALUE
;
1512 lengthDER
= (len
*3)/4 - adjust
;
1514 SECItem secitem_cert
;
1515 secitem_cert
.type
= siDERCertBuffer
;
1516 secitem_cert
.data
= (unsigned char*)certDER
;
1517 secitem_cert
.len
= lengthDER
;
1519 CERTCertificate
*cert
= CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &secitem_cert
, nsnull
, PR_FALSE
, PR_TRUE
);
1522 rv
= NS_ERROR_FAILURE
;
1525 nsNSSCertificate
*nsNSS
= new nsNSSCertificate(cert
);
1527 rv
= NS_ERROR_OUT_OF_MEMORY
;
1530 nsresult rv
= nsNSS
->QueryInterface(NS_GET_IID(nsIX509Cert
), (void**)_retval
);
1532 if (NS_SUCCEEDED(rv
) && *_retval
) {
1533 NS_ADDREF(*_retval
);
1538 CERT_DestroyCertificate(cert
);
1543 nsCRT::free(certDER
);
1549 nsNSSCertificateDB::get_default_nickname(CERTCertificate
*cert
,
1550 nsIInterfaceRequestor
* ctx
,
1551 nsCString
&nickname
)
1553 nickname
.Truncate();
1555 nsNSSShutDownPreventionLock locker
;
1557 CK_OBJECT_HANDLE keyHandle
;
1559 CERTCertDBHandle
*defaultcertdb
= CERT_GetDefaultCertDB();
1560 nsCOMPtr
<nsINSSComponent
> nssComponent(do_GetService(kNSSComponentCID
, &rv
));
1564 nsCAutoString username
;
1565 char *temp_un
= CERT_GetCommonName(&cert
->subject
);
1572 nsCAutoString caname
;
1573 char *temp_ca
= CERT_GetOrgName(&cert
->issuer
);
1580 nsAutoString tmpNickFmt
;
1581 nssComponent
->GetPIPNSSBundleString("nick_template", tmpNickFmt
);
1582 NS_ConvertUTF16toUTF8
nickFmt(tmpNickFmt
);
1584 nsCAutoString baseName
;
1585 char *temp_nn
= PR_smprintf(nickFmt
.get(), username
.get(), caname
.get());
1590 PR_smprintf_free(temp_nn
);
1594 nickname
= baseName
;
1597 * We need to see if the private key exists on a token, if it does
1598 * then we need to check for nicknames that already exist on the smart
1601 PK11SlotInfo
*slot
= PK11_KeyForCertExists(cert
, &keyHandle
, ctx
);
1602 PK11SlotInfoCleaner
slotCleaner(slot
);
1606 if (!PK11_IsInternal(slot
)) {
1607 char *tmp
= PR_smprintf("%s:%s", PK11_GetTokenName(slot
), baseName
.get());
1609 nickname
.Truncate();
1613 PR_smprintf_free(tmp
);
1615 nickname
= baseName
;
1621 char *tmp
= PR_smprintf("%s #%d", baseName
.get(), count
);
1623 nickname
.Truncate();
1627 PR_smprintf_free(tmp
);
1630 CERTCertificate
*dummycert
= nsnull
;
1631 CERTCertificateCleaner
dummycertCleaner(dummycert
);
1633 if (PK11_IsInternal(slot
)) {
1634 /* look up the nickname to make sure it isn't in use already */
1635 dummycert
= CERT_FindCertByNickname(defaultcertdb
, nickname
.get());
1639 * Check the cert against others that already live on the smart
1642 dummycert
= PK11_FindCertFromNickname(nickname
.get(), ctx
);
1643 if (dummycert
!= NULL
) {
1645 * Make sure the subject names are different.
1647 if (CERT_CompareName(&cert
->subject
, &dummycert
->subject
) == SECEqual
)
1650 * There is another certificate with the same nickname and
1651 * the same subject name on the smart card, so let's use this
1654 CERT_DestroyCertificate(dummycert
);
1666 NS_IMETHODIMP
nsNSSCertificateDB::AddCertFromBase64(const char *aBase64
, const char *aTrust
, const char *aName
)
1668 NS_ENSURE_ARG_POINTER(aBase64
);
1669 nsCOMPtr
<nsIX509Cert
> newCert
;
1671 nsNSSCertTrust trust
;
1673 // need to calculate the trust bits from the aTrust string.
1674 nsresult rv
= CERT_DecodeTrustString(trust
.GetTrust(), /* this is const, but not declared that way */(char *) aTrust
);
1675 NS_ENSURE_SUCCESS(rv
, rv
); // if bad trust passed in, return error.
1678 rv
= ConstructX509FromBase64(aBase64
, getter_AddRefs(newCert
));
1679 NS_ENSURE_SUCCESS(rv
, rv
);
1682 rv
= newCert
->GetRawDER(&der
.len
, (PRUint8
**)&der
.data
);
1683 NS_ENSURE_SUCCESS(rv
, rv
);
1685 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("Creating temp cert\n"));
1686 CERTCertificate
*tmpCert
;
1687 CERTCertDBHandle
*certdb
= CERT_GetDefaultCertDB();
1688 tmpCert
= CERT_FindCertByDERCert(certdb
, &der
);
1690 tmpCert
= CERT_NewTempCertificate(certdb
, &der
,
1691 nsnull
, PR_FALSE
, PR_TRUE
);
1692 nsMemory::Free(der
.data
);
1697 NS_ASSERTION(0,"Couldn't create cert from DER blob\n");
1698 return NS_ERROR_FAILURE
;
1701 if (tmpCert
->isperm
) {
1702 CERT_DestroyCertificate(tmpCert
);
1706 CERTCertificateCleaner
tmpCertCleaner(tmpCert
);
1708 nsXPIDLCString nickname
;
1709 nickname
.Adopt(CERT_MakeCANickname(tmpCert
));
1711 PR_LOG(gPIPNSSLog
, PR_LOG_DEBUG
, ("Created nick \"%s\"\n", nickname
.get()));
1713 SECStatus srv
= CERT_AddTempCertToPerm(tmpCert
,
1714 const_cast<char*>(nickname
.get()),
1718 return (srv
== SECSuccess
) ? NS_OK
: NS_ERROR_FAILURE
;
1722 nsNSSCertificateDB::GetCerts(nsIX509CertList
**_retval
)
1724 CERTCertList
*certList
;
1726 nsCOMPtr
<nsIInterfaceRequestor
> ctx
= new PipUIContext();
1727 nsCOMPtr
<nsIX509CertList
> nssCertList
;
1728 certList
= PK11_ListCerts(PK11CertListUnique
, ctx
);
1730 // nsNSSCertList 1) adopts certList, and 2) handles the NULL case fine.
1731 // (returns an empty list)
1732 nssCertList
= new nsNSSCertList(certList
, PR_TRUE
);
1733 if (!nssCertList
) { return NS_ERROR_OUT_OF_MEMORY
; }
1735 *_retval
= nssCertList
;
1736 NS_ADDREF(*_retval
);