Bug 1050518 - Remove nsICertificatePrincipal. r=keeler

This commit is contained in:
Giovanni Sferro 2014-09-10 20:31:00 -04:00
parent 39722a9a25
commit 0decd968e4
12 changed files with 56 additions and 217 deletions

View File

@ -15,7 +15,7 @@ struct PRFileDesc;
interface nsIUTF8StringEnumerator;
interface nsIInputStream;
interface nsIFile;
interface nsICertificatePrincipal;
interface nsIX509Cert;
[scriptable, uuid(fad6f72f-13d8-4e26-9173-53007a4afe71)]
interface nsIZipEntry : nsISupports
@ -63,7 +63,7 @@ interface nsIZipEntry : nsISupports
readonly attribute unsigned long permissions;
};
[scriptable, uuid(38d6d07a-8a58-4fe7-be8b-ef6472fa83ff)]
[scriptable, uuid(894c8dc0-37c8-11e4-916c-0800200c9a66)]
interface nsIZipReader : nsISupports
{
/**
@ -190,8 +190,8 @@ interface nsIZipReader : nsISupports
* stored in the jar, verifyExternalFile (not yet implemented) must
* be called before getPrincipal.
*/
nsICertificatePrincipal getCertificatePrincipal(in AUTF8String aEntryName);
nsIX509Cert getSigningCert(in AUTF8String aEntryName);
readonly attribute uint32_t manifestEntriesCount;
};

View File

