Bug 1040323 - SecureBrowserUI needs to consider scheme, not just security of connection. r=dkeeler, a=sledru
authorPatrick McManus <mcmanus@ducksong.com>
Mon, 28 Jul 2014 14:37:41 -0400
changeset 216426 2bea25f0a82b211ba17763dc91cd8df31edcb577
parent 216425 83411dedecb455b1ce5debaa6338beda5f1cb5da
child 216427 e2f568b39d92b12448ebf00771f6d519b545db77
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdkeeler, sledru
bugs1040323
milestone33.0a2
Bug 1040323 - SecureBrowserUI needs to consider scheme, not just security of connection. r=dkeeler, a=sledru
security/manager/boot/src/nsSecureBrowserUIImpl.cpp
security/manager/boot/src/nsSecureBrowserUIImpl.h
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
@@ -42,18 +42,16 @@
 #include "imgIRequest.h"
 #include "nsThreadUtils.h"
 #include "nsNetUtil.h"
 #include "nsNetCID.h"
 #include "nsCRT.h"
 
 using namespace mozilla;
 
-#define IS_SECURE(state) ((state & 0xFFFF) == STATE_IS_SECURE)
-
 #if defined(PR_LOGGING)
 //
 // Log module for nsSecureBrowserUI logging...
 //
 // To enable logging (see prlog.h for full details):
 //
 //    set NSPR_LOG_MODULES=nsSecureBrowserUI:5
 //    set NSPR_LOG_FILE=nspr.log
@@ -329,17 +327,18 @@ static nsresult IsChildOfDomWindow(nsIDO
   child->GetParent(getter_AddRefs(childsParent));
   
   if (childsParent && childsParent.get() != child)
     IsChildOfDomWindow(parent, childsParent, value);
   
   return NS_OK;
 }
 
-static uint32_t GetSecurityStateFromSecurityInfo(nsISupports *info)
+static uint32_t GetSecurityStateFromSecurityInfoAndRequest(nsISupports* info,
+                                                           nsIRequest* request)
 {
   nsresult res;
   uint32_t securityState;
 
   nsCOMPtr<nsITransportSecurityInfo> psmInfo(do_QueryInterface(info));
   if (!psmInfo) {
     PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI: GetSecurityState: - no nsITransportSecurityInfo for %p\n",
                                          (nsISupports *)info));
@@ -349,17 +348,42 @@ static uint32_t GetSecurityStateFromSecu
                                        (nsISupports *)info));
   
   res = psmInfo->GetSecurityState(&securityState);
   if (NS_FAILED(res)) {
     PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI: GetSecurityState: - GetSecurityState failed: %d\n",
                                          res));
     securityState = nsIWebProgressListener::STATE_IS_BROKEN;
   }
-  
+
+  if (securityState != nsIWebProgressListener::STATE_IS_INSECURE) {
+    // A secure connection does not yield a secure per-uri channel if the
+    // scheme is plain http.
+
+    nsCOMPtr<nsIURI> uri;
+    nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
+    if (channel) {
+      channel->GetURI(getter_AddRefs(uri));
+    } else {
+      nsCOMPtr<imgIRequest> imgRequest(do_QueryInterface(request));
+      if (imgRequest) {
+        imgRequest->GetURI(getter_AddRefs(uri));
+      }
+    }
+    if (uri) {
+      bool isHttp, isFtp;
+      if ((NS_SUCCEEDED(uri->SchemeIs("http", &isHttp)) && isHttp) ||
+          (NS_SUCCEEDED(uri->SchemeIs("ftp", &isFtp)) && isFtp)) {
+        PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI: GetSecurityState: - "
+                                             "channel scheme is insecure.\n"));
+        securityState = nsIWebProgressListener::STATE_IS_INSECURE;
+      }
+    }
+  }
+
   PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI: GetSecurityState: - Returning %d\n", 
                                        securityState));
   return securityState;
 }
 
 
 NS_IMETHODIMP
 nsSecureBrowserUIImpl::Notify(nsIDOMHTMLFormElement* aDOMForm,
@@ -464,17 +488,18 @@ nsSecureBrowserUIImpl::EvaluateAndUpdate
      member variables with the same suffix.*/
 
   uint32_t temp_NewToplevelSecurityState = nsIWebProgressListener::STATE_IS_INSECURE;
   bool temp_NewToplevelIsEV = false;
 
   bool updateStatus = false;
   nsCOMPtr<nsISSLStatus> temp_SSLStatus;
 
-    temp_NewToplevelSecurityState = GetSecurityStateFromSecurityInfo(info);
+    temp_NewToplevelSecurityState =
+      GetSecurityStateFromSecurityInfoAndRequest(info, aRequest);
 
     PR_LOG(gSecureDocLog, PR_LOG_DEBUG,
            ("SecureUI:%p: OnStateChange: remember mNewToplevelSecurityState => %x\n", this,
             temp_NewToplevelSecurityState));
 
     nsCOMPtr<nsISSLStatusProvider> sp = do_QueryInterface(info);
     if (sp) {
       // Ignore result
@@ -515,21 +540,23 @@ nsSecureBrowserUIImpl::EvaluateAndUpdate
     mRestoreSubrequests = false;
   }
 
   return UpdateSecurityState(aRequest, withNewLocation,
                              withNewSink || updateStatus);
 }
 
 void
