Bug 1201437 - Add new WebProgress state flag for user-overridden cert. r=keeler

MozReview-Commit-ID: cvBYSZykK0
This commit is contained in:
Nihanth Subramanya 2016-02-24 22:46:52 -08:00
parent d0ec6159f8
commit 1ae326cc39
5 changed files with 86 additions and 32 deletions

View File

@ -5,22 +5,24 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsNSSCallbacks.h"
#include "pkix/pkixtypes.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TimeStamp.h"
#include "nsNSSComponent.h"
#include "nsNSSIOLayer.h"
#include "nsIWebProgressListener.h"
#include "nsProtectedAuthThread.h"
#include "nsContentUtils.h"
#include "nsICertOverrideService.h"
#include "nsIHttpChannelInternal.h"
#include "nsIPrompt.h"
#include "nsISupportsPriority.h"
#include "nsITokenDialogs.h"
#include "nsIUploadChannel.h"
#include "nsIPrompt.h"
#include "nsProxyRelease.h"
#include "PSMRunnable.h"
#include "nsContentUtils.h"
#include "nsIHttpChannelInternal.h"
#include "nsISupportsPriority.h"
#include "nsIWebProgressListener.h"
#include "nsNetUtil.h"
#include "nsNSSComponent.h"
#include "nsNSSIOLayer.h"
#include "nsProtectedAuthThread.h"
#include "nsProxyRelease.h"
#include "pkix/pkixtypes.h"
#include "PSMRunnable.h"
#include "SharedSSLState.h"
#include "ssl.h"
#include "sslproto.h"
@ -1235,6 +1237,17 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
bool renegotiationUnsafe = !siteSupportsSafeRenego &&
ioLayerHelpers.treatUnsafeNegotiationAsBroken();
/* Set the SSL Status information */
RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
if (!status) {
status = new nsSSLStatus();
infoObject->SetSSLStatus(status);
}
RememberCertErrorsTable::GetInstance().LookupCertErrorBits(infoObject,
status);
uint32_t state;
if (usesWeakCipher || renegotiationUnsafe) {
state = nsIWebProgressListener::STATE_IS_BROKEN;
@ -1252,6 +1265,39 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
infoObject->GetPort());
}
}
if (status->HasServerCert()) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("HandshakeCallback KEEPING existing cert\n"));
} else {
ScopedCERTCertificate serverCert(SSL_PeerCertificate(fd));
RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(serverCert.get()));
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("HandshakeCallback using NEW cert %p\n", nssc.get()));
status->SetServerCert(nssc, nsNSSCertificate::ev_status_unknown);
}
nsCOMPtr<nsICertOverrideService> overrideService =
do_GetService(NS_CERTOVERRIDE_CONTRACTID);
if (overrideService) {
bool haveOverride;
uint32_t overrideBits = 0; // Unused.
bool isTemporaryOverride; // Unused.
const nsACString& hostString(infoObject->GetHostName());
const int32_t port(infoObject->GetPort());
nsCOMPtr<nsIX509Cert> cert;
status->GetServerCert(getter_AddRefs(cert));
nsresult nsrv = overrideService->HasMatchingOverride(hostString, port,
cert,
&overrideBits,
&isTemporaryOverride,
&haveOverride);
if (NS_SUCCEEDED(nsrv) && haveOverride) {
state |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}
}
infoObject->SetSecurityState(state);
// XXX Bug 883674: We shouldn't be formatting messages here in PSM; instead,
@ -1270,27 +1316,6 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
nsContentUtils::LogSimpleConsoleError(msg, "SSL");
}
/* Set the SSL Status information */
RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
if (!status) {
status = new nsSSLStatus();
infoObject->SetSSLStatus(status);
}
RememberCertErrorsTable::GetInstance().LookupCertErrorBits(infoObject,
status);
if (status->HasServerCert()) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("HandshakeCallback KEEPING existing cert\n"));
} else {
ScopedCERTCertificate serverCert(SSL_PeerCertificate(fd));
RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(serverCert.get()));
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("HandshakeCallback using NEW cert %p\n", nssc.get()));
status->SetServerCert(nssc, nsNSSCertificate::ev_status_unknown);
}
infoObject->NoteTimeUntilReady();
infoObject->SetHandshakeCompleted();
}

