Bug 439722, Make the "bad cert error dialog" more helpful
r=rrelyea, sr=dveditz
--- a/security/manager/locales/en-US/chrome/pippki/pippki.dtd
+++ b/security/manager/locales/en-US/chrome/pippki/pippki.dtd
@@ -124,8 +124,12 @@
<!ENTITY formSigning.title "Text Signing Request">
<!ENTITY formSigning.cert "Signing Certificate">
<!ENTITY formSigning.confirmPassword "To confirm you agree to sign this text message using your selected certificate, please confirm by entering the master password:">
<!-- Strings for protectedAuth dialog -->
<!ENTITY protectedAuth.title "Protected Token Authentication">
<!ENTITY protectedAuth.msg "Please authenticate to the token. Authentication method depends on the type of your token.">
<!ENTITY protectedAuth.tokenName.label "Token:">
+
+<!ENTITY certErrorDlg.title "Secure Connection Failed">
+<!ENTITY certErrorDlg.info1 "This could be a problem with the server's configuration or it could be someone trying to impersonate the server.">
+<!ENTITY certErrorDlg.info2 "If you have connected to this server successfully in the past the error may be temporary and you can try again later.">
new file mode 100644
--- /dev/null
+++ b/security/manager/pki/resources/content/certerror.js
@@ -0,0 +1,29 @@
+const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
+const nsIPKIParamBlock = Components.interfaces.nsIPKIParamBlock;
+const nsIX509Cert = Components.interfaces.nsIX509Cert;
+
+var dialogParams;
+var pkiParams;
+var cert;
+var hostport;
+
+function initCertErrorDialog()
+{
+ pkiParams = window.arguments[0].QueryInterface(nsIPKIParamBlock);
+ dialogParams = pkiParams.QueryInterface(nsIDialogParamBlock);
+
+ var isupport = pkiParams.getISupportAtIndex(1);
+ cert = isupport.QueryInterface(nsIX509Cert);
+
+ var portNumber = dialogParams.GetInt(1);
+ var hostName = dialogParams.GetString(1);
+ var msg = dialogParams.GetString(2);
+
+ hostport = hostName + ":" + portNumber;
+ setText("warningText", msg);
+}
+
+function viewCert()
+{
+ viewCertHelper(window, cert);
+}
new file mode 100644
--- /dev/null
+++ b/security/manager/pki/resources/content/certerror.xul
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is mozilla.org code.
+ -
+ - The Initial Developer of the Original Code is
+ - Red Hat, Inc.
+ - Portions created by the Initial Developer are Copyright (C) 2007
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Kai Engert <kaie@netscape.com>
+ - Johnathan Nightingale <johnath@mozilla.com>
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either 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
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE dialog [
+<!ENTITY % pippkiDTD SYSTEM "chrome://pippki/locale/pippki.dtd" >
+%pippkiDTD;
+]>
+
+<dialog id="certErrorDialog" title="&certErrorDlg.title;"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ style="width: 47em;"
+ onload="initCertErrorDialog();"
+ buttons="cancel,extra1"
+ defaultButton="cancel"
+ buttonlabelextra1="&examineCert.label;"
+ buttonaccesskeyextra1="&examineCert.accesskey;"
+ ondialogextra1="viewCert();">
+
+<script type="application/x-javascript" src="chrome://global/content/strres.js"/>
+<script type="application/x-javascript" src="chrome://pippki/content/pippki.js"/>
+<script type="application/x-javascript" src="chrome://pippki/content/certerror.js"/>
+
+<hbox>
+ <vbox>
+#ifdef MOZ_WIDGET_GTK2
+ <image src="moz-icon://stock/gtk-dialog-warning?size=dialog"/>
+#else
+ <image src="chrome://global/skin/icons/warning-large.png"/>
+#endif
+ <spacer flex="1"/>
+ </vbox>
+ <vbox flex="1">
+ <description id="warningText"
+ style="white-space: pre-wrap"/>
+ <separator/>
+ <description id="info1">&certErrorDlg.info1;</description>
+ <description id="info2">&certErrorDlg.info2;</description>
+ </vbox>
+</hbox>
+</dialog>
--- a/security/manager/pki/resources/jar.mn
+++ b/security/manager/pki/resources/jar.mn
@@ -11,16 +11,18 @@ pippki.jar:
content/pippki/resetpassword.js (content/resetpassword.js)
content/pippki/PrefOverlay.xul (content/PrefOverlay.xul)
content/pippki/pref-security.js (content/pref-security.js)
content/pippki/pref-ssl.xul (content/pref-ssl.xul)
content/pippki/pref-certs.xul (content/pref-certs.xul)
#ifndef MOZ_PHOENIX
content/pippki/PageInfoOverlay.xul (content/PageInfoOverlay.xul)
#endif
+ content/pippki/certerror.js (content/certerror.js)
+* content/pippki/certerror.xul (content/certerror.xul)
content/pippki/downloadcert.js (content/downloadcert.js)
content/pippki/downloadcert.xul (content/downloadcert.xul)
content/pippki/cacertexists.xul (content/cacertexists.xul)
content/pippki/certManager.js (content/certManager.js)
content/pippki/certManager.xul (content/certManager.xul)
content/pippki/CAOverlay.xul (content/CAOverlay.xul)
content/pippki/WebSitesOverlay.xul (content/WebSitesOverlay.xul)
content/pippki/OthersOverlay.xul (content/OthersOverlay.xul)
--- a/security/manager/pki/src/nsNSSDialogs.cpp
+++ b/security/manager/pki/src/nsNSSDialogs.cpp
@@ -54,16 +54,17 @@
#include "nsIStringBundle.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIX509Cert.h"
#include "nsIX509CertDB.h"
#include "nsILocaleService.h"
#include "nsIDateTimeFormat.h"
#include "nsDateTimeFormatCID.h"
+#include "nsPromiseFlatString.h"
#include "nsNSSDialogs.h"
#include "nsPKIParamBlock.h"
#include "nsIKeygenThread.h"
#include "nsIProtectedAuthThread.h"
#include "nsNSSDialogHelper.h"
#include "nsIWindowWatcher.h"
#include "nsIX509CertValidity.h"
@@ -76,23 +77,24 @@
nsNSSDialogs::nsNSSDialogs()
{
}
nsNSSDialogs::~nsNSSDialogs()
{
}
-NS_IMPL_THREADSAFE_ISUPPORTS7(nsNSSDialogs, nsITokenPasswordDialogs,
+NS_IMPL_THREADSAFE_ISUPPORTS8(nsNSSDialogs, nsITokenPasswordDialogs,
nsICertificateDialogs,
nsIClientAuthDialogs,
nsICertPickDialogs,
nsITokenDialogs,
nsIDOMCryptoDialogs,
- nsIGeneratingKeypairInfoDialogs)
+ nsIGeneratingKeypairInfoDialogs,
+ nsISSLCertErrorDialog)
nsresult
nsNSSDialogs::Init()
{
nsresult rv;
nsCOMPtr<nsIStringBundleService> service =
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
@@ -605,8 +607,51 @@ nsNSSDialogs::DisplayProtectedAuth(nsIIn
"chrome://pippki/content/protectedAuth.xul",
"_blank",
"centerscreen,chrome,modal,titlebar,close=no",
runnable,
getter_AddRefs(newWindow));
return rv;
}
+
+NS_IMETHODIMP
+nsNSSDialogs::ShowCertError(nsIInterfaceRequestor *ctx,
+ nsISSLStatus *status,
+ nsIX509Cert *cert,
+ const nsAString & textErrorMessage,
+ const nsAString & htmlErrorMessage,
+ const nsACString & hostName,
+ PRUint32 portNumber)
+{
+ nsCOMPtr<nsIPKIParamBlock> block =
+ do_CreateInstance(NS_PKIPARAMBLOCK_CONTRACTID);
+ if (!block)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsIDialogParamBlock> dialogBlock = do_QueryInterface(block);
+
+ nsresult rv;
+ rv = dialogBlock->SetInt(1, portNumber);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NS_ConvertUTF8toUTF16 host16(hostName);
+ nsPromiseFlatString flatHostName(host16);
+ nsPromiseFlatString flatMessage(textErrorMessage);
+
+ rv = dialogBlock->SetString(1, flatHostName.get());
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = dialogBlock->SetString(2, flatMessage.get());
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = block->SetISupportAtIndex(1, cert);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = nsNSSDialogHelper::openDialog(nsnull,
+ "chrome://pippki/content/certerror.xul",
+ block);
+ return rv;
+}
--- a/security/manager/pki/src/nsNSSDialogs.h
+++ b/security/manager/pki/src/nsNSSDialogs.h
@@ -42,42 +42,45 @@
#include "nsITokenPasswordDialogs.h"
#include "nsICertificateDialogs.h"
#include "nsIClientAuthDialogs.h"
#include "nsICertPickDialogs.h"
#include "nsITokenDialogs.h"
#include "nsIDOMCryptoDialogs.h"
#include "nsIGenKeypairInfoDlg.h"
+#include "nsISSLCertErrorDialog.h"
#include "nsCOMPtr.h"
#include "nsIStringBundle.h"
#define NS_NSSDIALOGS_CID \
{ 0x518e071f, 0x1dd2, 0x11b2, \
{ 0x93, 0x7e, 0xc4, 0x5f, 0x14, 0xde, 0xf7, 0x78 }}
class nsNSSDialogs
: public nsITokenPasswordDialogs,
public nsICertificateDialogs,
public nsIClientAuthDialogs,
public nsICertPickDialogs,
public nsITokenDialogs,
public nsIDOMCryptoDialogs,
- public nsIGeneratingKeypairInfoDialogs
+ public nsIGeneratingKeypairInfoDialogs,
+ public nsISSLCertErrorDialog
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSITOKENPASSWORDDIALOGS
NS_DECL_NSICERTIFICATEDIALOGS
NS_DECL_NSICLIENTAUTHDIALOGS
NS_DECL_NSICERTPICKDIALOGS
NS_DECL_NSITOKENDIALOGS
NS_DECL_NSIDOMCRYPTODIALOGS
NS_DECL_NSIGENERATINGKEYPAIRINFODIALOGS
+ NS_DECL_NSISSLCERTERRORDIALOG
nsNSSDialogs();
virtual ~nsNSSDialogs();
nsresult Init();
protected:
nsCOMPtr<nsIStringBundle> mPIPStringBundle;
};
--- a/security/manager/pki/src/nsPKIModule.cpp
+++ b/security/manager/pki/src/nsPKIModule.cpp
@@ -39,29 +39,37 @@
#include "nsIModule.h"
#include "nsIGenericFactory.h"
#include "nsNSSDialogs.h"
#include "nsPKIParamBlock.h"
#include "nsASN1Tree.h"
#include "nsFormSigningDialog.h"
+#include "nsISSLCertErrorDialog.h"
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNSSDialogs, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPKIParamBlock, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsNSSASN1Tree)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormSigningDialog)
#define NSS_DIALOGS_DESCRIPTION "PSM Dialog Impl"
static const nsModuleComponentInfo components[] =
{
{
NSS_DIALOGS_DESCRIPTION,
NS_NSSDIALOGS_CID,
+ NS_SSLCERTERRORDIALOG_CONTRACTID,
+ nsNSSDialogsConstructor
+ },
+
+ {
+ NSS_DIALOGS_DESCRIPTION,
+ NS_NSSDIALOGS_CID,
NS_TOKENPASSWORDSDIALOG_CONTRACTID,
nsNSSDialogsConstructor
},
{
NSS_DIALOGS_DESCRIPTION,
NS_NSSDIALOGS_CID,
NS_CERTIFICATEDIALOGS_CONTRACTID,
--- a/security/manager/ssl/public/Makefile.in
+++ b/security/manager/ssl/public/Makefile.in
@@ -54,16 +54,17 @@ SDK_XPIDLSRCS = \
nsICertificateDialogs.idl \
nsICRLInfo.idl \
nsIX509Cert.idl \
nsIX509CertDB.idl \
nsIX509CertValidity.idl \
$(NULL)
XPIDLSRCS = \
+ nsISSLCertErrorDialog.idl \
nsIBadCertListener2.idl \
nsISSLErrorListener.idl \
nsIIdentityInfo.idl \
nsIAssociatedContentSecurity.idl \
nsICertOverrideService.idl \
nsIRecentBadCertsService.idl \
nsIFormSigningDialog.idl \
nsIX509Cert2.idl \
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/public/nsISSLCertErrorDialog.idl
@@ -0,0 +1,72 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Red Hat, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Kai Engert <kaie@redhat.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIInterfaceRequestor;
+interface nsIX509Cert;
+interface nsISSLStatus;
+
+[scriptable, uuid(0729ce8e-8935-4989-ba72-a2d6307f2365)]
+interface nsISSLCertErrorDialog : nsISupports
+{
+ /**
+ * Called when an SSL connection aborts because of a bad certificate,
+ * and no other code is in place for reporting the problem.
+ * Should bring up a dialog to inform the user and display the certificate.
+ *
+ * @param status Might be used to query additional information
+ * @param cert The certificate that this error is about
+ * @param textErrorMessage An error message with whitespace formatting
+ * @param htmlErrorMessage Optional, might either be empty,
+ or might contain the same message as in
+ textErrorMessage plus some html formatting.
+ * @param hostName The error occurred when connecting to this hostName.
+ * @param portNumber The error occurred when connecting to this portNumber.
+ */
+ void showCertError(in nsIInterfaceRequestor ctx,
+ in nsISSLStatus status,
+ in nsIX509Cert cert,
+ in AString textErrorMessage,
+ in AString htmlErrorMessage,
+ in ACString hostName,
+ in PRUint32 portNumber);
+};
+
+%{C++
+#define NS_SSLCERTERRORDIALOG_CONTRACTID "@mozilla.org/nsSSLCertErrorDialog;1"
+%}
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -60,16 +60,17 @@
#include "nsIClientAuthDialogs.h"
#include "nsClientAuthRemember.h"
#include "nsICertOverrideService.h"
#include "nsIBadCertListener2.h"
#include "nsISSLErrorListener.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsRecentBadCerts.h"
+#include "nsISSLCertErrorDialog.h"
#include "nsXPIDLString.h"
#include "nsReadableUtils.h"
#include "nsHashSets.h"
#include "nsCRT.h"
#include "nsAutoPtr.h"
#include "nsPrintfCString.h"
#include "nsAutoLock.h"
@@ -1387,23 +1388,44 @@ nsHandleInvalidCertError(nsNSSSocketInfo
}
else
{
nsPSMUITracker tracker;
if (tracker.isUIForbidden()) {
rv = NS_ERROR_NOT_AVAILABLE;
}
else {
- rv = displayAlert(formattedString, socketInfo);
+ nsISSLCertErrorDialog *dialogs = nsnull;
+ rv = getNSSDialogs((void**)&dialogs,
+ NS_GET_IID(nsISSLCertErrorDialog),
+ NS_SSLCERTERRORDIALOG_CONTRACTID);
+
+ if (NS_SUCCEEDED(rv)) {
+ nsPSMUITracker tracker;
+ if (tracker.isUIForbidden()) {
+ rv = NS_ERROR_NOT_AVAILABLE;
+ }
+ else {
+ nsCOMPtr<nsISSLStatus> status;
+ socketInfo->GetSSLStatus(getter_AddRefs(status));
+
+ nsString empty;
+
+ rv = dialogs->ShowCertError(nsnull, status, ix509,
+ formattedString,
+ empty, host, port);
+ }
+
+ NS_RELEASE(dialogs);
+ }
}
}
return rv;
}
-
static PRStatus PR_CALLBACK
nsSSLIOLayerConnect(PRFileDesc* fd, const PRNetAddr* addr,
PRIntervalTime timeout)
{
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] connecting SSL socket\n", (void*)fd));
nsNSSShutDownPreventionLock locker;
if (!fd || !fd->lower)
return PR_FAILURE;