Bug 389816: Port badCertHandler to xpinstall. r+sr=dveditz, a=bzbarsky
authordtownsend@oxymoronical.com
Tue, 28 Aug 2007 11:01:37 -0700
changeset 5388 465e4be16d23d2f9d065d4c5df97cddfe07a5fe4
parent 5387 ea7b8becfc6555f2474f4174556a27af2dfbd1cf
child 5389 648a7e238f51a2f296fd4f7bb1065bff6cb10e35
push idunknown
push userunknown
push dateunknown
reviewersbzbarsky
bugs389816
milestone1.9a8pre
Bug 389816: Port badCertHandler to xpinstall. r+sr=dveditz, a=bzbarsky
xpinstall/src/Makefile.in
xpinstall/src/nsXPInstallManager.cpp
xpinstall/src/nsXPInstallManager.h
--- a/xpinstall/src/Makefile.in
+++ b/xpinstall/src/Makefile.in
@@ -83,16 +83,18 @@ REQUIRES	= xpcom \
 		  plugin \
 		  unicharutil \
 		  appshell \
 		  docshell \
 		  layout \
 		  chrome \
 		  extensions \
 		  embed_base \
+		  pipnss \
+		  pipboot \
 		  $(ZLIB_REQUIRES) \
 		  $(NULL)
 
 # XXX shouldn't need to export this
 EXPORTS		= nsXPITriggerInfo.h
 
 CPPSRCS		= \
 		CertReader.cpp \
--- a/xpinstall/src/nsXPInstallManager.cpp
+++ b/xpinstall/src/nsXPInstallManager.cpp
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Daniel Veditz <dveditz@netscape.com>
+ *   Dave Townsend <dtownsend@oxymoronical.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -75,16 +76,20 @@
 #include "nsReadableUtils.h"
 #include "nsProxiedService.h"
 #include "nsIPromptService.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIObserverService.h"
 
+#include "nsISSLStatusProvider.h"
+#include "nsISSLStatus.h"
+#include "nsIX509Cert.h"
+
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 
 #include "CertReader.h"
 
 #include "nsEmbedCID.h"
 
 static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
@@ -105,17 +110,17 @@ inline PRBool nsXPInstallManager::TimeTo
 
 	return PR_TRUE;
 }
 
 
 nsXPInstallManager::nsXPInstallManager()
   : mTriggers(0), mItem(0), mNextItem(0), mNumJars(0), mChromeType(NOT_CHROME),
     mContentLength(0), mDialogOpen(PR_FALSE), mCancelled(PR_FALSE),
-    mSelectChrome(PR_FALSE), mNeedsShutdown(PR_FALSE)
+    mSelectChrome(PR_FALSE), mNeedsShutdown(PR_FALSE), mFromChrome(PR_FALSE)
 {
     // we need to own ourself because we have a longer
     // lifetime than the scriptlet that created us.
     NS_ADDREF_THIS();
 
     // initialize mLastUpdate to the current time
     mLastUpdate = PR_Now();
 
@@ -127,25 +132,27 @@ nsXPInstallManager::nsXPInstallManager()
 
 nsXPInstallManager::~nsXPInstallManager()
 {
     if (mTriggers)
         delete mTriggers;
 }
 
 
-NS_IMPL_THREADSAFE_ISUPPORTS9( nsXPInstallManager,
+NS_IMPL_THREADSAFE_ISUPPORTS11(nsXPInstallManager,
                                nsIXPIListener,
                                nsIXPIDialogService,
                                nsIXPInstallManager,
                                nsIObserver,
                                nsIStreamListener,
                                nsIProgressEventSink,
                                nsIInterfaceRequestor,
                                nsPICertNotification,
+                               nsIBadCertListener,
+                               nsIChannelEventSink,
                                nsISupportsWeakReference)
 
 NS_IMETHODIMP
 nsXPInstallManager::InitManagerFromChrome(const PRUnichar **aURLs,
                                           PRUint32 aURLCount,
                                           nsIXPIProgressDialog* aListener)
 {
     return InitManagerWithHashes(aURLs, nsnull, aURLCount, aListener);
@@ -192,16 +199,18 @@ nsXPInstallManager::InitManagerWithHashe
     if (NS_FAILED(rv)) 
     {
         delete mTriggers;
         mTriggers = nsnull;
         Shutdown();
         return rv;
     }
 
+    mFromChrome = PR_TRUE;
+    
     rv = Observe(aListener, XPI_PROGRESS_TOPIC, NS_LITERAL_STRING("open").get());
     if (NS_FAILED(rv))
         Shutdown();
     return rv;
 }
 
 
 NS_IMETHODIMP
@@ -970,27 +979,76 @@ nsXPInstallManager::GetDestinationFile(n
                     NS_IF_ADDREF(*file);
                 }
             }
         }
     }
     return rv;
 }
 
