2012-05-31 13:33:35 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2012-11-02 23:34:46 +04:00
|
|
|
// XXX: This must be done prior to including cert.h (directly or indirectly).
|
|
|
|
// CERT_AddTempCertToPerm is exposed as __CERT_AddTempCertToPerm, but it is
|
|
|
|
// only exported so PSM can use it for this specific purpose.
|
|
|
|
#define CERT_AddTempCertToPerm __CERT_AddTempCertToPerm
|
|
|
|
|
2012-10-27 11:11:35 +04:00
|
|
|
#include "nsNSSComponent.h"
|
2013-04-16 03:45:11 +04:00
|
|
|
#include "nsNSSCertificateDB.h"
|
2012-10-27 11:11:35 +04:00
|
|
|
|
|
|
|
#include "CertVerifier.h"
|
2014-01-27 07:36:28 +04:00
|
|
|
#include "ExtendedValidation.h"
|
2013-07-09 03:30:59 +04:00
|
|
|
#include "NSSCertDBTrustDomain.h"
|
2014-03-21 01:29:21 +04:00
|
|
|
#include "pkix/pkixtypes.h"
|
2015-09-11 21:52:30 +03:00
|
|
|
#include "pkix/Time.h"
|
2012-10-27 11:11:35 +04:00
|
|
|
#include "nsNSSComponent.h"
|
2012-11-15 03:31:39 +04:00
|
|
|
#include "mozilla/Base64.h"
|
2002-09-17 22:51:22 +04:00
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsNSSCertificate.h"
|
|
|
|
#include "nsNSSHelper.h"
|
|
|
|
#include "nsNSSCertHelper.h"
|
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nsICertificateDialogs.h"
|
|
|
|
#include "nsNSSCertTrust.h"
|
2012-06-06 06:08:30 +04:00
|
|
|
#include "nsIFile.h"
|
2002-09-17 22:51:22 +04:00
|
|
|
#include "nsPKCS12Blob.h"
|
|
|
|
#include "nsPK11TokenDB.h"
|
|
|
|
#include "nsReadableUtils.h"
|
2006-04-12 19:43:32 +04:00
|
|
|
#include "nsIMutableArray.h"
|
|
|
|
#include "nsArrayUtils.h"
|
2003-01-18 17:03:00 +03:00
|
|
|
#include "nsNSSShutDown.h"
|
2004-09-07 22:54:02 +04:00
|
|
|
#include "nsIPrefService.h"
|
|
|
|
#include "nsIPrefBranch.h"
|
2006-04-12 19:43:32 +04:00
|
|
|
#include "nsComponentManagerUtils.h"
|
2006-06-26 21:13:13 +04:00
|
|
|
#include "nsIPrompt.h"
|
2011-11-03 08:02:48 +04:00
|
|
|
#include "nsThreadUtils.h"
|
2012-12-07 07:05:27 +04:00
|
|
|
#include "nsIObserverService.h"
|
2012-12-08 02:50:43 +04:00
|
|
|
#include "SharedSSLState.h"
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
#include "nspr.h"
|
|
|
|
#include "certdb.h"
|
|
|
|
#include "secerr.h"
|
|
|
|
#include "nssb64.h"
|
|
|
|
#include "secasn1.h"
|
|
|
|
#include "secder.h"
|
|
|
|
#include "ssl.h"
|
|
|
|
#include "plbase64.h"
|
|
|
|
|
2016-01-16 01:33:56 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
#include <winsock.h> // for ntohl
|
|
|
|
#endif
|
|
|
|
|
2012-10-18 00:48:36 +04:00
|
|
|
using namespace mozilla;
|
2012-10-27 11:11:35 +04:00
|
|
|
using namespace mozilla::psm;
|
2012-12-08 02:50:43 +04:00
|
|
|
using mozilla::psm::SharedSSLState;
|
2012-10-18 00:48:36 +04:00
|
|
|
|
2016-01-29 21:15:34 +03:00
|
|
|
extern PRLogModuleInfo* gPIPNSSLog;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2014-03-02 07:01:23 +04:00
|
|
|
static nsresult
|
|
|
|
attemptToLogInWithDefaultPassword()
|
|
|
|
{
|
|
|
|
#ifdef NSS_DISABLE_DBM
|
|
|
|
// The SQL NSS DB requires the user to be authenticated to set certificate
|
|
|
|
// trust settings, even if the user's password is empty. To maintain
|
|
|
|
// compatibility with the DBM-based database, try to log in with the
|
|
|
|
// default empty password. This will allow, at least, tests that need to
|
|
|
|
// change certificate trust to pass on all platforms. TODO(bug 978120): Do
|
|
|
|
// proper testing and/or implement a better solution so that we are confident
|
|
|
|
// that this does the correct thing outside of xpcshell tests too.
|
|
|
|
ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
|
|
|
|
if (!slot) {
|
|
|
|
return MapSECStatus(SECFailure);
|
|
|
|
}
|
|
|
|
if (PK11_NeedUserInit(slot)) {
|
|
|
|
// Ignore the return value. Presumably PK11_InitPin will fail if the user
|
|
|
|
// has a non-default password.
|
|
|
|
(void) PK11_InitPin(slot, nullptr, nullptr);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-07-04 09:09:24 +04:00
|
|
|
NS_IMPL_ISUPPORTS(nsNSSCertificateDB, nsIX509CertDB)
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
nsNSSCertificateDB::~nsNSSCertificateDB()
|
|
|
|
{
|
2013-12-19 23:45:50 +04:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
shutdown(calledFromObject);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 11:20:58 +03:00
|
|
|
nsNSSCertificateDB::FindCertByNickname(const nsAString& nickname,
|
|
|
|
nsIX509Cert** _rvCert)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2012-11-12 21:42:28 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(_rvCert);
|
|
|
|
*_rvCert = nullptr;
|
|
|
|
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate cert;
|
2012-10-18 00:48:36 +04:00
|
|
|
char *asciiname = nullptr;
|
2006-02-03 17:18:39 +03:00
|
|
|
NS_ConvertUTF16toUTF8 aUtf8Nickname(nickname);
|
2007-07-08 11:08:04 +04:00
|
|
|
asciiname = const_cast<char*>(aUtf8Nickname.get());
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Getting \"%s\"\n", asciiname));
|
2012-10-18 00:48:36 +04:00
|
|
|
cert = PK11_FindCertFromNickname(asciiname, nullptr);
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!cert) {
|
|
|
|
cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname);
|
|
|
|
}
|
|
|
|
if (cert) {
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("got it\n"));
|
2014-01-23 05:13:19 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert.get());
|
2010-10-26 15:57:18 +04:00
|
|
|
if (pCert) {
|
2012-11-12 21:42:28 +04:00
|
|
|
pCert.forget(_rvCert);
|
2010-10-26 15:57:18 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2016-01-30 11:20:58 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::FindCertByDBKey(const char* aDBkey,nsIX509Cert** _cert)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2012-11-12 21:42:28 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(aDBkey);
|
|
|
|
NS_ENSURE_ARG(aDBkey[0]);
|
|
|
|
NS_ENSURE_ARG_POINTER(_cert);
|
|
|
|
*_cert = nullptr;
|
|
|
|
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2016-01-16 01:33:56 +03:00
|
|
|
static_assert(sizeof(uint64_t) == 8, "type size sanity check");
|
|
|
|
static_assert(sizeof(uint32_t) == 4, "type size sanity check");
|
|
|
|
// (From nsNSSCertificate::GetDbKey)
|
|
|
|
// The format of the key is the base64 encoding of the following:
|
|
|
|
// 4 bytes: {0, 0, 0, 0} (this was intended to be the module ID, but it was
|
|
|
|
// never implemented)
|
|
|
|
// 4 bytes: {0, 0, 0, 0} (this was intended to be the slot ID, but it was
|
|
|
|
// never implemented)
|
|
|
|
// 4 bytes: <serial number length in big-endian order>
|
|
|
|
// 4 bytes: <DER-encoded issuer distinguished name length in big-endian order>
|
|
|
|
// n bytes: <bytes of serial number>
|
|
|
|
// m bytes: <DER-encoded issuer distinguished name>
|
|
|
|
nsAutoCString decoded;
|
|
|
|
nsAutoCString tmpDBKey(aDBkey);
|
|
|
|
// Filter out any whitespace for backwards compatibility.
|
|
|
|
tmpDBKey.StripWhitespace();
|
|
|
|
nsresult rv = Base64Decode(tmpDBKey, decoded);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2007-09-18 00:46:27 +04:00
|
|
|
}
|
2016-01-16 01:33:56 +03:00
|
|
|
if (decoded.Length() < 16) {
|
|
|
|
return NS_ERROR_ILLEGAL_INPUT;
|
|
|
|
}
|
|
|
|
const char* reader = decoded.BeginReading();
|
|
|
|
uint64_t zeroes = *reinterpret_cast<const uint64_t*>(reader);
|
|
|
|
if (zeroes != 0) {
|
|
|
|
return NS_ERROR_ILLEGAL_INPUT;
|
|
|
|
}
|
|
|
|
reader += sizeof(uint64_t);
|
|
|
|
uint32_t serialNumberLen = ntohl(*reinterpret_cast<const uint32_t*>(reader));
|
|
|
|
reader += sizeof(uint32_t);
|
|
|
|
uint32_t issuerLen = ntohl(*reinterpret_cast<const uint32_t*>(reader));
|
|
|
|
reader += sizeof(uint32_t);
|
|
|
|
if (decoded.Length() != 16ULL + serialNumberLen + issuerLen) {
|
|
|
|
return NS_ERROR_ILLEGAL_INPUT;
|
|
|
|
}
|
|
|
|
CERTIssuerAndSN issuerSN;
|
|
|
|
issuerSN.serialNumber.len = serialNumberLen;
|
|
|
|
issuerSN.serialNumber.data = (unsigned char*)reader;
|
|
|
|
reader += serialNumberLen;
|
|
|
|
issuerSN.derIssuer.len = issuerLen;
|
|
|
|
issuerSN.derIssuer.data = (unsigned char*)reader;
|
|
|
|
reader += issuerLen;
|
|
|
|
MOZ_ASSERT(reader == decoded.EndReading());
|
|
|
|
|
|
|
|
ScopedCERTCertificate cert(
|
|
|
|
CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerSN));
|
2002-09-17 22:51:22 +04:00
|
|
|
if (cert) {
|
2014-01-23 05:13:19 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
|
2016-01-16 01:33:56 +03:00
|
|
|
if (!nssCert) {
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2016-01-16 01:33:56 +03:00
|
|
|
}
|
2012-11-12 21:42:28 +04:00
|
|
|
nssCert.forget(_cert);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-09-25 20:18:38 +04:00
|
|
|
SECStatus
|
2002-09-17 22:51:22 +04:00
|
|
|
collect_certs(void *arg, SECItem **certs, int numcerts)
|
|
|
|
{
|
|
|
|
CERTDERCerts *collectArgs;
|
|
|
|
SECItem *cert;
|
|
|
|
SECStatus rv;
|
|
|
|
|
|
|
|
collectArgs = (CERTDERCerts *)arg;
|
|
|
|
|
|
|
|
collectArgs->numcerts = numcerts;
|
|
|
|
collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc(collectArgs->arena,
|
|
|
|
sizeof(SECItem) * numcerts);
|
2012-10-18 00:48:36 +04:00
|
|
|
if (!collectArgs->rawCerts)
|
2002-09-17 22:51:22 +04:00
|
|
|
return(SECFailure);
|
|
|
|
|
|
|
|
cert = collectArgs->rawCerts;
|
|
|
|
|
|
|
|
while ( numcerts-- ) {
|
|
|
|
rv = SECITEM_CopyItem(collectArgs->arena, cert, *certs);
|
|
|
|
if ( rv == SECFailure )
|
|
|
|
return(SECFailure);
|
|
|
|
cert++;
|
|
|
|
certs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (SECSuccess);
|
|
|
|
}
|
|
|
|
|
|
|
|
CERTDERCerts*
|
2012-10-11 10:39:28 +04:00
|
|
|
nsNSSCertificateDB::getCertsFromPackage(PLArenaPool *arena, uint8_t *data,
|
2013-08-30 03:15:35 +04:00
|
|
|
uint32_t length,
|
|
|
|
const nsNSSShutDownPreventionLock &/*proofOfLock*/)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
|
|
|
CERTDERCerts *collectArgs =
|
|
|
|
(CERTDERCerts *)PORT_ArenaZAlloc(arena, sizeof(CERTDERCerts));
|
2012-10-18 00:48:36 +04:00
|
|
|
if (!collectArgs)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
collectArgs->arena = arena;
|
2007-07-08 11:08:04 +04:00
|
|
|
SECStatus sec_rv = CERT_DecodeCertPackage(reinterpret_cast<char *>(data),
|
2002-09-17 22:51:22 +04:00
|
|
|
length, collect_certs,
|
|
|
|
(void *)collectArgs);
|
|
|
|
if (sec_rv != SECSuccess)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
return collectArgs;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2002-10-14 18:49:00 +04:00
|
|
|
nsNSSCertificateDB::handleCACertDownload(nsIArray *x509Certs,
|
2013-08-30 03:15:35 +04:00
|
|
|
nsIInterfaceRequestor *ctx,
|
|
|
|
const nsNSSShutDownPreventionLock &proofOfLock)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
|
|
|
// First thing we have to do is figure out which certificate we're
|
|
|
|
// gonna present to the user. The CA may have sent down a list of
|
|
|
|
// certs which may or may not be a chained list of certs. Until
|
|
|
|
// the day we can design some solid UI for the general case, we'll
|
|
|
|
// code to the > 90% case. That case is where a CA sends down a
|
2005-09-27 02:43:22 +04:00
|
|
|
// list that is a hierarchy whose root is either the first or
|
|
|
|
// the last cert. What we're gonna do is compare the first
|
|
|
|
// 2 entries, if the second was signed by the first, we assume
|
|
|
|
// the root cert is the first cert and display it. Otherwise,
|
|
|
|
// we compare the last 2 entries, if the second to last cert was
|
|
|
|
// signed by the last cert, then we assume the last cert is the
|
|
|
|
// root and display it.
|
2003-01-18 17:03:00 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t numCerts;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2002-10-14 18:49:00 +04:00
|
|
|
x509Certs->GetLength(&numCerts);
|
2002-09-17 22:51:22 +04:00
|
|
|
NS_ASSERTION(numCerts > 0, "Didn't get any certs to import.");
|
|
|
|
if (numCerts == 0)
|
|
|
|
return NS_OK; // Nothing to import, so nothing to do.
|
|
|
|
|
|
|
|
nsCOMPtr<nsIX509Cert> certToShow;
|
|
|
|
nsCOMPtr<nsISupports> isupports;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t selCertIndex;
|
2002-09-17 22:51:22 +04:00
|
|
|
if (numCerts == 1) {
|
|
|
|
// There's only one cert, so let's show it.
|
|
|
|
selCertIndex = 0;
|
2002-10-14 18:49:00 +04:00
|
|
|
certToShow = do_QueryElementAt(x509Certs, selCertIndex);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else {
|
2005-09-27 02:43:22 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> cert0; // first cert
|
|
|
|
nsCOMPtr<nsIX509Cert> cert1; // second cert
|
|
|
|
nsCOMPtr<nsIX509Cert> certn_2; // second to last cert
|
|
|
|
nsCOMPtr<nsIX509Cert> certn_1; // last cert
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2002-10-14 18:49:00 +04:00
|
|
|
cert0 = do_QueryElementAt(x509Certs, 0);
|
|
|
|
cert1 = do_QueryElementAt(x509Certs, 1);
|
2005-09-27 02:43:22 +04:00
|
|
|
certn_2 = do_QueryElementAt(x509Certs, numCerts-2);
|
|
|
|
certn_1 = do_QueryElementAt(x509Certs, numCerts-1);
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
nsXPIDLString cert0SubjectName;
|
|
|
|
nsXPIDLString cert1IssuerName;
|
2005-09-27 02:43:22 +04:00
|
|
|
nsXPIDLString certn_2IssuerName;
|
|
|
|
nsXPIDLString certn_1SubjectName;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2002-09-24 00:17:16 +04:00
|
|
|
cert0->GetSubjectName(cert0SubjectName);
|
|
|
|
cert1->GetIssuerName(cert1IssuerName);
|
2005-09-27 02:43:22 +04:00
|
|
|
certn_2->GetIssuerName(certn_2IssuerName);
|
|
|
|
certn_1->GetSubjectName(certn_1SubjectName);
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2004-01-31 10:09:21 +03:00
|
|
|
if (cert1IssuerName.Equals(cert0SubjectName)) {
|
2002-09-17 22:51:22 +04:00
|
|
|
// In this case, the first cert in the list signed the second,
|
2005-09-27 02:43:22 +04:00
|
|
|
// so the first cert is the root. Let's display it.
|
2002-09-17 22:51:22 +04:00
|
|
|
selCertIndex = 0;
|
|
|
|
certToShow = cert0;
|
2005-09-27 02:43:22 +04:00
|
|
|
} else
|
|
|
|
if (certn_2IssuerName.Equals(certn_1SubjectName)) {
|
|
|
|
// In this case the last cert has signed the second to last cert.
|
|
|
|
// The last cert is the root, so let's display it.
|
|
|
|
selCertIndex = numCerts-1;
|
|
|
|
certToShow = certn_1;
|
2002-09-17 22:51:22 +04:00
|
|
|
} else {
|
|
|
|
// It's not a chain, so let's just show the first one in the
|
|
|
|
// downloaded list.
|
|
|
|
selCertIndex = 0;
|
|
|
|
certToShow = cert0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!certToShow)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsICertificateDialogs> dialogs;
|
|
|
|
nsresult rv = ::getNSSDialogs(getter_AddRefs(dialogs),
|
|
|
|
NS_GET_IID(nsICertificateDialogs),
|
|
|
|
NS_CERTIFICATEDIALOGS_CONTRACTID);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
SECItem der;
|
2012-08-22 19:56:38 +04:00
|
|
|
rv=certToShow->GetRawDER(&der.len, (uint8_t **)&der.data);
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Creating temp cert\n"));
|
2002-09-17 22:51:22 +04:00
|
|
|
CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate tmpCert(CERT_FindCertByDERCert(certdb, &der));
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!tmpCert) {
|
|
|
|
tmpCert = CERT_NewTempCertificate(certdb, &der,
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, false, true);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
2015-03-27 03:01:12 +03:00
|
|
|
free(der.data);
|
2012-07-30 18:20:58 +04:00
|
|
|
der.data = nullptr;
|
2006-02-22 23:36:53 +03:00
|
|
|
der.len = 0;
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!tmpCert) {
|
2010-06-18 00:28:38 +04:00
|
|
|
NS_ERROR("Couldn't create cert from DER blob");
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2014-01-23 05:13:19 +04:00
|
|
|
if (!CERT_IsCACert(tmpCert.get(), nullptr)) {
|
2013-08-30 03:15:35 +04:00
|
|
|
DisplayCertificateAlert(ctx, "NotACACert", certToShow, proofOfLock);
|
2005-09-27 02:43:22 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
if (tmpCert->isperm) {
|
2013-08-30 03:15:35 +04:00
|
|
|
DisplayCertificateAlert(ctx, "CaCertExists", certToShow, proofOfLock);
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t trustBits;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool allows;
|
2002-11-14 03:50:02 +03:00
|
|
|
rv = dialogs->ConfirmDownloadCACert(ctx, certToShow, &trustBits, &allows);
|
2002-09-17 22:51:22 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2002-11-14 03:50:02 +03:00
|
|
|
if (!allows)
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("trust is %d\n", trustBits));
|
2002-09-17 22:51:22 +04:00
|
|
|
nsXPIDLCString nickname;
|
2014-01-23 05:13:19 +04:00
|
|
|
nickname.Adopt(CERT_MakeCANickname(tmpCert.get()));
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Created nick \"%s\"\n", nickname.get()));
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
nsNSSCertTrust trust;
|
|
|
|
trust.SetValidCA();
|
2008-09-26 02:34:22 +04:00
|
|
|
trust.AddCATrust(!!(trustBits & nsIX509CertDB::TRUSTED_SSL),
|
|
|
|
!!(trustBits & nsIX509CertDB::TRUSTED_EMAIL),
|
|
|
|
!!(trustBits & nsIX509CertDB::TRUSTED_OBJSIGN));
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2014-01-23 05:13:19 +04:00
|
|
|
SECStatus srv = __CERT_AddTempCertToPerm(tmpCert.get(),
|
2012-11-02 23:34:46 +04:00
|
|
|
const_cast<char*>(nickname.get()),
|
|
|
|
trust.GetTrust());
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
if (srv != SECSuccess)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2004-07-28 04:31:37 +04:00
|
|
|
// Import additional delivered certificates that can be verified.
|
|
|
|
|
|
|
|
// build a CertList for filtering
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertList certList(CERT_NewCertList());
|
2012-10-18 00:48:36 +04:00
|
|
|
if (!certList) {
|
2004-07-28 04:31:37 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get all remaining certs into temp store
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i=0; i<numCerts; i++) {
|
2004-07-28 04:31:37 +04:00
|
|
|
if (i == selCertIndex) {
|
|
|
|
// we already processed that one
|
2002-09-17 22:51:22 +04:00
|
|
|
continue;
|
2004-07-28 04:31:37 +04:00
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2002-10-14 18:49:00 +04:00
|
|
|
certToShow = do_QueryElementAt(x509Certs, i);
|
2012-08-22 19:56:38 +04:00
|
|
|
certToShow->GetRawDER(&der.len, (uint8_t **)&der.data);
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
CERTCertificate *tmpCert2 =
|
2012-07-30 18:20:58 +04:00
|
|
|
CERT_NewTempCertificate(certdb, &der, nullptr, false, true);
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2015-03-27 03:01:12 +03:00
|
|
|
free(der.data);
|
2012-07-30 18:20:58 +04:00
|
|
|
der.data = nullptr;
|
2006-02-22 23:36:53 +03:00
|
|
|
der.len = 0;
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!tmpCert2) {
|
2010-06-18 00:28:38 +04:00
|
|
|
NS_ERROR("Couldn't create temp cert from DER blob");
|
2002-09-17 22:51:22 +04:00
|
|
|
continue; // Let's try to import the rest of 'em
|
|
|
|
}
|
2004-07-28 04:31:37 +04:00
|
|
|
|
2014-01-23 05:13:19 +04:00
|
|
|
CERT_AddCertToListTail(certList.get(), tmpCert2);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
2004-07-28 04:31:37 +04:00
|
|
|
|
2014-01-23 05:13:19 +04:00
|
|
|
return ImportValidCACertsInList(certList.get(), ctx, proofOfLock);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsNSSCertificateDB::ImportCertificates(uint8_t * data, uint32_t length,
|
|
|
|
uint32_t type,
|
2002-09-17 22:51:22 +04:00
|
|
|
nsIInterfaceRequestor *ctx)
|
|
|
|
|
|
|
|
{
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
nsresult nsrv;
|
|
|
|
|
2012-10-11 10:39:28 +04:00
|
|
|
PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!arena)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2013-08-30 03:15:35 +04:00
|
|
|
CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length, locker);
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!certCollection) {
|
2011-10-17 18:59:28 +04:00
|
|
|
PORT_FreeArena(arena, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2006-04-12 19:43:32 +04:00
|
|
|
nsCOMPtr<nsIMutableArray> array =
|
|
|
|
do_CreateInstance(NS_ARRAY_CONTRACTID, &nsrv);
|
|
|
|
if (NS_FAILED(nsrv)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
PORT_FreeArena(arena, false);
|
2006-04-12 19:43:32 +04:00
|
|
|
return nsrv;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now let's create some certs to work with
|
|
|
|
nsCOMPtr<nsIX509Cert> x509Cert;
|
|
|
|
nsNSSCertificate *nssCert;
|
|
|
|
SECItem *currItem;
|
|
|
|
for (int i=0; i<certCollection->numcerts; i++) {
|
|
|
|
currItem = &certCollection->rawCerts[i];
|
|
|
|
nssCert = nsNSSCertificate::ConstructFromDER((char*)currItem->data, currItem->len);
|
|
|
|
if (!nssCert)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
x509Cert = do_QueryInterface((nsIX509Cert*)nssCert);
|
2011-10-17 18:59:28 +04:00
|
|
|
array->AppendElement(x509Cert, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
switch (type) {
|
|
|
|
case nsIX509Cert::CA_CERT:
|
2013-08-30 03:15:35 +04:00
|
|
|
nsrv = handleCACertDownload(array, ctx, locker);
|
2002-09-17 22:51:22 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// We only deal with import CA certs in this method currently.
|
|
|
|
nsrv = NS_ERROR_FAILURE;
|
|
|
|
break;
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
PORT_FreeArena(arena, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
return nsrv;
|
|
|
|
}
|
|
|
|
|
2012-10-27 11:11:35 +04:00
|
|
|
static
|
|
|
|
SECStatus
|
2014-01-23 05:13:19 +04:00
|
|
|
ImportCertsIntoPermanentStorage(
|
2014-07-07 02:55:38 +04:00
|
|
|
const ScopedCERTCertList& certChain,
|
2014-01-23 05:13:19 +04:00
|
|
|
const SECCertUsage usage, const PRBool caOnly)
|
2012-10-27 11:11:35 +04:00
|
|
|
{
|
|
|
|
CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
|
|
|
|
|
|
|
|
int chainLen = 0;
|
|
|
|
for (CERTCertListNode *chainNode = CERT_LIST_HEAD(certChain);
|
|
|
|
!CERT_LIST_END(chainNode, certChain);
|
|
|
|
chainNode = CERT_LIST_NEXT(chainNode)) {
|
|
|
|
chainLen++;
|
|
|
|
}
|
|
|
|
|
|
|
|
SECItem **rawArray;
|
|
|
|
rawArray = (SECItem **) PORT_Alloc(chainLen * sizeof(SECItem *));
|
|
|
|
if (!rawArray) {
|
|
|
|
return SECFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
for (CERTCertListNode *chainNode = CERT_LIST_HEAD(certChain);
|
|
|
|
!CERT_LIST_END(chainNode, certChain);
|
|
|
|
chainNode = CERT_LIST_NEXT(chainNode), i++) {
|
|
|
|
rawArray[i] = &chainNode->cert->derCert;
|
|
|
|
}
|
2013-11-06 21:30:45 +04:00
|
|
|
SECStatus srv = CERT_ImportCerts(certdb, usage, chainLen, rawArray,
|
|
|
|
nullptr, true, caOnly, nullptr);
|
2012-10-27 11:11:35 +04:00
|
|
|
|
2013-11-06 21:30:45 +04:00
|
|
|
PORT_Free(rawArray);
|
|
|
|
return srv;
|
2012-10-27 11:11:35 +04:00
|
|
|
}
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsNSSCertificateDB::ImportEmailCertificate(uint8_t * data, uint32_t length,
|
2002-09-17 22:51:22 +04:00
|
|
|
nsIInterfaceRequestor *ctx)
|
|
|
|
|
|
|
|
{
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
SECStatus srv = SECFailure;
|
|
|
|
nsresult nsrv = NS_OK;
|
2004-07-28 04:31:37 +04:00
|
|
|
CERTCertDBHandle *certdb;
|
2012-10-18 00:48:36 +04:00
|
|
|
CERTCertificate **certArray = nullptr;
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertList certList;
|
2004-07-28 04:31:37 +04:00
|
|
|
CERTCertListNode *node;
|
|
|
|
SECItem **rawArray;
|
2002-09-17 22:51:22 +04:00
|
|
|
int numcerts;
|
|
|
|
int i;
|
2013-04-16 03:45:11 +04:00
|
|
|
|
2012-10-11 10:39:28 +04:00
|
|
|
PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!arena)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2013-08-30 03:15:35 +04:00
|
|
|
CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length, locker);
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!certCollection) {
|
2011-10-17 18:59:28 +04:00
|
|
|
PORT_FreeArena(arena, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2004-07-28 04:31:37 +04:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
2012-10-27 11:11:35 +04:00
|
|
|
NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
|
|
|
|
|
2004-07-28 04:31:37 +04:00
|
|
|
certdb = CERT_GetDefaultCertDB();
|
|
|
|
|
|
|
|
numcerts = certCollection->numcerts;
|
|
|
|
|
|
|
|
rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
|
|
|
|
if ( !rawArray ) {
|
2002-09-17 22:51:22 +04:00
|
|
|
nsrv = NS_ERROR_FAILURE;
|
|
|
|
goto loser;
|
|
|
|
}
|
2004-07-28 04:31:37 +04:00
|
|
|
|
|
|
|
for (i=0; i < numcerts; i++) {
|
|
|
|
rawArray[i] = &certCollection->rawCerts[i];
|
|
|
|
}
|
|
|
|
|
2012-10-27 11:11:35 +04:00
|
|
|
srv = CERT_ImportCerts(certdb, certUsageEmailRecipient, numcerts, rawArray,
|
2012-10-18 00:48:36 +04:00
|
|
|
&certArray, false, false, nullptr);
|
2004-07-28 04:31:37 +04:00
|
|
|
|
|
|
|
PORT_Free(rawArray);
|
2012-10-18 00:48:36 +04:00
|
|
|
rawArray = nullptr;
|
2004-07-28 04:31:37 +04:00
|
|
|
|
|
|
|
if (srv != SECSuccess) {
|
2002-09-17 22:51:22 +04:00
|
|
|
nsrv = NS_ERROR_FAILURE;
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
|
2004-07-28 04:31:37 +04:00
|
|
|
// build a CertList for filtering
|
|
|
|
certList = CERT_NewCertList();
|
2012-10-18 00:48:36 +04:00
|
|
|
if (!certList) {
|
2004-07-28 04:31:37 +04:00
|
|
|
nsrv = NS_ERROR_FAILURE;
|
|
|
|
goto loser;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
2004-07-28 04:31:37 +04:00
|
|
|
for (i=0; i < numcerts; i++) {
|
|
|
|
CERTCertificate *cert = certArray[i];
|
|
|
|
if (cert)
|
|
|
|
cert = CERT_DupCertificate(cert);
|
|
|
|
if (cert)
|
2014-01-23 05:13:19 +04:00
|
|
|
CERT_AddCertToListTail(certList.get(), cert);
|
2004-07-28 04:31:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* go down the remaining list of certs and verify that they have
|
|
|
|
* valid chains, then import them.
|
|
|
|
*/
|
2011-05-06 00:41:40 +04:00
|
|
|
|
2004-07-28 04:31:37 +04:00
|
|
|
for (node = CERT_LIST_HEAD(certList);
|
|
|
|
!CERT_LIST_END(node,certList);
|
|
|
|
node = CERT_LIST_NEXT(node)) {
|
2006-06-26 21:13:13 +04:00
|
|
|
|
|
|
|
if (!node->cert) {
|
2004-07-28 04:31:37 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-07-07 02:55:38 +04:00
|
|
|
ScopedCERTCertList certChain;
|
2004-07-28 04:31:37 +04:00
|
|
|
|
2014-02-06 02:49:10 +04:00
|
|
|
SECStatus rv = certVerifier->VerifyCert(node->cert,
|
2012-10-27 11:11:35 +04:00
|
|
|
certificateUsageEmailRecipient,
|
2014-08-02 19:49:12 +04:00
|
|
|
mozilla::pkix::Now(), ctx,
|
2016-01-13 23:50:42 +03:00
|
|
|
nullptr, certChain);
|
2013-04-16 03:44:38 +04:00
|
|
|
|
2012-10-27 11:11:35 +04:00
|
|
|
if (rv != SECSuccess) {
|
2010-10-26 15:57:18 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
|
2013-08-30 03:15:35 +04:00
|
|
|
DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow, locker);
|
2006-06-26 21:13:13 +04:00
|
|
|
continue;
|
|
|
|
}
|
2014-01-23 05:13:19 +04:00
|
|
|
rv = ImportCertsIntoPermanentStorage(certChain, certUsageEmailRecipient,
|
|
|
|
false);
|
2012-10-27 11:11:35 +04:00
|
|
|
if (rv != SECSuccess) {
|
|
|
|
goto loser;
|
|
|
|
}
|
2012-10-18 00:48:36 +04:00
|
|
|
CERT_SaveSMimeProfile(node->cert, nullptr, nullptr);
|
2004-07-28 04:31:37 +04:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
loser:
|
2004-07-28 04:31:37 +04:00
|
|
|
if (certArray) {
|
|
|
|
CERT_DestroyCertArray(certArray, numcerts);
|
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
if (arena)
|
2011-10-17 18:59:28 +04:00
|
|
|
PORT_FreeArena(arena, true);
|
2002-09-17 22:51:22 +04:00
|
|
|
return nsrv;
|
|
|
|
}
|
|
|
|
|
2004-07-28 04:31:37 +04:00
|
|
|
nsresult
|
2013-08-30 03:15:35 +04:00
|
|
|
nsNSSCertificateDB::ImportValidCACerts(int numCACerts, SECItem *CACerts, nsIInterfaceRequestor *ctx, const nsNSSShutDownPreventionLock &proofOfLock)
|
2004-07-28 04:31:37 +04:00
|
|
|
{
|
2012-11-12 21:42:28 +04:00
|
|
|
ScopedCERTCertList certList;
|
2004-07-28 04:31:37 +04:00
|
|
|
SECItem **rawArray;
|
|
|
|
|
|
|
|
// build a CertList for filtering
|
|
|
|
certList = CERT_NewCertList();
|
2012-10-18 00:48:36 +04:00
|
|
|
if (!certList) {
|
2004-07-28 04:31:37 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get all certs into temp store
|
|
|
|
SECStatus srv = SECFailure;
|
2012-10-18 00:48:36 +04:00
|
|
|
CERTCertificate **certArray = nullptr;
|
2004-07-28 04:31:37 +04:00
|
|
|
|
|
|
|
rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numCACerts);
|
|
|
|
if ( !rawArray ) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i=0; i < numCACerts; i++) {
|
|
|
|
rawArray[i] = &CACerts[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, numCACerts, rawArray,
|
2012-10-18 00:48:36 +04:00
|
|
|
&certArray, false, true, nullptr);
|
2004-07-28 04:31:37 +04:00
|
|
|
|
|
|
|
PORT_Free(rawArray);
|
2012-10-18 00:48:36 +04:00
|
|
|
rawArray = nullptr;
|
2004-07-28 04:31:37 +04:00
|
|
|
|
|
|
|
if (srv != SECSuccess) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i2=0; i2 < numCACerts; i2++) {
|
|
|
|
CERTCertificate *cacert = certArray[i2];
|
|
|
|
if (cacert)
|
|
|
|
cacert = CERT_DupCertificate(cacert);
|
|
|
|
if (cacert)
|
|
|
|
CERT_AddCertToListTail(certList, cacert);
|
|
|
|
}
|
|
|
|
|
|
|
|
CERT_DestroyCertArray(certArray, numCACerts);
|
|
|
|
|
2013-08-30 03:15:35 +04:00
|
|
|
return ImportValidCACertsInList(certList, ctx, proofOfLock);
|
2004-07-28 04:31:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2013-08-30 03:15:35 +04:00
|
|
|
nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx,
|
|
|
|
const nsNSSShutDownPreventionLock &proofOfLock)
|
2004-07-28 04:31:37 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
2012-10-27 11:11:35 +04:00
|
|
|
if (!certVerifier)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
2004-07-28 04:31:37 +04:00
|
|
|
|
|
|
|
/* filter out the certs we don't want */
|
2011-10-17 18:59:28 +04:00
|
|
|
SECStatus srv = CERT_FilterCertListByUsage(certList, certUsageAnyCA, true);
|
2004-07-28 04:31:37 +04:00
|
|
|
if (srv != SECSuccess) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* go down the remaining list of certs and verify that they have
|
|
|
|
* valid chains, if yes, then import.
|
|
|
|
*/
|
|
|
|
CERTCertListNode *node;
|
2011-05-06 00:41:40 +04:00
|
|
|
|
2004-07-28 04:31:37 +04:00
|
|
|
for (node = CERT_LIST_HEAD(certList);
|
|
|
|
!CERT_LIST_END(node,certList);
|
|
|
|
node = CERT_LIST_NEXT(node)) {
|
2014-07-07 02:55:38 +04:00
|
|
|
ScopedCERTCertList certChain;
|
2014-02-06 02:49:10 +04:00
|
|
|
SECStatus rv = certVerifier->VerifyCert(node->cert,
|
2013-09-28 06:53:36 +04:00
|
|
|
certificateUsageVerifyCA,
|
2014-08-02 19:49:12 +04:00
|
|
|
mozilla::pkix::Now(), ctx,
|
2016-01-13 23:50:42 +03:00
|
|
|
nullptr, certChain);
|
2012-10-27 11:11:35 +04:00
|
|
|
if (rv != SECSuccess) {
|
2010-10-26 15:57:18 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
|
2013-08-30 03:15:35 +04:00
|
|
|
DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow, proofOfLock);
|
2006-06-26 21:13:13 +04:00
|
|
|
continue;
|
|
|
|
}
|
2004-07-28 04:31:37 +04:00
|
|
|
|
2013-11-06 21:30:45 +04:00
|
|
|
rv = ImportCertsIntoPermanentStorage(certChain, certUsageAnyCA, true);
|
|
|
|
if (rv != SECSuccess) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2004-07-28 04:31:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2006-06-26 21:13:13 +04:00
|
|
|
void nsNSSCertificateDB::DisplayCertificateAlert(nsIInterfaceRequestor *ctx,
|
|
|
|
const char *stringID,
|
2013-08-30 03:15:35 +04:00
|
|
|
nsIX509Cert *certToShow,
|
|
|
|
const nsNSSShutDownPreventionLock &/*proofOfLock*/)
|
2006-06-26 21:13:13 +04:00
|
|
|
{
|
2013-11-26 22:18:21 +04:00
|
|
|
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
|
|
|
|
|
2011-11-03 08:02:48 +04:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
NS_ERROR("nsNSSCertificateDB::DisplayCertificateAlert called off the main thread");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
bug 1215690 - remove nsPSMUITracker r=Cykesiopka r=mgoodwin
nsPSMUITracker was problematic. Apparently it was originally intended to prevent
NSS shutdown while NSS-related UI operations were going on (such as choosing a
client certificate). However, when nsNSSComponent would receive the event that
told it to shutdown NSS, it would attempt to call
mShutdownObjectList->evaporateAllNSSResources(), which would call
mActivityState.restrictActivityToCurrentThread(), which failed if such a UI
operation was in progress. This actually prevented the important part of
evaporateAllNSSResources, which is the releasing of all NSS objects in use by
PSM objects. Importantly, nsNSSComponent didn't check for or handle this failure
and proceeded to call NSS_Shutdown(), leaving PSM in an inconsistent state where
it thought it was okay to keep using the NSS objects it had when in fact it
wasn't.
In any case, nsPSMUITracker isn't really necessary as long as we have the
nsNSSShutDownPreventionLock mechanism, which mostly works and is what we should
use instead (or not at all, if no such lock is needed for the operation being
performed (for example, if no NSS functions are being called)).
2015-10-17 00:31:57 +03:00
|
|
|
nsCOMPtr<nsIInterfaceRequestor> my_ctx = ctx;
|
|
|
|
if (!my_ctx) {
|
|
|
|
my_ctx = new PipUIContext();
|
|
|
|
}
|
2006-12-06 19:31:32 +03:00
|
|
|
|
bug 1215690 - remove nsPSMUITracker r=Cykesiopka r=mgoodwin
nsPSMUITracker was problematic. Apparently it was originally intended to prevent
NSS shutdown while NSS-related UI operations were going on (such as choosing a
client certificate). However, when nsNSSComponent would receive the event that
told it to shutdown NSS, it would attempt to call
mShutdownObjectList->evaporateAllNSSResources(), which would call
mActivityState.restrictActivityToCurrentThread(), which failed if such a UI
operation was in progress. This actually prevented the important part of
evaporateAllNSSResources, which is the releasing of all NSS objects in use by
PSM objects. Importantly, nsNSSComponent didn't check for or handle this failure
and proceeded to call NSS_Shutdown(), leaving PSM in an inconsistent state where
it thought it was okay to keep using the NSS objects it had when in fact it
wasn't.
In any case, nsPSMUITracker isn't really necessary as long as we have the
nsNSSShutDownPreventionLock mechanism, which mostly works and is what we should
use instead (or not at all, if no such lock is needed for the operation being
performed (for example, if no NSS functions are being called)).
2015-10-17 00:31:57 +03:00
|
|
|
// This shall be replaced by embedding ovverridable prompts
|
|
|
|
// as discussed in bug 310446, and should make use of certToShow.
|
2006-06-26 21:13:13 +04:00
|
|
|
|
bug 1215690 - remove nsPSMUITracker r=Cykesiopka r=mgoodwin
nsPSMUITracker was problematic. Apparently it was originally intended to prevent
NSS shutdown while NSS-related UI operations were going on (such as choosing a
client certificate). However, when nsNSSComponent would receive the event that
told it to shutdown NSS, it would attempt to call
mShutdownObjectList->evaporateAllNSSResources(), which would call
mActivityState.restrictActivityToCurrentThread(), which failed if such a UI
operation was in progress. This actually prevented the important part of
evaporateAllNSSResources, which is the releasing of all NSS objects in use by
PSM objects. Importantly, nsNSSComponent didn't check for or handle this failure
and proceeded to call NSS_Shutdown(), leaving PSM in an inconsistent state where
it thought it was okay to keep using the NSS objects it had when in fact it
wasn't.
In any case, nsPSMUITracker isn't really necessary as long as we have the
nsNSSShutDownPreventionLock mechanism, which mostly works and is what we should
use instead (or not at all, if no such lock is needed for the operation being
performed (for example, if no NSS functions are being called)).
2015-10-17 00:31:57 +03:00
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsAutoString tmpMessage;
|
|
|
|
nssComponent->GetPIPNSSBundleString(stringID, tmpMessage);
|
2006-06-26 21:13:13 +04:00
|
|
|
|
bug 1215690 - remove nsPSMUITracker r=Cykesiopka r=mgoodwin
nsPSMUITracker was problematic. Apparently it was originally intended to prevent
NSS shutdown while NSS-related UI operations were going on (such as choosing a
client certificate). However, when nsNSSComponent would receive the event that
told it to shutdown NSS, it would attempt to call
mShutdownObjectList->evaporateAllNSSResources(), which would call
mActivityState.restrictActivityToCurrentThread(), which failed if such a UI
operation was in progress. This actually prevented the important part of
evaporateAllNSSResources, which is the releasing of all NSS objects in use by
PSM objects. Importantly, nsNSSComponent didn't check for or handle this failure
and proceeded to call NSS_Shutdown(), leaving PSM in an inconsistent state where
it thought it was okay to keep using the NSS objects it had when in fact it
wasn't.
In any case, nsPSMUITracker isn't really necessary as long as we have the
nsNSSShutDownPreventionLock mechanism, which mostly works and is what we should
use instead (or not at all, if no such lock is needed for the operation being
performed (for example, if no NSS functions are being called)).
2015-10-17 00:31:57 +03:00
|
|
|
nsCOMPtr<nsIPrompt> prompt (do_GetInterface(my_ctx));
|
|
|
|
if (!prompt) {
|
|
|
|
return;
|
2006-06-26 21:13:13 +04:00
|
|
|
}
|
bug 1215690 - remove nsPSMUITracker r=Cykesiopka r=mgoodwin
nsPSMUITracker was problematic. Apparently it was originally intended to prevent
NSS shutdown while NSS-related UI operations were going on (such as choosing a
client certificate). However, when nsNSSComponent would receive the event that
told it to shutdown NSS, it would attempt to call
mShutdownObjectList->evaporateAllNSSResources(), which would call
mActivityState.restrictActivityToCurrentThread(), which failed if such a UI
operation was in progress. This actually prevented the important part of
evaporateAllNSSResources, which is the releasing of all NSS objects in use by
PSM objects. Importantly, nsNSSComponent didn't check for or handle this failure
and proceeded to call NSS_Shutdown(), leaving PSM in an inconsistent state where
it thought it was okay to keep using the NSS objects it had when in fact it
wasn't.
In any case, nsPSMUITracker isn't really necessary as long as we have the
nsNSSShutDownPreventionLock mechanism, which mostly works and is what we should
use instead (or not at all, if no such lock is needed for the operation being
performed (for example, if no NSS functions are being called)).
2015-10-17 00:31:57 +03:00
|
|
|
|
|
|
|
prompt->Alert(nullptr, tmpMessage.get());
|
2006-06-26 21:13:13 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-28 04:31:37 +04:00
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsNSSCertificateDB::ImportUserCertificate(uint8_t *data, uint32_t length, nsIInterfaceRequestor *ctx)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2011-11-03 08:02:48 +04:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
NS_ERROR("nsNSSCertificateDB::ImportUserCertificate called off the main thread");
|
|
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
|
|
}
|
|
|
|
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2012-11-12 21:42:28 +04:00
|
|
|
ScopedPK11SlotInfo slot;
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString nickname;
|
2002-09-17 22:51:22 +04:00
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
int numCACerts;
|
|
|
|
SECItem *CACerts;
|
|
|
|
CERTDERCerts * collectArgs;
|
2012-10-11 10:39:28 +04:00
|
|
|
PLArenaPool *arena;
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate cert;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
2012-10-18 00:48:36 +04:00
|
|
|
if (!arena) {
|
2002-09-17 22:51:22 +04:00
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
|
2013-08-30 03:15:35 +04:00
|
|
|
collectArgs = getCertsFromPackage(arena, data, length, locker);
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!collectArgs) {
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
|
|
|
|
cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs->rawCerts,
|
2012-10-18 00:48:36 +04:00
|
|
|
nullptr, false, true);
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!cert) {
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
|
2014-01-23 05:13:19 +04:00
|
|
|
slot = PK11_KeyForCertExists(cert.get(), nullptr, ctx);
|
2012-10-18 00:48:36 +04:00
|
|
|
if (!slot) {
|
2014-01-23 05:13:19 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert.get());
|
2013-08-30 03:15:35 +04:00
|
|
|
DisplayCertificateAlert(ctx, "UserCertIgnoredNoPrivateKey", certToShow, locker);
|
2002-09-17 22:51:22 +04:00
|
|
|
goto loser;
|
|
|
|
}
|
2012-11-12 21:42:28 +04:00
|
|
|
slot = nullptr;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
/* pick a nickname for the cert */
|
|
|
|
if (cert->nickname) {
|
|
|
|
/* sigh, we need a call to look up other certs with this subject and
|
|
|
|
* identify nicknames from them. We can no longer walk down internal
|
|
|
|
* database structures rjr */
|
|
|
|
nickname = cert->nickname;
|
|
|
|
}
|
|
|
|
else {
|
2014-01-23 05:13:19 +04:00
|
|
|
get_default_nickname(cert.get(), ctx, nickname, locker);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* user wants to import the cert */
|
2008-06-11 22:20:24 +04:00
|
|
|
{
|
|
|
|
char *cast_const_away = const_cast<char*>(nickname.get());
|
2014-01-23 05:13:19 +04:00
|
|
|
slot = PK11_ImportCertForKey(cert.get(), cast_const_away, ctx);
|
2008-06-11 22:20:24 +04:00
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!slot) {
|
|
|
|
goto loser;
|
|
|
|
}
|
2012-11-12 21:42:28 +04:00
|
|
|
slot = nullptr;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2006-06-26 21:13:13 +04:00
|
|
|
{
|
2014-01-23 05:13:19 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert.get());
|
2013-08-30 03:15:35 +04:00
|
|
|
DisplayCertificateAlert(ctx, "UserCertImported", certToShow, locker);
|
2006-06-26 21:13:13 +04:00
|
|
|
}
|
2004-07-28 04:31:37 +04:00
|
|
|
rv = NS_OK;
|
|
|
|
|
|
|
|
numCACerts = collectArgs->numcerts - 1;
|
2002-09-17 22:51:22 +04:00
|
|
|
if (numCACerts) {
|
|
|
|
CACerts = collectArgs->rawCerts+1;
|
2013-08-30 03:15:35 +04:00
|
|
|
rv = ImportValidCACerts(numCACerts, CACerts, ctx, locker);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
loser:
|
|
|
|
if (arena) {
|
2011-10-17 18:59:28 +04:00
|
|
|
PORT_FreeArena(arena, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert)
|
|
|
|
{
|
2015-05-28 00:12:26 +03:00
|
|
|
NS_ENSURE_ARG_POINTER(aCert);
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate cert(aCert->GetCert());
|
2014-07-04 09:09:24 +04:00
|
|
|
if (!cert) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
SECStatus srv = SECSuccess;
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t certType;
|
2014-07-04 09:09:24 +04:00
|
|
|
aCert->GetCertType(&certType);
|
|
|
|
if (NS_FAILED(aCert->MarkForPermDeletion()))
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cert->slot && certType != nsIX509Cert::USER_CERT) {
|
|
|
|
// To delete a cert of a slot (builtin, most likely), mark it as
|
|
|
|
// completely untrusted. This way we keep a copy cached in the
|
|
|
|
// local database, and next time we try to load it off of the
|
|
|
|
// external token/slot, we'll know not to trust it. We don't
|
|
|
|
// want to do that with user certs, because a user may re-store
|
|
|
|
// the cert onto the card again at which point we *will* want to
|
|
|
|
// trust that cert if it chains up properly.
|
|
|
|
nsNSSCertTrust trust(0, 0, 0);
|
|
|
|
srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
|
2014-01-23 05:13:19 +04:00
|
|
|
cert.get(), trust.GetTrust());
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("cert deleted: %d", srv));
|
2002-09-17 22:51:22 +04:00
|
|
|
return (srv) ? NS_ERROR_FAILURE : NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::SetCertTrust(nsIX509Cert *cert,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t type,
|
|
|
|
uint32_t trusted)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2015-05-28 00:12:26 +03:00
|
|
|
NS_ENSURE_ARG_POINTER(cert);
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
nsNSSCertTrust trust;
|
2014-02-28 23:19:38 +04:00
|
|
|
nsresult rv;
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate nsscert(cert->GetCert());
|
2012-11-12 21:42:28 +04:00
|
|
|
|
2014-03-02 07:01:23 +04:00
|
|
|
rv = attemptToLogInWithDefaultPassword();
|
|
|
|
if (NS_WARN_IF(rv != NS_OK)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2014-02-28 23:19:38 +04:00
|
|
|
SECStatus srv;
|
2002-09-17 22:51:22 +04:00
|
|
|
if (type == nsIX509Cert::CA_CERT) {
|
|
|
|
// always start with untrusted and move up
|
|
|
|
trust.SetValidCA();
|
2008-09-26 02:34:22 +04:00
|
|
|
trust.AddCATrust(!!(trusted & nsIX509CertDB::TRUSTED_SSL),
|
|
|
|
!!(trusted & nsIX509CertDB::TRUSTED_EMAIL),
|
|
|
|
!!(trusted & nsIX509CertDB::TRUSTED_OBJSIGN));
|
2002-09-17 22:51:22 +04:00
|
|
|
srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
|
2014-01-23 05:13:19 +04:00
|
|
|
nsscert.get(),
|
2002-09-17 22:51:22 +04:00
|
|
|
trust.GetTrust());
|
|
|
|
} else if (type == nsIX509Cert::SERVER_CERT) {
|
|
|
|
// always start with untrusted and move up
|
|
|
|
trust.SetValidPeer();
|
|
|
|
trust.AddPeerTrust(trusted & nsIX509CertDB::TRUSTED_SSL, 0, 0);
|
|
|
|
srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
|
2014-01-23 05:13:19 +04:00
|
|
|
nsscert.get(),
|
2002-09-17 22:51:22 +04:00
|
|
|
trust.GetTrust());
|
|
|
|
} else if (type == nsIX509Cert::EMAIL_CERT) {
|
|
|
|
// always start with untrusted and move up
|
|
|
|
trust.SetValidPeer();
|
2008-09-26 02:34:22 +04:00
|
|
|
trust.AddPeerTrust(0, !!(trusted & nsIX509CertDB::TRUSTED_EMAIL), 0);
|
2002-09-17 22:51:22 +04:00
|
|
|
srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(),
|
2014-01-23 05:13:19 +04:00
|
|
|
nsscert.get(),
|
2002-09-17 22:51:22 +04:00
|
|
|
trust.GetTrust());
|
|
|
|
} else {
|
|
|
|
// ignore user certs
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-02-28 23:19:38 +04:00
|
|
|
return MapSECStatus(srv);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-11-14 03:50:02 +03:00
|
|
|
nsNSSCertificateDB::IsCertTrusted(nsIX509Cert *cert,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t certType,
|
|
|
|
uint32_t trustType,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool *_isTrusted)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2005-09-04 23:05:01 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(_isTrusted);
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = false;
|
2005-09-04 23:05:01 +04:00
|
|
|
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
SECStatus srv;
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate nsscert(cert->GetCert());
|
2002-09-17 22:51:22 +04:00
|
|
|
CERTCertTrust nsstrust;
|
2014-01-23 05:13:19 +04:00
|
|
|
srv = CERT_GetCertTrust(nsscert.get(), &nsstrust);
|
2005-09-04 23:05:01 +04:00
|
|
|
if (srv != SECSuccess)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
nsNSSCertTrust trust(&nsstrust);
|
|
|
|
if (certType == nsIX509Cert::CA_CERT) {
|
|
|
|
if (trustType & nsIX509CertDB::TRUSTED_SSL) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = trust.HasTrustedCA(true, false, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = trust.HasTrustedCA(false, true, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = trust.HasTrustedCA(false, false, true);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
} else if (certType == nsIX509Cert::SERVER_CERT) {
|
|
|
|
if (trustType & nsIX509CertDB::TRUSTED_SSL) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = trust.HasTrustedPeer(true, false, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = trust.HasTrustedPeer(false, true, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = trust.HasTrustedPeer(false, false, true);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
} else if (certType == nsIX509Cert::EMAIL_CERT) {
|
|
|
|
if (trustType & nsIX509CertDB::TRUSTED_SSL) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = trust.HasTrustedPeer(true, false, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = trust.HasTrustedPeer(false, true, false);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
|
2011-10-17 18:59:28 +04:00
|
|
|
*_isTrusted = trust.HasTrustedPeer(false, false, true);
|
2002-09-17 22:51:22 +04:00
|
|
|
} else {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
} /* user: ignore */
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-30 11:20:58 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::ImportCertsFromFile(nsIFile* aFile, uint32_t aType)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2013-08-30 03:15:35 +04:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2007-07-23 14:48:51 +04:00
|
|
|
NS_ENSURE_ARG(aFile);
|
2002-09-17 22:51:22 +04:00
|
|
|
switch (aType) {
|
|
|
|
case nsIX509Cert::CA_CERT:
|
|
|
|
case nsIX509Cert::EMAIL_CERT:
|
|
|
|
// good
|
|
|
|
break;
|
2016-01-30 11:20:58 +03:00
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
default:
|
|
|
|
// not supported (yet)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2016-02-07 07:41:11 +03:00
|
|
|
PRFileDesc* fd = nullptr;
|
|
|
|
nsresult rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
|
|
|
|
if (NS_FAILED(rv)) {
|
2002-09-17 22:51:22 +04:00
|
|
|
return rv;
|
2016-02-07 07:41:11 +03:00
|
|
|
}
|
|
|
|
if (!fd) {
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
2016-02-07 07:41:11 +03:00
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2016-02-07 07:41:11 +03:00
|
|
|
PRFileInfo fileInfo;
|
|
|
|
if (PR_GetOpenFileInfo(fd, &fileInfo) != PR_SUCCESS) {
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
2016-02-07 07:41:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
auto buf = MakeUnique<unsigned char[]>(fileInfo.size);
|
|
|
|
int32_t bytesObtained = PR_Read(fd, buf.get(), fileInfo.size);
|
2002-09-17 22:51:22 +04:00
|
|
|
PR_Close(fd);
|
2016-02-07 07:41:11 +03:00
|
|
|
|
|
|
|
if (bytesObtained != fileInfo.size) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
2016-02-07 07:41:11 +03:00
|
|
|
nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
|
|
|
|
|
|
|
|
switch (aType) {
|
|
|
|
case nsIX509Cert::CA_CERT:
|
|
|
|
return ImportCertificates(buf.get(), bytesObtained, aType, cxt);
|
|
|
|
case nsIX509Cert::EMAIL_CERT:
|
|
|
|
return ImportEmailCertificate(buf.get(), bytesObtained, cxt);
|
|
|
|
default:
|
|
|
|
MOZ_ASSERT(false, "Unsupported type should have been filtered out");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_FAILURE;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 11:20:58 +03:00
|
|
|
nsNSSCertificateDB::ImportPKCS12File(nsISupports* aToken, nsIFile* aFile)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2013-08-30 03:15:35 +04:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
NS_ENSURE_ARG(aFile);
|
|
|
|
nsPKCS12Blob blob;
|
2004-11-05 18:23:35 +03:00
|
|
|
nsCOMPtr<nsIPK11Token> token = do_QueryInterface(aToken);
|
|
|
|
if (token) {
|
|
|
|
blob.SetToken(token);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
return blob.ImportFromFile(aFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 11:20:58 +03:00
|
|
|
nsNSSCertificateDB::ExportPKCS12File(nsISupports* aToken,
|
|
|
|
nsIFile* aFile,
|
|
|
|
uint32_t count,
|
|
|
|
nsIX509Cert** certs)
|
2014-01-04 19:02:17 +04:00
|
|
|
//const char16_t **aCertNames)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
NS_ENSURE_ARG(aFile);
|
|
|
|
nsPKCS12Blob blob;
|
|
|
|
if (count == 0) return NS_OK;
|
|
|
|
nsCOMPtr<nsIPK11Token> localRef;
|
|
|
|
if (!aToken) {
|
2012-11-12 21:42:28 +04:00
|
|
|
ScopedPK11SlotInfo keySlot(PK11_GetInternalKeySlot());
|
2002-09-17 22:51:22 +04:00
|
|
|
NS_ASSERTION(keySlot,"Failed to get the internal key slot");
|
|
|
|
localRef = new nsPK11Token(keySlot);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
localRef = do_QueryInterface(aToken);
|
|
|
|
}
|
|
|
|
blob.SetToken(localRef);
|
|
|
|
//blob.LoadCerts(aCertNames, count);
|
|
|
|
//return blob.ExportToFile(aFile);
|
|
|
|
return blob.ExportToFile(aFile, certs, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2014-07-04 09:09:24 +04:00
|
|
|
nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString& aNickname,
|
|
|
|
nsIX509Cert** _retval)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2012-11-12 21:42:28 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
*_retval = nullptr;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2002-09-24 00:17:16 +04:00
|
|
|
if (aNickname.IsEmpty())
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
|
2012-10-18 00:48:36 +04:00
|
|
|
char *asciiname = nullptr;
|
2006-02-03 17:18:39 +03:00
|
|
|
NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
|
2007-07-08 11:08:04 +04:00
|
|
|
asciiname = const_cast<char*>(aUtf8Nickname.get());
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
/* Find a good cert in the user's database */
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate cert(CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
|
|
|
|
asciiname,
|
|
|
|
certUsageEmailRecipient,
|
|
|
|
true, ctx));
|
2012-11-12 21:42:28 +04:00
|
|
|
if (!cert) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2014-01-23 05:13:19 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
|
2012-10-18 00:48:36 +04:00
|
|
|
if (!nssCert) {
|
2012-11-12 21:42:28 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
2012-11-12 21:42:28 +04:00
|
|
|
nssCert.forget(_retval);
|
|
|
|
return NS_OK;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2014-07-04 09:09:24 +04:00
|
|
|
nsNSSCertificateDB::FindEmailSigningCert(const nsAString& aNickname,
|
|
|
|
nsIX509Cert** _retval)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2012-11-12 21:42:28 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
*_retval = nullptr;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2002-09-24 00:17:16 +04:00
|
|
|
if (aNickname.IsEmpty())
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
|
2012-10-18 00:48:36 +04:00
|
|
|
char *asciiname = nullptr;
|
2006-02-03 17:18:39 +03:00
|
|
|
NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
|
2007-07-08 11:08:04 +04:00
|
|
|
asciiname = const_cast<char*>(aUtf8Nickname.get());
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
/* Find a good cert in the user's database */
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate cert(CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
|
|
|
|
asciiname,
|
|
|
|
certUsageEmailSigner,
|
|
|
|
true, ctx));
|
2012-11-12 21:42:28 +04:00
|
|
|
if (!cert) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2014-01-23 05:13:19 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
|
2012-10-18 00:48:36 +04:00
|
|
|
if (!nssCert) {
|
2012-11-12 21:42:28 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
2012-11-12 21:42:28 +04:00
|
|
|
nssCert.forget(_retval);
|
|
|
|
return NS_OK;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 11:20:58 +03:00
|
|
|
nsNSSCertificateDB::FindCertByEmailAddress(const char* aEmailAddress,
|
|
|
|
nsIX509Cert** _retval)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2003-01-18 17:03:00 +03:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
2013-08-30 03:15:35 +04:00
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2016-01-30 11:20:58 +03:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
2012-10-27 11:11:35 +04:00
|
|
|
NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
|
|
|
|
|
2012-11-12 21:42:28 +04:00
|
|
|
ScopedCERTCertList certlist(
|
|
|
|
PK11_FindCertsFromEmailAddress(aEmailAddress, nullptr));
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!certlist)
|
2016-01-30 11:20:58 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2011-06-28 16:26:41 +04:00
|
|
|
// certlist now contains certificates with the right email address,
|
|
|
|
// but they might not have the correct usage or might even be invalid
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
if (CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist))
|
2011-06-28 16:26:41 +04:00
|
|
|
return NS_ERROR_FAILURE; // no certs found
|
|
|
|
|
|
|
|
CERTCertListNode *node;
|
|
|
|
// search for a valid certificate
|
|
|
|
for (node = CERT_LIST_HEAD(certlist);
|
|
|
|
!CERT_LIST_END(node, certlist);
|
|
|
|
node = CERT_LIST_NEXT(node)) {
|
|
|
|
|
2016-01-13 23:50:42 +03:00
|
|
|
ScopedCERTCertList unusedCertChain;
|
2014-02-06 02:49:10 +04:00
|
|
|
SECStatus srv = certVerifier->VerifyCert(node->cert,
|
2012-10-27 11:11:35 +04:00
|
|
|
certificateUsageEmailRecipient,
|
2014-08-02 19:49:12 +04:00
|
|
|
mozilla::pkix::Now(),
|
|
|
|
nullptr /*XXX pinarg*/,
|
2016-01-13 23:50:42 +03:00
|
|
|
nullptr /*hostname*/,
|
|
|
|
unusedCertChain);
|
2012-10-27 11:11:35 +04:00
|
|
|
if (srv == SECSuccess) {
|
|
|
|
break;
|
2011-06-28 16:26:41 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CERT_LIST_END(node, certlist)) {
|
|
|
|
// no valid cert found
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
2011-06-28 16:26:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// node now contains the first valid certificate with correct usage
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsNSSCertificate> nssCert = nsNSSCertificate::Create(node->cert);
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!nssCert)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2015-07-01 20:10:53 +03:00
|
|
|
nssCert.forget(_retval);
|
2002-09-17 22:51:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-03-27 22:21:08 +04:00
|
|
|
nsNSSCertificateDB::ConstructX509FromBase64(const char *base64,
|
|
|
|
nsIX509Cert **_retval)
|
2002-09-17 22:51:22 +04:00
|
|
|
{
|
2013-11-04 23:22:37 +04:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2014-02-01 05:33:28 +04:00
|
|
|
if (NS_WARN_IF(!_retval)) {
|
|
|
|
return NS_ERROR_INVALID_POINTER;
|
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2011-03-27 22:21:08 +04:00
|
|
|
// sure would be nice to have a smart pointer class for PL_ allocations
|
|
|
|
// unfortunately, we cannot distinguish out-of-memory from bad-input here
|
2013-05-08 07:47:33 +04:00
|
|
|
uint32_t len = base64 ? strlen(base64) : 0;
|
2012-10-18 00:48:36 +04:00
|
|
|
char *certDER = PL_Base64Decode(base64, len, nullptr);
|
2011-03-27 22:21:08 +04:00
|
|
|
if (!certDER)
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
if (!*certDER) {
|
|
|
|
PL_strfree(certDER);
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we get to this point, we know we had well-formed base64 input;
|
|
|
|
// therefore the input string cannot have been less than two
|
|
|
|
// characters long. Compute the unpadded length of the decoded data.
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t lengthDER = (len * 3) / 4;
|
2002-09-17 22:51:22 +04:00
|
|
|
if (base64[len-1] == '=') {
|
2011-03-27 22:21:08 +04:00
|
|
|
lengthDER--;
|
|
|
|
if (base64[len-2] == '=')
|
|
|
|
lengthDER--;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
2014-02-01 05:33:28 +04:00
|
|
|
nsresult rv = ConstructX509(certDER, lengthDER, _retval);
|
|
|
|
PL_strfree(certDER);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::ConstructX509(const char* certDER,
|
|
|
|
uint32_t lengthDER,
|
|
|
|
nsIX509Cert** _retval)
|
|
|
|
{
|
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
if (NS_WARN_IF(!_retval)) {
|
|
|
|
return NS_ERROR_INVALID_POINTER;
|
|
|
|
}
|
2013-08-30 03:15:35 +04:00
|
|
|
|
2011-03-27 22:21:08 +04:00
|
|
|
SECItem secitem_cert;
|
|
|
|
secitem_cert.type = siDERCertBuffer;
|
|
|
|
secitem_cert.data = (unsigned char*)certDER;
|
|
|
|
secitem_cert.len = lengthDER;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
|
|
|
|
&secitem_cert, nullptr,
|
|
|
|
false, true));
|
2011-03-27 22:21:08 +04:00
|
|
|
if (!cert)
|
|
|
|
return (PORT_GetError() == SEC_ERROR_NO_MEMORY)
|
|
|
|
? NS_ERROR_OUT_OF_MEMORY : NS_ERROR_FAILURE;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2014-01-23 05:13:19 +04:00
|
|
|
nsCOMPtr<nsIX509Cert> nssCert = nsNSSCertificate::Create(cert.get());
|
2012-11-12 21:42:28 +04:00
|
|
|
if (!nssCert) {
|
2011-03-27 22:21:08 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2012-11-12 21:42:28 +04:00
|
|
|
}
|
|
|
|
nssCert.forget(_retval);
|
|
|
|
return NS_OK;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
|
2008-06-11 22:20:24 +04:00
|
|
|
void
|
|
|
|
nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert,
|
|
|
|
nsIInterfaceRequestor* ctx,
|
2013-08-30 03:15:35 +04:00
|
|
|
nsCString &nickname,
|
|
|
|
const nsNSSShutDownPreventionLock &/*proofOfLock*/)
|
2008-06-11 22:20:24 +04:00
|
|
|
{
|
2013-11-26 22:18:21 +04:00
|
|
|
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
|
|
|
|
|
2008-06-11 22:20:24 +04:00
|
|
|
nickname.Truncate();
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
CK_OBJECT_HANDLE keyHandle;
|
|
|
|
|
|
|
|
CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
|
|
|
|
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
|
2008-06-11 22:20:24 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString username;
|
2008-06-11 22:20:24 +04:00
|
|
|
char *temp_un = CERT_GetCommonName(&cert->subject);
|
|
|
|
if (temp_un) {
|
|
|
|
username = temp_un;
|
|
|
|
PORT_Free(temp_un);
|
2012-07-30 18:20:58 +04:00
|
|
|
temp_un = nullptr;
|
2008-06-11 22:20:24 +04:00
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString caname;
|
2008-06-11 22:20:24 +04:00
|
|
|
char *temp_ca = CERT_GetOrgName(&cert->issuer);
|
|
|
|
if (temp_ca) {
|
|
|
|
caname = temp_ca;
|
|
|
|
PORT_Free(temp_ca);
|
2012-07-30 18:20:58 +04:00
|
|
|
temp_ca = nullptr;
|
2008-06-11 22:20:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString tmpNickFmt;
|
2004-02-26 07:07:23 +03:00
|
|
|
nssComponent->GetPIPNSSBundleString("nick_template", tmpNickFmt);
|
2008-06-11 22:20:24 +04:00
|
|
|
NS_ConvertUTF16toUTF8 nickFmt(tmpNickFmt);
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString baseName;
|
2008-06-11 22:20:24 +04:00
|
|
|
char *temp_nn = PR_smprintf(nickFmt.get(), username.get(), caname.get());
|
|
|
|
if (!temp_nn) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
baseName = temp_nn;
|
|
|
|
PR_smprintf_free(temp_nn);
|
2012-07-30 18:20:58 +04:00
|
|
|
temp_nn = nullptr;
|
2008-06-11 22:20:24 +04:00
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
|
2008-06-11 22:20:24 +04:00
|
|
|
nickname = baseName;
|
2002-09-17 22:51:22 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We need to see if the private key exists on a token, if it does
|
|
|
|
* then we need to check for nicknames that already exist on the smart
|
|
|
|
* card.
|
|
|
|
*/
|
2012-11-12 21:42:28 +04:00
|
|
|
ScopedPK11SlotInfo slot(PK11_KeyForCertExists(cert, &keyHandle, ctx));
|
2008-06-11 22:20:24 +04:00
|
|
|
if (!slot)
|
|
|
|
return;
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
if (!PK11_IsInternal(slot)) {
|
2008-06-11 22:20:24 +04:00
|
|
|
char *tmp = PR_smprintf("%s:%s", PK11_GetTokenName(slot), baseName.get());
|
|
|
|
if (!tmp) {
|
|
|
|
nickname.Truncate();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
baseName = tmp;
|
|
|
|
PR_smprintf_free(tmp);
|
|
|
|
|
|
|
|
nickname = baseName;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
2008-06-11 22:20:24 +04:00
|
|
|
|
|
|
|
int count = 1;
|
|
|
|
while (true) {
|
2002-09-17 22:51:22 +04:00
|
|
|
if ( count > 1 ) {
|
2008-06-11 22:20:24 +04:00
|
|
|
char *tmp = PR_smprintf("%s #%d", baseName.get(), count);
|
|
|
|
if (!tmp) {
|
|
|
|
nickname.Truncate();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nickname = tmp;
|
|
|
|
PR_smprintf_free(tmp);
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
2008-06-11 22:20:24 +04:00
|
|
|
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate dummycert;
|
2008-06-11 22:20:24 +04:00
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
if (PK11_IsInternal(slot)) {
|
|
|
|
/* look up the nickname to make sure it isn't in use already */
|
2008-06-11 22:20:24 +04:00
|
|
|
dummycert = CERT_FindCertByNickname(defaultcertdb, nickname.get());
|
|
|
|
|
2002-09-17 22:51:22 +04:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Check the cert against others that already live on the smart
|
|
|
|
* card.
|
|
|
|
*/
|
2008-06-11 22:20:24 +04:00
|
|
|
dummycert = PK11_FindCertFromNickname(nickname.get(), ctx);
|
2012-10-18 00:48:36 +04:00
|
|
|
if (dummycert) {
|
2002-09-17 22:51:22 +04:00
|
|
|
/*
|
|
|
|
* Make sure the subject names are different.
|
|
|
|
*/
|
|
|
|
if (CERT_CompareName(&cert->subject, &dummycert->subject) == SECEqual)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* There is another certificate with the same nickname and
|
|
|
|
* the same subject name on the smart card, so let's use this
|
|
|
|
* nickname.
|
|
|
|
*/
|
2012-10-18 00:48:36 +04:00
|
|
|
dummycert = nullptr;
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-07-04 09:09:24 +04:00
|
|
|
if (!dummycert) {
|
2008-06-11 22:20:24 +04:00
|
|
|
break;
|
2014-07-04 09:09:24 +04:00
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
count++;
|
2008-06-11 22:20:24 +04:00
|
|
|
}
|
2002-09-17 22:51:22 +04:00
|
|
|
}
|
2003-10-20 19:00:17 +04:00
|
|
|
|
2014-07-04 09:09:24 +04:00
|
|
|
NS_IMETHODIMP nsNSSCertificateDB::AddCertFromBase64(const char* aBase64,
|
|
|
|
const char* aTrust,
|
|
|
|
const char* aName)
|
2003-10-20 19:00:17 +04:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aBase64);
|
|
|
|
nsCOMPtr <nsIX509Cert> newCert;
|
|
|
|
|
2013-08-30 03:15:35 +04:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2003-10-20 19:00:17 +04:00
|
|
|
nsNSSCertTrust trust;
|
|
|
|
|
|
|
|
// need to calculate the trust bits from the aTrust string.
|
2012-07-27 18:03:25 +04:00
|
|
|
SECStatus stat = CERT_DecodeTrustString(trust.GetTrust(),
|
|
|
|
/* this is const, but not declared that way */(char *) aTrust);
|
|
|
|
NS_ENSURE_STATE(stat == SECSuccess); // if bad trust passed in, return error.
|
2003-10-20 19:00:17 +04:00
|
|
|
|
|
|
|
|
2012-07-27 18:03:25 +04:00
|
|
|
nsresult rv = ConstructX509FromBase64(aBase64, getter_AddRefs(newCert));
|
2003-10-20 19:00:17 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
SECItem der;
|
2012-08-22 19:56:38 +04:00
|
|
|
rv = newCert->GetRawDER(&der.len, (uint8_t **)&der.data);
|
2003-10-20 19:00:17 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Creating temp cert\n"));
|
2003-10-20 19:00:17 +04:00
|
|
|
CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate tmpCert(CERT_FindCertByDERCert(certdb, &der));
|
2014-02-28 23:19:38 +04:00
|
|
|
if (!tmpCert)
|
2003-10-20 19:00:17 +04:00
|
|
|
tmpCert = CERT_NewTempCertificate(certdb, &der,
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, false, true);
|
2015-03-27 03:01:12 +03:00
|
|
|
free(der.data);
|
2012-07-30 18:20:58 +04:00
|
|
|
der.data = nullptr;
|
2006-02-22 23:36:53 +03:00
|
|
|
der.len = 0;
|
2003-10-20 19:00:17 +04:00
|
|
|
|
|
|
|
if (!tmpCert) {
|
2010-06-18 00:28:38 +04:00
|
|
|
NS_ERROR("Couldn't create cert from DER blob");
|
2014-02-28 23:19:38 +04:00
|
|
|
return MapSECStatus(SECFailure);
|
2003-10-20 19:00:17 +04:00
|
|
|
}
|
|
|
|
|
2014-07-10 13:38:00 +04:00
|
|
|
// If there's already a certificate that matches this one in the database,
|
|
|
|
// we still want to set its trust to the given value.
|
2003-10-20 19:00:17 +04:00
|
|
|
if (tmpCert->isperm) {
|
2014-07-10 13:38:00 +04:00
|
|
|
return SetCertTrustFromString(newCert, aTrust);
|
2003-10-20 19:00:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsXPIDLCString nickname;
|
2014-01-23 05:13:19 +04:00
|
|
|
nickname.Adopt(CERT_MakeCANickname(tmpCert.get()));
|
2003-10-20 19:00:17 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Created nick \"%s\"\n", nickname.get()));
|
2003-10-20 19:00:17 +04:00
|
|
|
|
2014-03-02 07:01:23 +04:00
|
|
|
rv = attemptToLogInWithDefaultPassword();
|
|
|
|
if (NS_WARN_IF(rv != NS_OK)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2014-01-23 05:13:19 +04:00
|
|
|
SECStatus srv = __CERT_AddTempCertToPerm(tmpCert.get(),
|
2012-11-02 23:34:46 +04:00
|
|
|
const_cast<char*>(nickname.get()),
|
|
|
|
trust.GetTrust());
|
2014-02-28 23:19:38 +04:00
|
|
|
return MapSECStatus(srv);
|
2003-10-20 19:00:17 +04:00
|
|
|
}
|
2006-01-10 05:07:47 +03:00
|
|
|
|
2012-11-15 03:31:39 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::AddCert(const nsACString & aCertDER, const char *aTrust,
|
|
|
|
const char *aName)
|
|
|
|
{
|
|
|
|
nsCString base64;
|
|
|
|
nsresult rv = Base64Encode(aCertDER, base64);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return AddCertFromBase64(base64.get(), aTrust, aName);
|
|
|
|
}
|
|
|
|
|
2014-02-23 07:08:06 +04:00
|
|
|
NS_IMETHODIMP
|
2014-07-04 09:09:24 +04:00
|
|
|
nsNSSCertificateDB::SetCertTrustFromString(nsIX509Cert* cert,
|
2014-02-23 07:08:06 +04:00
|
|
|
const char* trustString)
|
|
|
|
{
|
|
|
|
CERTCertTrust trust;
|
|
|
|
|
|
|
|
// need to calculate the trust bits from the aTrust string.
|
|
|
|
SECStatus srv = CERT_DecodeTrustString(&trust,
|
|
|
|
const_cast<char *>(trustString));
|
|
|
|
if (srv != SECSuccess) {
|
|
|
|
return MapSECStatus(SECFailure);
|
|
|
|
}
|
2014-07-04 08:49:56 +04:00
|
|
|
ScopedCERTCertificate nssCert(cert->GetCert());
|
2014-03-02 07:01:23 +04:00
|
|
|
|
|
|
|
nsresult rv = attemptToLogInWithDefaultPassword();
|
|
|
|
if (NS_WARN_IF(rv != NS_OK)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2014-02-23 07:08:06 +04:00
|
|
|
srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nssCert.get(), &trust);
|
|
|
|
return MapSECStatus(srv);
|
|
|
|
}
|
|
|
|
|
2006-01-10 05:07:47 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::GetCerts(nsIX509CertList **_retval)
|
|
|
|
{
|
2013-08-30 03:15:35 +04:00
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2014-02-23 07:08:06 +04:00
|
|
|
}
|
2006-01-10 05:07:47 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
|
|
|
|
nsCOMPtr<nsIX509CertList> nssCertList;
|
2014-07-07 02:55:38 +04:00
|
|
|
ScopedCERTCertList certList(PK11_ListCerts(PK11CertListUnique, ctx));
|
2006-01-10 05:07:47 +03:00
|
|
|
|
2012-10-18 00:48:36 +04:00
|
|
|
// nsNSSCertList 1) adopts certList, and 2) handles the nullptr case fine.
|
2006-01-10 05:07:47 +03:00
|
|
|
// (returns an empty list)
|
2013-11-12 03:16:45 +04:00
|
|
|
nssCertList = new nsNSSCertList(certList, locker);
|
2006-01-10 05:07:47 +03:00
|
|
|
|
2015-07-01 20:10:53 +03:00
|
|
|
nssCertList.forget(_retval);
|
2006-01-10 05:07:47 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-12-07 07:05:27 +04:00
|
|
|
|
2015-09-11 21:52:30 +03:00
|
|
|
nsresult
|
|
|
|
VerifyCertAtTime(nsIX509Cert* aCert,
|
|
|
|
int64_t /*SECCertificateUsage*/ aUsage,
|
|
|
|
uint32_t aFlags,
|
|
|
|
const char* aHostname,
|
|
|
|
mozilla::pkix::Time aTime,
|
|
|
|
nsIX509CertList** aVerifiedChain,
|
|
|
|
bool* aHasEVPolicy,
|
|
|
|
int32_t* /*PRErrorCode*/ _retval,
|
|
|
|
const nsNSSShutDownPreventionLock& locker)
|
2013-11-12 04:37:06 +04:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aCert);
|
|
|
|
NS_ENSURE_ARG_POINTER(aHasEVPolicy);
|
2015-05-07 21:06:07 +03:00
|
|
|
NS_ENSURE_ARG_POINTER(aVerifiedChain);
|
2013-11-12 04:37:06 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
|
2015-05-07 21:06:07 +03:00
|
|
|
*aVerifiedChain = nullptr;
|
2013-11-12 04:37:06 +04:00
|
|
|
*aHasEVPolicy = false;
|
|
|
|
*_retval = PR_UNKNOWN_ERROR;
|
|
|
|
|
2014-02-24 10:15:53 +04:00
|
|
|
#ifndef MOZ_NO_EV_CERTS
|
2014-01-27 07:36:28 +04:00
|
|
|
EnsureIdentityInfoLoaded();
|
2013-11-12 04:37:06 +04:00
|
|
|
#endif
|
|
|
|
|
2014-07-04 09:09:24 +04:00
|
|
|
ScopedCERTCertificate nssCert(aCert->GetCert());
|
|
|
|
if (!nssCert) {
|
2013-11-12 04:37:06 +04:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
2013-11-12 04:37:06 +04:00
|
|
|
NS_ENSURE_TRUE(certVerifier, NS_ERROR_FAILURE);
|
|
|
|
|
2014-07-07 02:55:38 +04:00
|
|
|
ScopedCERTCertList resultChain;
|
2013-11-12 04:37:06 +04:00
|
|
|
SECOidTag evOidPolicy;
|
|
|
|
SECStatus srv;
|
|
|
|
|
2015-05-07 21:06:07 +03:00
|
|
|
if (aHostname && aUsage == certificateUsageSSLServer) {
|
|
|
|
srv = certVerifier->VerifySSLServerCert(nssCert,
|
|
|
|
nullptr, // stapledOCSPResponse
|
2015-09-11 21:52:30 +03:00
|
|
|
aTime,
|
2015-05-07 21:06:07 +03:00
|
|
|
nullptr, // Assume no context
|
|
|
|
aHostname,
|
2016-01-13 23:50:42 +03:00
|
|
|
resultChain,
|
2015-05-07 21:06:07 +03:00
|
|
|
false, // don't save intermediates
|
|
|
|
aFlags,
|
|
|
|
&evOidPolicy);
|
|
|
|
} else {
|
2015-09-11 21:52:30 +03:00
|
|
|
srv = certVerifier->VerifyCert(nssCert, aUsage, aTime,
|
2015-05-07 21:06:07 +03:00
|
|
|
nullptr, // Assume no context
|
|
|
|
aHostname,
|
2016-01-13 23:50:42 +03:00
|
|
|
resultChain,
|
2015-05-07 21:06:07 +03:00
|
|
|
aFlags,
|
|
|
|
nullptr, // stapledOCSPResponse
|
|
|
|
&evOidPolicy);
|
|
|
|
}
|
2013-11-12 04:37:06 +04:00
|
|
|
|
|
|
|
PRErrorCode error = PR_GetError();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIX509CertList> nssCertList;
|
|
|
|
// This adopts the list
|
|
|
|
nssCertList = new nsNSSCertList(resultChain, locker);
|
|
|
|
NS_ENSURE_TRUE(nssCertList, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
if (srv == SECSuccess) {
|
|
|
|
if (evOidPolicy != SEC_OID_UNKNOWN) {
|
|
|
|
*aHasEVPolicy = true;
|
|
|
|
}
|
|
|
|
*_retval = 0;
|
|
|
|
} else {
|
|
|
|
NS_ENSURE_TRUE(evOidPolicy == SEC_OID_UNKNOWN, NS_ERROR_FAILURE);
|
|
|
|
NS_ENSURE_TRUE(error != 0, NS_ERROR_FAILURE);
|
|
|
|
*_retval = error;
|
|
|
|
}
|
2015-05-07 21:06:07 +03:00
|
|
|
nssCertList.forget(aVerifiedChain);
|
2013-11-12 04:37:06 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-03-13 00:08:48 +04:00
|
|
|
|
2015-09-11 21:52:30 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::VerifyCertNow(nsIX509Cert* aCert,
|
|
|
|
int64_t /*SECCertificateUsage*/ aUsage,
|
|
|
|
uint32_t aFlags,
|
|
|
|
const char* aHostname,
|
|
|
|
nsIX509CertList** aVerifiedChain,
|
|
|
|
bool* aHasEVPolicy,
|
|
|
|
int32_t* /*PRErrorCode*/ _retval)
|
|
|
|
{
|
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ::VerifyCertAtTime(aCert, aUsage, aFlags, aHostname,
|
|
|
|
mozilla::pkix::Now(),
|
|
|
|
aVerifiedChain, aHasEVPolicy, _retval, locker);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::VerifyCertAtTime(nsIX509Cert* aCert,
|
|
|
|
int64_t /*SECCertificateUsage*/ aUsage,
|
|
|
|
uint32_t aFlags,
|
|
|
|
const char* aHostname,
|
|
|
|
uint64_t aTime,
|
|
|
|
nsIX509CertList** aVerifiedChain,
|
|
|
|
bool* aHasEVPolicy,
|
|
|
|
int32_t* /*PRErrorCode*/ _retval)
|
|
|
|
{
|
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ::VerifyCertAtTime(aCert, aUsage, aFlags, aHostname,
|
|
|
|
mozilla::pkix::TimeFromEpochInSeconds(aTime),
|
|
|
|
aVerifiedChain, aHasEVPolicy, _retval, locker);
|
|
|
|
}
|
|
|
|
|
2014-03-13 00:08:48 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsNSSCertificateDB::ClearOCSPCache()
|
|
|
|
{
|
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
2014-03-13 00:08:48 +04:00
|
|
|
NS_ENSURE_TRUE(certVerifier, NS_ERROR_FAILURE);
|
2014-06-17 10:13:29 +04:00
|
|
|
certVerifier->ClearOCSPCache();
|
2014-03-13 00:08:48 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|