зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1409259 - Add a console warning for soon-to-be-distrusted roots r=keeler,ttaubert
This patch adds a new diagnostic status flag to nsIWebProgressListener, STATE_CERT_DISTRUST_IMMINENT, which indicates that the certificate chain is going to change validity due to an upcoming distrust event. The first of these events is this bug, affecting various roots from Symantec. The STATE_CERT_DISTRUST_IMMINENT flag is set by nsNSSCallbacks and passed, via nsSecureBrowserUIImpl, to browser.js where it is used to alert the console. Adding this sort of diagnostic printing to be accessible to browser.js is a long-desired goal, as future functionality can start doing more decision-making there. We may, for example, also want to degrade the lock icon, which will be straightforward with this flag. This commit does not implement the IsCertificateDistrustImminent method. That is follow-on work. MozReview-Commit-ID: 75IOdc24XIV --HG-- extra : rebase_source : e6a95d0be65f667eff0b131274272f0df91f8732
This commit is contained in:
Родитель
ce24b2607a
Коммит
0e002bccbd
|
@ -7199,6 +7199,10 @@ var gIdentityHandler = {
|
|||
return this._state & Ci.nsIWebProgressListener.STATE_CERT_USER_OVERRIDDEN;
|
||||
},
|
||||
|
||||
get _isCertDistrustImminent() {
|
||||
return this._state & Ci.nsIWebProgressListener.STATE_CERT_DISTRUST_IMMINENT;
|
||||
},
|
||||
|
||||
get _hasInsecureLoginForms() {
|
||||
// checks if the page has been flagged for an insecure login. Also checks
|
||||
// if the pref to degrade the UI is set to true
|
||||
|
@ -7450,6 +7454,19 @@ var gIdentityHandler = {
|
|||
// we receive a new security state on the existing page (i.e. from a
|
||||
// subframe). If the user opened the popup and looks at the provided
|
||||
// information we don't want to suddenly change the panel contents.
|
||||
|
||||
// Finally, if there are warnings to issue, issue them
|
||||
if (this._isCertDistrustImminent) {
|
||||
let consoleMsg = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError);
|
||||
let windowId = gBrowser.selectedBrowser.innerWindowID;
|
||||
let message = gBrowserBundle.GetStringFromName("certImminentDistrust.message");
|
||||
// Use uri.prePath instead of initWithSourceURI() so that these can be
|
||||
// de-duplicated on the scheme+host+port combination.
|
||||
consoleMsg.initWithWindowID(message, uri.prePath, null, 0, 0,
|
||||
Ci.nsIScriptError.warningFlag, "SSL",
|
||||
windowId);
|
||||
Services.console.logMessage(consoleMsg);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -915,3 +915,8 @@ permissions.remove.tooltip = Clear this permission and ask again
|
|||
# e.g.: "48.0.2 (32-bit) <What's new>" or "51.0a1 (2016-09-05) (64-bit)".
|
||||
aboutDialog.architecture.sixtyFourBit = 64-bit
|
||||
aboutDialog.architecture.thirtyTwoBit = 32-bit
|
||||
|
||||
# LOCALIZATION NOTE (certImminentDistrust.message):
|
||||
# Shown in the browser console when visiting a website that is trusted today,
|
||||
# but won't be in the future unless the site operator makes a change.
|
||||
certImminentDistrust.message = The security certificate in use on this web site will no longer be trusted in a future release of Firefox. For more information, visit https://wiki.mozilla.org/CA/Upcoming_Distrust_Actions
|
|
@ -34,6 +34,11 @@
|
|||
#include "ssl.h"
|
||||
#include "sslproto.h"
|
||||
|
||||
#include "TrustOverrideUtils.h"
|
||||
#include "TrustOverride-SymantecData.inc"
|
||||
#include "TrustOverride-AppleGoogleData.inc"
|
||||
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::pkix;
|
||||
using namespace mozilla::psm;
|
||||
|
@ -1260,6 +1265,72 @@ DetermineEVAndCTStatusAndSetNewCert(RefPtr<nsSSLStatus> sslStatus,
|
|||
}
|
||||
}
|
||||
|
||||
static nsresult
|
||||
IsCertificateDistrustImminent(nsIX509CertList* aCertList,
|
||||
/* out */ bool& aResult) {
|
||||
if (!aCertList) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIX509Cert> rootCert;
|
||||
nsCOMPtr<nsIX509CertList> intCerts;
|
||||
nsCOMPtr<nsIX509Cert> eeCert;
|
||||
|
||||
RefPtr<nsNSSCertList> certList = aCertList->GetCertList();
|
||||
nsresult rv = certList->SegmentCertificateChain(rootCert, intCerts, eeCert);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// We need to verify the age of the end entity
|
||||
nsCOMPtr<nsIX509CertValidity> validity;
|
||||
rv = eeCert->GetValidity(getter_AddRefs(validity));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRTime notBefore;
|
||||
rv = validity->GetNotBefore(¬Before);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// PRTime is microseconds since the epoch, whereas JS time is milliseconds.
|
||||
// (new Date("2016-06-01T00:00:00Z")).getTime() * 1000
|
||||
static const PRTime JUNE_1_2016 = 1464739200000000;
|
||||
|
||||
// If the end entity's notBefore date is after 2016-06-01, this algorithm
|
||||
// doesn't apply, so exit false before we do any iterating
|
||||
if (notBefore >= JUNE_1_2016) {
|
||||
aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If the root is not one of the Symantec roots, exit false
|
||||
if (!CertDNIsInList(rootCert->GetCert(), RootSymantecDNs)) {
|
||||
aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Look for one of the intermediates to be in the whitelist
|
||||
bool foundInWhitelist = false;
|
||||
RefPtr<nsNSSCertList> intCertList = intCerts->GetCertList();
|
||||
|
||||
intCertList->ForEachCertificateInChain(
|
||||
[&foundInWhitelist] (nsCOMPtr<nsIX509Cert> aCert, bool aHasMore,
|
||||
/* out */ bool& aContinue) {
|
||||
if (CertDNIsInList(aCert->GetCert(), RootAppleAndGoogleDNs)) {
|
||||
foundInWhitelist = true;
|
||||
aContinue = false;
|
||||
}
|
||||
return NS_OK;
|
||||
});
|
||||
|
||||
// If this chain did not match the whitelist, exit true
|
||||
aResult = !foundInWhitelist;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
SECStatus rv;
|
||||
|
@ -1411,6 +1482,18 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
|||
DetermineEVAndCTStatusAndSetNewCert(status, fd, infoObject);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIX509CertList> succeededCertChain;
|
||||
// This always returns NS_OK, but the list could be empty. This is a
|
||||
// best-effort check for now. Bug 731478 will reduce the incidence of empty
|
||||
// succeeded cert chains through better caching.
|
||||
Unused << status->GetSucceededCertChain(getter_AddRefs(succeededCertChain));
|
||||
bool distrustImminent;
|
||||
nsresult srv = IsCertificateDistrustImminent(succeededCertChain,
|
||||
distrustImminent);
|
||||
if (NS_SUCCEEDED(srv) && distrustImminent) {
|
||||
state |= nsIWebProgressListener::STATE_CERT_DISTRUST_IMMINENT;
|
||||
}
|
||||
|
||||
bool domainMismatch;
|
||||
bool untrusted;
|
||||
bool notValidAtThisTime;
|
||||
|
|
|
@ -269,6 +269,12 @@ nsSecureBrowserUIImpl::MapInternalToExternalState(uint32_t* aState, lockIconStat
|
|||
if (docShell->GetHasTrackingContentLoaded())
|
||||
*aState |= nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT;
|
||||
|
||||
// Copy forward any diagnostic flags for downstream use (e.g., warnings)
|
||||
if (mNewToplevelSecurityStateKnown &&
|
||||
mNewToplevelSecurityState & STATE_CERT_DISTRUST_IMMINENT) {
|
||||
*aState |= nsIWebProgressListener::STATE_CERT_DISTRUST_IMMINENT;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -223,6 +223,18 @@ interface nsIWebProgressListener : nsISupports
|
|||
const unsigned long STATE_LOADED_TRACKING_CONTENT = 0x00002000;
|
||||
const unsigned long STATE_BLOCKED_UNSAFE_CONTENT = 0x00004000;
|
||||
|
||||
/**
|
||||
* Diagnostic flags
|
||||
*
|
||||
* May be set in addition to other security state flags to indicate that
|
||||
* some state is countered that deserves a warning or error, but does not
|
||||
* change the top level security state of the connection.
|
||||
*
|
||||
* STATE_CERT_DISTRUST_IMMINENT
|
||||
* The certificate in use will be distrusted in the near future.
|
||||
*/
|
||||
const unsigned long STATE_CERT_DISTRUST_IMMINENT = 0x00008000;
|
||||
|
||||
/**
|
||||
* Security Strength Flags
|
||||
*
|
||||
|
|
Загрузка…
Ссылка в новой задаче