-
+nsresult
+nsXPInstallManager::CheckCert(nsIChannel* aChannel)
+{
+    nsCOMPtr<nsIURI> uri;
+    nsresult rv = aChannel->GetOriginalURI(getter_AddRefs(uri));
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCAutoString scheme;
+    rv = uri->GetScheme(scheme);
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (!scheme.Equals(NS_LITERAL_CSTRING("https")))
+        return NS_OK;
+    
+    nsCOMPtr<nsISupports> security;
+    rv = aChannel->GetSecurityInfo(getter_AddRefs(security));
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsISSLStatusProvider> statusProvider(do_QueryInterface(security));
+    NS_ENSURE_TRUE(statusProvider, NS_ERROR_FAILURE);
+    
+    rv = statusProvider->GetSSLStatus(getter_AddRefs(security));
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsISSLStatus> status(do_QueryInterface(security));
+    NS_ENSURE_TRUE(status, NS_ERROR_FAILURE);
+    nsCOMPtr<nsIX509Cert> cert;
+    rv = status->GetServerCert(getter_AddRefs(cert));
+    NS_ENSURE_SUCCESS(rv, rv);
+    
+    nsCOMPtr<nsIX509Cert> issuer;
+    rv = cert->GetIssuer(getter_AddRefs(issuer));
+    NS_ENSURE_SUCCESS(rv, rv);
+    PRBool equal;
+    while (issuer && NS_SUCCEEDED(cert->Equals(issuer, &equal)) && !equal) {
+        cert = issuer;
+        rv = cert->GetIssuer(getter_AddRefs(issuer));
+        NS_ENSURE_SUCCESS(rv, rv);
+    }
+    
+    if (issuer) {
+        nsAutoString tokenName;
+        rv = issuer->GetTokenName(tokenName);
+        NS_ENSURE_SUCCESS(rv ,rv);
+        if (tokenName.Equals(NS_LITERAL_STRING("Builtin Object Token")))
+            return NS_OK;
+    }
+    return NS_ERROR_FAILURE;
+}
 
 NS_IMETHODIMP
 nsXPInstallManager::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
 {
     nsresult rv = NS_ERROR_FAILURE;
 
     // If we are dealing with a HTTP request, then treat HTTP error pages as
     // download failures.
     nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(request);
     if (httpChan) {
+        // If we were chrome lauched check the certificate on the request
+        if (mFromChrome && NS_FAILED(CheckCert(httpChan))) {
+            request->Cancel(NS_BINDING_ABORTED);
+            return NS_OK;
+        }
         PRBool succeeded;
         if (NS_SUCCEEDED(httpChan->GetRequestSucceeded(&succeeded)) && !succeeded) {
             // HTTP response is not a 2xx!
             request->Cancel(NS_BINDING_ABORTED);
             return NS_OK;
         }
     }
 
@@ -1163,19 +1221,62 @@ nsXPInstallManager::GetInterface(const n
         rv = ww->GetNewAuthPrompter(nsnull, getter_AddRefs(prompt));
         NS_ENSURE_SUCCESS(rv, rv);
  
         nsIAuthPrompt *p = prompt.get();
         NS_ADDREF(p);
         *_retval = p;
         return NS_OK;
     }
+    else if (eventSinkIID.Equals(NS_GET_IID(nsIBadCertListener))) {
+        // If we aren't chrome triggered fall back to the default dialogs
+        if (!mFromChrome)
+            return NS_ERROR_NO_INTERFACE;
+    }
     return QueryInterface(eventSinkIID, (void**)_retval);
 }
 