View File

@ -1117,6 +1117,14 @@ nsNSSComponent::InitializeNSS()
return NS_ERROR_FAILURE;
}
// Initialize the cert override service
nsCOMPtr<nsICertOverrideService> coService =
do_GetService(NS_CERTOVERRIDE_CONTRACTID);
if (!coService) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Cannot initialize cert override service\n"));
return NS_ERROR_FAILURE;
}
if (PK11_IsFIPS()) {
Telemetry::Accumulate(Telemetry::FIPS_ENABLED, true);
}

View File

@ -107,6 +107,7 @@ nsSecureBrowserUIImpl::nsSecureBrowserUIImpl()
, mIsViewSource(false)
, mSubRequestsBrokenSecurity(0)
, mSubRequestsNoSecurity(0)
, mCertUserOverridden(false)
, mRestoreSubrequests(false)
, mOnLocationChangeSeen(false)
#ifdef DEBUG
@ -233,6 +234,10 @@ nsSecureBrowserUIImpl::MapInternalToExternalState(uint32_t* aState, lockIconStat
if (ev && (*aState & STATE_IS_SECURE))
*aState |= nsIWebProgressListener::STATE_IDENTITY_EV_TOPLEVEL;
if (mCertUserOverridden && (*aState & STATE_IS_SECURE)) {
*aState |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
if (!docShell)
return NS_OK;
@ -260,6 +265,9 @@ nsSecureBrowserUIImpl::MapInternalToExternalState(uint32_t* aState, lockIconStat
if (ev) {
*aState |= nsIWebProgressListener::STATE_IDENTITY_EV_TOPLEVEL;
}
if (mCertUserOverridden) {
*aState |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}
}
// * If so, the state should be broken or insecure; overriding the previous
// state set by the lock parameter.
@ -793,6 +801,11 @@ nsSecureBrowserUIImpl::OnStateChange(nsIWebProgress* aWebProgress,
f -= nsIWebProgressListener::STATE_SECURE_HIGH;
info.AppendLiteral("SECURE_HIGH ");
}
if (f & nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN)
{
f -= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
info.AppendLiteral("STATE_CERT_USER_OVERRIDDEN ");
}
if (f & nsIWebProgressListener::STATE_RESTORING)
{
f -= nsIWebProgressListener::STATE_RESTORING;
@ -1131,6 +1144,9 @@ nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest,
newSecurityState = lis_broken_security;
}
mCertUserOverridden =
mNewToplevelSecurityState & STATE_CERT_USER_OVERRIDDEN;
MOZ_LOG(gSecureDocLog, LogLevel::Debug,
("SecureUI:%p: UpdateSecurityState: old-new %d - %d\n", this,
mNotifiedSecurityState, newSecurityState));

View File

@ -74,6 +74,7 @@ protected:
int32_t mDocumentRequestsInProgress;
int32_t mSubRequestsBrokenSecurity;
int32_t mSubRequestsNoSecurity;
bool mCertUserOverridden;
bool mRestoreSubrequests;
bool mOnLocationChangeSeen;
#ifdef DEBUG

View File

@ -262,9 +262,13 @@ interface nsIWebProgressListener : nsISupports
*
* STATE_USES_WEAK_CRYPTO
* The topmost document uses a weak cipher suite such as RC4.
*
* STATE_CERT_USER_OVERRIDDEN
* The user has added a security exception for the site.
*/
const unsigned long STATE_USES_SSL_3 = 0x01000000;
const unsigned long STATE_USES_WEAK_CRYPTO = 0x02000000;
const unsigned long STATE_CERT_USER_OVERRIDDEN = 0x04000000;
/**
* Notification indicating the state has changed for one of the requests