-nsSecureBrowserUIImpl::UpdateSubrequestMembers(nsISupports *securityInfo)
+nsSecureBrowserUIImpl::UpdateSubrequestMembers(nsISupports* securityInfo,
+                                               nsIRequest* request)
 {
   // For wyciwyg channels in subdocuments we only update our
   // subrequest state members.
-  uint32_t reqState = GetSecurityStateFromSecurityInfo(securityInfo);
+  uint32_t reqState = GetSecurityStateFromSecurityInfoAndRequest(securityInfo,
+                                                                 request);
 
   // the code above this line should run without a lock
   ReentrantMonitorAutoEnter lock(mReentrantMonitor);
 
   if (reqState & STATE_IS_SECURE) {
     // do nothing
   } else if (reqState & STATE_IS_BROKEN) {
     PR_LOG(gSecureDocLog, PR_LOG_DEBUG,
@@ -915,17 +942,17 @@ nsSecureBrowserUIImpl::OnStateChange(nsI
           info.get(), info2.get()));
 
   if (aProgressStateFlags & STATE_STOP
       &&
       channel)
   {
     PR_LOG(gSecureDocLog, PR_LOG_DEBUG,
            ("SecureUI:%p: OnStateChange: seeing STOP with security state: %d\n", this,
-            GetSecurityStateFromSecurityInfo(securityInfo)
+            GetSecurityStateFromSecurityInfoAndRequest(securityInfo, aRequest)
             ));
   }
 #endif
 
   if (aProgressStateFlags & STATE_TRANSFERRING
       &&
       aProgressStateFlags & STATE_IS_REQUEST)
   {
@@ -1215,17 +1242,17 @@ nsSecureBrowserUIImpl::OnStateChange(nsI
       return NS_OK;
     
     // if we arrive here, LOAD_DOCUMENT_URI is not set
     
     // We only care for the security state of sub requests which have actually transfered data.
 
     if (allowSecurityStateChange && requestHasTransferedData)
     {  
-      UpdateSubrequestMembers(securityInfo);
+      UpdateSubrequestMembers(securityInfo, aRequest);
       
       // Care for the following scenario:
       // A new top level document load might have already started,
       // but the security state of the new top level document might not yet been known.
       // 
       // At this point, we are learning about the security state of a sub-document.
       // We must not update the security state based on the sub content,
       // if the new top level state is not yet known.
@@ -1448,17 +1475,17 @@ nsSecureBrowserUIImpl::OnLocationChange(
 
   if (windowForProgress.get() == window.get()) {
     // For toplevel channels, update the security state right away.
     mOnLocationChangeSeen = true;
     return EvaluateAndUpdateSecurityState(aRequest, securityInfo, true, false);
   }
 
   // For channels in subdocuments we only update our subrequest state members.
-  UpdateSubrequestMembers(securityInfo);
+  UpdateSubrequestMembers(securityInfo, aRequest);
 
   // Care for the following scenario:
 
   // A new toplevel document load might have already started, but the security
   // state of the new toplevel document might not yet be known.
   // 
   // At this point, we are learning about the security state of a sub-document.
   // We must not update the security state based on the sub content, if the new
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.h
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.h
@@ -101,17 +101,17 @@ protected:
   nsresult UpdateSecurityState(nsIRequest* aRequest, bool withNewLocation,
                                bool withUpdateStatus);
   bool UpdateMyFlags(lockIconState &warnSecurityState);
   nsresult TellTheWorld(lockIconState warnSecurityState, 
                         nsIRequest* aRequest);
 
   nsresult EvaluateAndUpdateSecurityState(nsIRequest* aRequest, nsISupports *info,
                                           bool withNewLocation, bool withNewSink);
-  void UpdateSubrequestMembers(nsISupports *securityInfo);
+  void UpdateSubrequestMembers(nsISupports* securityInfo, nsIRequest* request);
 
   void ObtainEventSink(nsIChannel *channel, 
                        nsCOMPtr<nsISecurityEventSink> &sink);
 
   nsCOMPtr<nsISSLStatus> mSSLStatus;
   nsCOMPtr<nsISupports> mCurrentToplevelSecurityInfo;
 
   nsresult CheckPost(nsIURI *formURI, nsIURI *actionURL, bool *okayToPost);