+// nsIChannelEventSink method
+NS_IMETHODIMP
+nsXPInstallManager::OnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel, PRUint32 flags)
+{
+    // Chrome triggered installs need to have their certificates checked
+    if (mFromChrome)
+        return CheckCert(oldChannel);
+    return NS_OK;
+}
+
+// nsIBadCertListener methods
+NS_IMETHODIMP
+nsXPInstallManager::ConfirmUnknownIssuer(nsIInterfaceRequestor *socketInfo, nsIX509Cert *cert, PRInt16 *certAddType, PRBool *_retval)
+{
+    *_retval = PR_FALSE;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXPInstallManager::ConfirmMismatchDomain(nsIInterfaceRequestor *socketInfo, const nsACString & targetURL, nsIX509Cert *cert, PRBool *_retval)
+{
+    *_retval = PR_FALSE;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXPInstallManager::ConfirmCertExpired(nsIInterfaceRequestor *socketInfo, nsIX509Cert *cert, PRBool *_retval)
+{
+    *_retval = PR_FALSE;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXPInstallManager::NotifyCrlNextupdate(nsIInterfaceRequestor *socketInfo, const nsACString & targetURL, nsIX509Cert *cert)
+{
+    return NS_OK;
+}
+
 // IXPIListener methods
 
 PRInt32 
 nsXPInstallManager::GetIndexFromURL(const PRUnichar* aUrl)
 {
     // --- figure out which index corresponds to this URL
     PRUint32 i;
     for (i=0; i < mTriggers->Size(); i++)
--- a/xpinstall/src/nsXPInstallManager.h
+++ b/xpinstall/src/nsXPInstallManager.h
@@ -51,16 +51,18 @@
 #include "nsIXPINotifier.h"
 #include "nsIXPInstallManager.h"
 #include "nsIXPIDialogService.h"
 #include "nsXPITriggerInfo.h"
 #include "nsIXPIProgressDialog.h"
 #include "nsIChromeRegistry.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIObserver.h"
+#include "nsIBadCertListener.h"
+#include "nsIChannelEventSink.h"
 
 #include "nsISoftwareUpdate.h"
 
 #include "nsCOMPtr.h"
 
 #include "nsIProgressEventSink.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
@@ -78,60 +80,66 @@
 class nsXPInstallManager : public nsIXPIListener,
                            public nsIXPIDialogService,
                            public nsIXPInstallManager,
                            public nsIObserver,
                            public nsIStreamListener,
                            public nsIProgressEventSink,
                            public nsIInterfaceRequestor,
                            public nsPICertNotification,
+                           public nsIBadCertListener,
+                           public nsIChannelEventSink,
                            public nsSupportsWeakReference
 {
     public:
         nsXPInstallManager();
         virtual ~nsXPInstallManager();
 
         NS_DECL_ISUPPORTS
         NS_DECL_NSIXPILISTENER
         NS_DECL_NSIXPIDIALOGSERVICE
         NS_DECL_NSIXPINSTALLMANAGER
         NS_DECL_NSIOBSERVER
         NS_DECL_NSISTREAMLISTENER
         NS_DECL_NSIPROGRESSEVENTSINK
         NS_DECL_NSIREQUESTOBSERVER
         NS_DECL_NSIINTERFACEREQUESTOR
         NS_DECL_NSPICERTNOTIFICATION
+        NS_DECL_NSIBADCERTLISTENER
+        NS_DECL_NSICHANNELEVENTSINK
 
         NS_IMETHOD InitManager(nsIScriptGlobalObject* aGlobalObject, nsXPITriggerInfo* aTrigger, PRUint32 aChromeType );
 
     private:
         nsresult    InitManagerInternal();
         NS_IMETHOD  DownloadNext();
         void        Shutdown();
         NS_IMETHOD  GetDestinationFile(nsString& url, nsILocalFile* *file);
         NS_IMETHOD  LoadParams(PRUint32 aCount, const PRUnichar** aPackageList, nsIDialogParamBlock** aParams);
 #ifdef ENABLE_SKIN_SIMPLE_INSTALLATION_UI
         PRBool      ConfirmChromeInstall(nsIDOMWindowInternal* aParentWindow, const PRUnichar** aPackage);
 #endif
         PRBool      TimeToUpdate(PRTime now);
         PRBool      VerifyHash(nsXPITriggerItem* aItem);
         PRInt32     GetIndexFromURL(const PRUnichar* aUrl);
+        nsresult    CheckCert(nsIChannel* aChannel);
 
         nsXPITriggerInfo*   mTriggers;
         nsXPITriggerItem*   mItem;
         PRTime              mLastUpdate;
         PRUint32            mNextItem;
         PRInt32             mNumJars;
         PRUint32            mChromeType;
         PRInt32             mContentLength;
         PRInt32             mOutstandingCertLoads;
         PRBool              mDialogOpen;
         PRBool              mCancelled;
         PRBool              mSelectChrome;
         PRBool              mNeedsShutdown;
+        PRBool              mFromChrome;
   
         nsCOMPtr<nsIXPIProgressDialog>  mDlg;
         nsCOMPtr<nsISoftwareUpdate>     mInstallSvc;
 
         nsCOMPtr<nsIDOMWindowInternal>  mParentWindow;
 };
 
 #endif