Bug 307081 - Expose nsNSSCertificate.cpp GetKeyUsagesString() as the keyUsages attribute on nsIX509Cert. r=keeler
This allows nsNSSCertificate::FormatUIStrings() to be reimplemented in JS, which
is a necessary step for making nsIClientAuthDialogs::ChooseCertificate() pass an
nsIArray of nsIX509Certs.
Also removes some deprecated and unused constants.
MozReview-Commit-ID: CJITKVlUEtP
--- a/security/manager/ssl/nsIX509Cert.idl
+++ b/security/manager/ssl/nsIX509Cert.idl
@@ -178,34 +178,16 @@ interface nsIX509Cert : nsISupports {
const unsigned long CERT_NOT_TRUSTED = 1 << 3;
const unsigned long ISSUER_NOT_TRUSTED = 1 << 4;
const unsigned long ISSUER_UNKNOWN = 1 << 5;
const unsigned long INVALID_CA = 1 << 6;
const unsigned long USAGE_NOT_ALLOWED = 1 << 7;
const unsigned long SIGNATURE_ALGORITHM_DISABLED = 1 << 8;
/**
- * Constants that describe the certified usages of a certificate.
- *
- * Deprecated and unused
- */
- const unsigned long CERT_USAGE_SSLClient = 0;
- const unsigned long CERT_USAGE_SSLServer = 1;
- const unsigned long CERT_USAGE_SSLServerWithStepUp = 2;
- const unsigned long CERT_USAGE_SSLCA = 3;
- const unsigned long CERT_USAGE_EmailSigner = 4;
- const unsigned long CERT_USAGE_EmailRecipient = 5;
- const unsigned long CERT_USAGE_ObjectSigner = 6;
- const unsigned long CERT_USAGE_UserCertImport = 7;
- const unsigned long CERT_USAGE_VerifyCA = 8;
- const unsigned long CERT_USAGE_ProtectedObjectSigner = 9;
- const unsigned long CERT_USAGE_StatusResponder = 10;
- const unsigned long CERT_USAGE_AnyCA = 11;
-
- /**
* Constants for specifying the chain mode when exporting a certificate
*/
const unsigned long CMS_CHAIN_MODE_CertOnly = 1;
const unsigned long CMS_CHAIN_MODE_CertChain = 2;
const unsigned long CMS_CHAIN_MODE_CertChainWithRoot = 3;
/**
* Obtain a list of certificates that contains this certificate
@@ -246,16 +228,23 @@ interface nsIX509Cert : nsISupports {
* @param localOnly Do not hit the network, even if revocation information
* downloading is currently activated.
* @param verified The certificate verification result, see constants.
* @param purposes The string listing the usages.
*/
void getUsagesString(in boolean localOnly, out uint32_t verified, out AString usages);
/**
+ * A comma separated list of localized strings representing the contents of
+ * the certificate's key usage extension, if present. The empty string if the
+ * certificate doesn't have the key usage extension, or has an empty extension.
+ */
+ readonly attribute AString keyUsages;
+
+ /**
* This is the attribute which describes the ASN1 layout
* of the certificate. This can be used when doing a
* "pretty print" of the certificate's ASN1 structure.
*/
readonly attribute nsIASN1Object ASN1Structure;
/**
* Obtain a raw binary encoding of this certificate
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -6,16 +6,17 @@
#include "nsNSSCertificate.h"
#include "CertVerifier.h"
#include "ExtendedValidation.h"
#include "NSSCertDBTrustDomain.h"
#include "certdb.h"
#include "mozilla/Base64.h"
#include "mozilla/Casting.h"
+#include "mozilla/NotNull.h"
#include "mozilla/unused.h"
#include "nsArray.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsCertVerificationThread.h"
#include "nsICertificateDialogs.h"
#include "nsIClassInfoImpl.h"
#include "nsIObjectInputStream.h"
@@ -65,16 +66,18 @@ extern LazyLogModule gPIPNSSLog;
// in the list to mean not yet initialized.
#define CERT_TYPE_NOT_YET_INITIALIZED (1 << 30)
NS_IMPL_ISUPPORTS(nsNSSCertificate,
nsIX509Cert,
nsISerializable,
nsIClassInfo)
+static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
+
/*static*/ nsNSSCertificate*
nsNSSCertificate::Create(CERTCertificate* cert, SECOidTag* evOidPolicy)
{
if (GeckoProcessType_Default != XRE_GetProcessType()) {
NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
return nullptr;
}
if (cert)
@@ -251,110 +254,102 @@ nsNSSCertificate::MarkForPermDeletion()
return NS_ERROR_FAILURE;
}
}
mPermDelete = true;
return NS_OK;
}
-nsresult
-GetKeyUsagesString(CERTCertificate* cert, nsINSSComponent* nssComponent,
- nsString& text)
+/**
+ * Appends a pipnss bundle string to the given string.
+ *
+ * @param nssComponent For accessing the string bundle.
+ * @param bundleKey Key for the string to append.
+ * @param currentText The text to append to, using commas as separators.
+ */
+template<size_t N>
+void
+AppendBundleString(const NotNull<nsCOMPtr<nsINSSComponent>>& nssComponent,
+ const char (&bundleKey)[N],
+ /*in/out*/ nsAString& currentText)
+{
+ nsAutoString bundleString;
+ nsresult rv = nssComponent->GetPIPNSSBundleString(bundleKey, bundleString);
+ if (NS_FAILED(rv)) {
+ return;
+ }
+
+ if (!currentText.IsEmpty()) {
+ currentText.Append(',');
+ }
+ currentText.Append(bundleString);
+}
+
+NS_IMETHODIMP
+nsNSSCertificate::GetKeyUsages(nsAString& text)
{
text.Truncate();
- SECItem keyUsageItem;
- keyUsageItem.data = nullptr;
- keyUsageItem.len = 0;
+ nsCOMPtr<nsINSSComponent> nssComponent = do_GetService(kNSSComponentCID);
+ if (!nssComponent) {
+ return NS_ERROR_FAILURE;
+ }
- SECStatus srv;
+ if (!mCert) {
+ return NS_ERROR_FAILURE;
+ }
- // There is no extension, v1 or v2 certificate
- if (!cert->extensions)
+ if (!mCert->extensions) {
return NS_OK;
-
+ }
- srv = CERT_FindKeyUsageExtension(cert, &keyUsageItem);
- if (srv == SECFailure) {
- if (PORT_GetError () == SEC_ERROR_EXTENSION_NOT_FOUND)
- return NS_OK;
- else
- return NS_ERROR_FAILURE;
+ ScopedAutoSECItem keyUsageItem;
+ if (CERT_FindKeyUsageExtension(mCert.get(), &keyUsageItem) != SECSuccess) {
+ return PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND ? NS_OK
+ : NS_ERROR_FAILURE;
}
+
unsigned char keyUsage = 0;
if (keyUsageItem.len) {
keyUsage = keyUsageItem.data[0];
}
- nsAutoString local;
- nsresult rv;
- const char16_t comma = ',';
-
+ NotNull<nsCOMPtr<nsINSSComponent>> wrappedNSSComponent =
+ WrapNotNull(nssComponent);
if (keyUsage & KU_DIGITAL_SIGNATURE) {
- rv = nssComponent->GetPIPNSSBundleString("CertDumpKUSign", local);
- if (NS_SUCCEEDED(rv)) {
- if (!text.IsEmpty()) text.Append(comma);
- text.Append(local.get());
- }
+ AppendBundleString(wrappedNSSComponent, "CertDumpKUSign", text);
}
if (keyUsage & KU_NON_REPUDIATION) {
- rv = nssComponent->GetPIPNSSBundleString("CertDumpKUNonRep", local);
- if (NS_SUCCEEDED(rv)) {
- if (!text.IsEmpty()) text.Append(comma);
- text.Append(local.get());
- }
+ AppendBundleString(wrappedNSSComponent, "CertDumpKUNonRep", text);
}
if (keyUsage & KU_KEY_ENCIPHERMENT) {
- rv = nssComponent->GetPIPNSSBundleString("CertDumpKUEnc", local);
- if (NS_SUCCEEDED(rv)) {
- if (!text.IsEmpty()) text.Append(comma);
- text.Append(local.get());
- }
+ AppendBundleString(wrappedNSSComponent, "CertDumpKUEnc", text);
}
if (keyUsage & KU_DATA_ENCIPHERMENT) {
- rv = nssComponent->GetPIPNSSBundleString("CertDumpKUDEnc", local);
- if (NS_SUCCEEDED(rv)) {
- if (!text.IsEmpty()) text.Append(comma);
- text.Append(local.get());
- }
+ AppendBundleString(wrappedNSSComponent, "CertDumpKUDEnc", text);
}
if (keyUsage & KU_KEY_AGREEMENT) {
- rv = nssComponent->GetPIPNSSBundleString("CertDumpKUKA", local);
- if (NS_SUCCEEDED(rv)) {
- if (!text.IsEmpty()) text.Append(comma);
- text.Append(local.get());
- }
+ AppendBundleString(wrappedNSSComponent, "CertDumpKUKA", text);
}
if (keyUsage & KU_KEY_CERT_SIGN) {
- rv = nssComponent->GetPIPNSSBundleString("CertDumpKUCertSign", local);
- if (NS_SUCCEEDED(rv)) {
- if (!text.IsEmpty()) text.Append(comma);
- text.Append(local.get());
- }
+ AppendBundleString(wrappedNSSComponent, "CertDumpKUCertSign", text);
}
if (keyUsage & KU_CRL_SIGN) {
- rv = nssComponent->GetPIPNSSBundleString("CertDumpKUCRLSign", local);
- if (NS_SUCCEEDED(rv)) {
- if (!text.IsEmpty()) text.Append(comma);
- text.Append(local.get());
- }
+ AppendBundleString(wrappedNSSComponent, "CertDumpKUCRLSign", text);
}
- PORT_Free (keyUsageItem.data);
return NS_OK;
}
nsresult
nsNSSCertificate::FormatUIStrings(const nsAutoString& nickname,
nsAutoString& nickWithSerial,
nsAutoString& details)
{
- static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
-
if (!NS_IsMainThread()) {
NS_ERROR("nsNSSCertificate::FormatUIStrings called off the main thread");
return NS_ERROR_NOT_SAME_THREAD;
}
nsresult rv = NS_OK;
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
@@ -416,18 +411,17 @@ nsNSSCertificate::FormatUIStrings(const
details.Append(char16_t(' '));
}
details.Append(temp1);
}
details.Append(char16_t('\n'));
}
- if (NS_SUCCEEDED(GetKeyUsagesString(mCert.get(), nssComponent, temp1)) &&
- !temp1.IsEmpty()) {
+ if (NS_SUCCEEDED(GetKeyUsages(temp1)) && !temp1.IsEmpty()) {
details.AppendLiteral(" ");
if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertDumpKeyUsage", info))) {
details.Append(info);
details.AppendLiteral(": ");
}
details.Append(temp1);
details.Append(char16_t('\n'));
}
@@ -580,18 +574,16 @@ nsNSSCertificate::GetWindowTitle(nsAStri
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetNickname(nsAString& aNickname)
{
- static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
-
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
if (mCert->nickname) {
CopyUTF8toUTF16(mCert->nickname, aNickname);
} else {
nsresult rv;
@@ -602,18 +594,16 @@ nsNSSCertificate::GetNickname(nsAString&
nssComponent->GetPIPNSSBundleString("CertNoNickname", aNickname);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificate::GetEmailAddress(nsAString& aEmailAddress)
{
- static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
-
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
if (mCert->emailAddr) {
CopyUTF8toUTF16(mCert->emailAddr, aEmailAddress);
} else {
nsresult rv;
@@ -1049,18 +1039,16 @@ NS_IMETHODIMP
nsNSSCertificate::GetSha1Fingerprint(nsAString& _sha1Fingerprint)
{
return GetCertificateHash(_sha1Fingerprint, SEC_OID_SHA1);
}
NS_IMETHODIMP
nsNSSCertificate::GetTokenName(nsAString& aTokenName)
{
- static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
-
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
aTokenName.Truncate();
if (mCert) {
// HACK alert
// When the trust of a builtin cert is modified, NSS copies it into the
--- a/security/manager/ssl/nsNSSCertificateFakeTransport.cpp
+++ b/security/manager/ssl/nsNSSCertificateFakeTransport.cpp
@@ -1,22 +1,22 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsNSSCertificateFakeTransport.h"
+#include "mozilla/Assertions.h"
#include "nsIClassInfoImpl.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsISupportsPrimitives.h"
#include "nsNSSCertificate.h"
#include "nsString.h"
-#include "nsXPIDLString.h"
NS_IMPL_ISUPPORTS(nsNSSCertificateFakeTransport,
nsIX509Cert,
nsISerializable,
nsIClassInfo)
nsNSSCertificateFakeTransport::nsNSSCertificateFakeTransport()
: mCertSerialization(nullptr)
@@ -195,16 +195,23 @@ nsNSSCertificateFakeTransport::GetUsages
NS_IMETHODIMP
nsNSSCertificateFakeTransport::GetUsagesString(bool, uint32_t*, nsAString&)
{
NS_NOTREACHED("Unimplemented on content process");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
+nsNSSCertificateFakeTransport::GetKeyUsages(nsAString&)
+{
+ MOZ_ASSERT_UNREACHABLE("Unimplemented on content process");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
nsNSSCertificateFakeTransport::GetASN1Structure(nsIASN1Object**)
{
NS_NOTREACHED("Unimplemented on content process");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsNSSCertificateFakeTransport::Equals(nsIX509Cert*, bool*)