@ -6,7 +6,7 @@
#include "nsJARInputStream.h"
#include "nsJAR.h"
#include "nsIFile.h"
#include "nsICertificatePrincipal.h"
#include "nsIX509Cert.h"
#include "nsIConsoleService.h"
#include "nsICryptoHash.h"
#include "nsIDataSignatureVerifier.h"
@ -323,12 +323,13 @@ nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec,
}
NS_IMETHODIMP
nsJAR::GetCertificatePrincipal(const nsACString &aFilename, nsICertificatePrincipal** aPrincipal)
nsJAR::GetSigningCert(const nsACString& aFilename, nsIX509Cert** aSigningCert)
{
//-- Parameter check
if (!aPrincipal)
if (!aSigningCert) {
return NS_ERROR_NULL_POINTER;
*aPrincipal = nullptr;
}
*aSigningCert = nullptr;
// Don't check signatures in the omnijar - this is only
// interesting for extensions/XPIs.
@ -366,12 +367,11 @@ nsJAR::GetCertificatePrincipal(const nsACString &aFilename, nsICertificatePrinci
else // User wants identity of signer w/o verifying any entries
requestedStatus = mGlobalStatus;
if (requestedStatus != JAR_VALID_MANIFEST)
if (requestedStatus != JAR_VALID_MANIFEST) {
ReportError(aFilename, requestedStatus);
else // Valid signature
{
*aPrincipal = mPrincipal;
NS_IF_ADDREF(*aPrincipal);
} else { // Valid signature
*aSigningCert = mSigningCert;
NS_IF_ADDREF(*aSigningCert);
}
return NS_OK;
}
@ -589,14 +589,15 @@ nsJAR::ParseManifest()
//-- Verify that the signature file is a valid signature of the SF file
int32_t verifyError;
rv = verifier->VerifySignature(sigBuffer, sigLen, manifestBuffer, manifestLen,
&verifyError, getter_AddRefs(mPrincipal));
&verifyError, getter_AddRefs(mSigningCert));
if (NS_FAILED(rv)) return rv;
if (mPrincipal && verifyError == nsIDataSignatureVerifier::VERIFY_OK)
if (mSigningCert && verifyError == nsIDataSignatureVerifier::VERIFY_OK) {
mGlobalStatus = JAR_VALID_MANIFEST;
else if (verifyError == nsIDataSignatureVerifier::VERIFY_ERROR_UNKNOWN_ISSUER)
} else if (verifyError == nsIDataSignatureVerifier::VERIFY_ERROR_UNKNOWN_ISSUER) {
mGlobalStatus = JAR_INVALID_UNKNOWN_CA;
else
} else {
mGlobalStatus = JAR_INVALID_SIG;
}
//-- Parse the SF file. If the verification above failed, principal
// is null, and ParseOneFile will mark the relevant entries as invalid.

View File

@ -29,7 +29,7 @@
#include "nsIObserver.h"
#include "mozilla/Attributes.h"
class nsICertificatePrincipal;
class nsIX509Cert;
class nsIInputStream;
class nsJARManifestItem;
class nsZipReaderCache;
@ -106,7 +106,7 @@ class nsJAR MOZ_FINAL : public nsIZipReader
nsRefPtr<nsZipArchive> mZip; // The underlying zip archive
ManifestDataHashtable mManifestData; // Stores metadata for each entry
bool mParsedManifest; // True if manifest has been parsed
nsCOMPtr<nsICertificatePrincipal> mPrincipal; // The entity which signed this file
nsCOMPtr<nsIX509Cert> mSigningCert; // The entity which signed this file
int16_t mGlobalStatus; // Global signature verification status
PRIntervalTime mReleaseTime; // used by nsZipReaderCache for flushing entries
nsZipReaderCache* mCache; // if cached, this points to the cache it's contained in

View File

@ -45,14 +45,15 @@ function openZip(path) {
// Gets the pretty name from the signing cert or null if the zip is unsigned.
function getSigner(zip) {
var principal = zip.getCertificatePrincipal(null);
if (principal && principal.hasCertificate)
return principal.prettyName;
var signingCert = zip.getSigningCert(null);
if (signingCert) {
return signingCert.organization;
}
return null;
}
function verifySigning(zip) {
var principal = zip.getCertificatePrincipal(null);
var signingCert = zip.getSigningCert(null);
var count = 0;
var entries = zip.findEntries(null);
while (entries.hasMore()) {
@ -64,9 +65,10 @@ function verifySigning(zip) {
if (entry.substr(-1) == "/")
continue;
count++;
var entryPrincipal = zip.getCertificatePrincipal(entry);
if (!entryPrincipal || !principal.equals(entryPrincipal))
var entryCert = zip.getSigningCert(entry);
if (!entryCert || !signingCert.equals(entryCert)) {
return false;
}
}
return zip.manifestEntriesCount == count;
}

View File

@ -11,7 +11,6 @@ XPIDL_SOURCES += [
'nsIAssociatedContentSecurity.idl',
'nsIBadCertListener2.idl',
'nsICertificateDialogs.idl',
'nsICertificatePrincipal.idl',
'nsICertOverrideService.idl',
'nsICertPickDialogs.idl',
'nsIClientAuthDialogs.idl',

View File

@ -1,33 +0,0 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 "nsISupports.idl"
/*
* Historically, principals, certificates, and signed JARs were all linked
* together in one big mess. When that mess was cleaned up, it turned out that
* the principals used to store certificate information didn't overlap at all
* with the principals used for security policy. So this interface was created
* so that real principals wouldn't have to carry around all that baggage.
*
* The name here is totally a misnomer. This isn't a principal at all, and would
* better be called nsICertificateHolder or something. But that would require
* renaming some APIs, so let's just let this be for now.
*/
[scriptable, uuid(7cd4af5a-64d3-44a8-9700-804a42a6109a)]
interface nsICertificatePrincipal : nsISupports
{
readonly attribute AUTF8String fingerprint;
readonly attribute AUTF8String prettyName;
readonly attribute AUTF8String subjectName;
readonly attribute nsISupports certificate;
readonly attribute boolean hasCertificate; // For compat; always true.
bool equals(in nsICertificatePrincipal aOther);
};
////////////////////////////////////////////////////////////////////////////////

View File

@ -5,14 +5,13 @@
#include "nsISupports.idl"
// NB: This isn't actually a principal at all. The naming is just historical.
interface nsICertificatePrincipal;
interface nsIX509Cert;
/**
* An interface for verifying that a given string of data was signed by the
* private key matching the given public key.
*/
[scriptable, uuid(577f097f-15e4-4043-bc0e-6d2fadcacae2)]
[scriptable, uuid(94066a00-37c9-11e4-916c-0800200c9a66)]
interface nsIDataSignatureVerifier : nsISupports
{
/**
@ -32,10 +31,10 @@ interface nsIDataSignatureVerifier : nsISupports
const long VERIFY_ERROR_UNKNOWN_ISSUER = 1;
const long VERIFY_ERROR_OTHER = 2;
nsICertificatePrincipal verifySignature(in string aSignature,
in unsigned long aSignatureLen,
in string plaintext,
in unsigned long plaintextLen,
out long errorCode);
nsIX509Cert verifySignature(in string aSignature,
in unsigned long aSignatureLen,
in string plaintext,
in unsigned long plaintextLen,
out long errorCode);
};

View File

@ -19,7 +19,6 @@ EXPORTS.mozilla += [
UNIFIED_SOURCES += [
'CryptoTask.cpp',
'nsCertificatePrincipal.cpp',
'nsCertOverrideService.cpp',
'nsCertPicker.cpp',
'nsCertVerificationThread.cpp',

View File

@ -1,67 +0,0 @@
/* -*- 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 "nsCertificatePrincipal.h"
NS_IMPL_ISUPPORTS(nsCertificatePrincipal, nsICertificatePrincipal)
NS_IMETHODIMP
nsCertificatePrincipal::GetFingerprint(nsACString& aFingerprint)
{
aFingerprint = mFingerprint;
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::GetSubjectName(nsACString& aSubjectName)
{
aSubjectName = mSubjectName;
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::GetPrettyName(nsACString& aPrettyName)
{
aPrettyName = mPrettyName;
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::GetCertificate(nsISupports** aCert)
{
nsCOMPtr<nsISupports> cert = mCert;
cert.forget(aCert);
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::GetHasCertificate(bool* rv)
{
*rv = true;
return NS_OK;
}
NS_IMETHODIMP
nsCertificatePrincipal::Equals(nsICertificatePrincipal* aOther, bool* rv)
{
nsAutoCString str;
aOther->GetFingerprint(str);
if (!str.Equals(mFingerprint)) {
*rv = false;
return NS_OK;
}
// If either subject name is empty, just let the result stand, but if they're
// both non-empty, only claim equality if they're equal.
if (!mSubjectName.IsEmpty()) {
// Check the other principal's subject name
aOther->GetSubjectName(str);
*rv = str.Equals(mSubjectName) || str.IsEmpty();
return NS_OK;
}
*rv = true;
return NS_OK;
}

View File

@ -1,39 +0,0 @@
/* -*- 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/. */
#ifndef __NS_CERTIFICATEPRINCIPAL_H
#define __NS_CERTIFICATEPRINCIPAL_H
#include "nsICertificatePrincipal.h"
#include "nsString.h"
#include "nsCOMPtr.h"
class nsCertificatePrincipal : public nsICertificatePrincipal
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICERTIFICATEPRINCIPAL
nsCertificatePrincipal(const nsACString& aFingerprint,
const nsACString& aSubjectName,
const nsACString& aPrettyName,
nsISupports* aCert)
: mFingerprint(aFingerprint)
, mSubjectName(aSubjectName)
, mPrettyName(aPrettyName)
, mCert(aCert)
{}
protected:
virtual ~nsCertificatePrincipal() {}
private:
nsCString mFingerprint;
nsCString mSubjectName;
nsCString mPrettyName;
nsCOMPtr<nsISupports> mCert;
};
#endif /* __NS_CERTIFICATEPRINCIPAL_H */

View File

@ -7,7 +7,6 @@
#include "cms.h"
#include "cryptohi.h"
#include "keyhi.h"
#include "nsCertificatePrincipal.h"
#include "nsCOMPtr.h"
#include "nsNSSComponent.h"
#include "nssb64.h"
@ -222,7 +221,7 @@ namespace {
struct VerifyCertificateContext
{
nsCOMPtr<nsICertificatePrincipal> principal;
nsCOMPtr<nsIX509Cert> signingCert;
ScopedCERTCertList builtChain;
};
@ -242,27 +241,7 @@ VerifyCertificate(CERTCertificate* cert, void* voidContext, void* pinArg)
return NS_ERROR_OUT_OF_MEMORY;
}
nsAutoString fingerprint;
nsresult rv = xpcomCert->GetSha1Fingerprint(fingerprint);
if (NS_FAILED(rv)) {
return rv;
}
nsAutoString orgName;
rv = xpcomCert->GetOrganization(orgName);
if (NS_FAILED(rv)) {
return rv;
}
nsAutoString subjectName;
rv = xpcomCert->GetSubjectName(subjectName);
if (NS_FAILED(rv)) {
return rv;
}
context->principal =
new nsCertificatePrincipal(NS_ConvertUTF16toUTF8(fingerprint),
NS_ConvertUTF16toUTF8(subjectName),
NS_ConvertUTF16toUTF8(orgName),
xpcomCert);
context->signingCert = xpcomCert;
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
@ -284,14 +263,14 @@ nsDataSignatureVerifier::VerifySignature(const char* aRSABuf,
const char* aPlaintext,
uint32_t aPlaintextLen,
int32_t* aErrorCode,
nsICertificatePrincipal** aPrincipal)
nsIX509Cert** aSigningCert)
{
if (!aPlaintext || !aPrincipal || !aErrorCode) {
if (!aPlaintext || !aSigningCert || !aErrorCode) {
return NS_ERROR_INVALID_ARG;
}
*aErrorCode = VERIFY_ERROR_OTHER;
*aPrincipal = nullptr;
*aSigningCert = nullptr;
nsNSSShutDownPreventionLock locker;
@ -325,7 +304,7 @@ nsDataSignatureVerifier::VerifySignature(const char* aRSABuf,
rv = NS_OK;
}
if (rv == NS_OK) {
context.principal.forget(aPrincipal);
context.signingCert.forget(aSigningCert);
}
return rv;

View File

@ -1197,12 +1197,12 @@ function getTemporaryFile() {
*
* @param aZip
* A nsIZipReader to check
* @param aPrincipal
* The nsIPrincipal to compare against
* @param aCertificate
* The nsIX509Cert to compare against
* @return true if all the contents that should be signed were signed by the
* principal
*/
function verifyZipSigning(aZip, aPrincipal) {
function verifyZipSigning(aZip, aCertificate) {
var count = 0;
var entries = aZip.findEntries(null);
while (entries.hasMore()) {
@ -1214,9 +1214,10 @@ function verifyZipSigning(aZip, aPrincipal) {
if (entry.substr(-1) == "/")
continue;
count++;
var entryPrincipal = aZip.getCertificatePrincipal(entry);
if (!entryPrincipal || !aPrincipal.equals(entryPrincipal))
var entryCertificate = aZip.getSigningCert(entry);
if (!entryCertificate || !aCertificate.equals(entryCertificate)) {
return false;
}
}
return aZip.manifestEntriesCount == count;
}
@ -5127,19 +5128,17 @@ AddonInstall.prototype = {
throw e;
}
let principal = zipreader.getCertificatePrincipal(null);
if (principal && principal.hasCertificate) {
let x509 = zipreader.getSigningCert(null);
if (x509) {
logger.debug("Verifying XPI signature");
if (verifyZipSigning(zipreader, principal)) {
let x509 = principal.certificate;
if (x509 instanceof Ci.nsIX509Cert)
this.certificate = x509;
if (this.certificate && this.certificate.commonName.length > 0)
if (verifyZipSigning(zipreader, x509)) {
this.certificate = x509;
if (this.certificate.commonName.length > 0) {
this.certName = this.certificate.commonName;
else
this.certName = principal.prettyName;
}
else {
} else {
this.certName = this.certificate.organization;
}
} else {
zipreader.close();
throw new Error("XPI is incorrectly signed");
}