Make the new server cert dialog for SSL warning work.

This commit is contained in:
javi%netscape.com 2001-02-16 22:17:52 +00:00
parent cbc4c7b484
commit fd5d0bcad4
13 changed files with 549 additions and 30 deletions

View File

@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Javier Delgadillo <javi@netscape.com>
*/
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
var params;
function setText(id, value) {
var element = document.getElementById(id);
if (!element) return;
if (element.hasChildNodes())
element.removeChild(element.firstChild);
var textNode = document.createTextNode(value);
element.appendChild(textNode);
}
function onLoad()
{
params = window.arguments[0].QueryInterface(nsIDialogParamBlock);
serverName = params.GetString(1);
var bundle = srGetStrBundle("chrome://pippki/locale/newserver.properties");
var gBundleBrand = srGetStrBundle("chrome://global/locale/brand.properties");
var brandName = gBundleBrand.GetStringFromName("brandShortName");
var message1 = bundle.formatStringFromName("newServerMessage1",
[ serverName, brandName ],
2);
var message4 = bundle.formatStringFromName("newServerMessage4",
[ serverName ],
1);
setText("message1", message1);
setText("message4", message4);
}
function doOK()
{
params.SetInt(1,1);
var radioGroup = document.getElementById("trustSiteCert");
params.SetInt(2,parseInt(radioGroup.selectedItem.data));
window.close();
}
function doCancel()
{
params.SetInt(1,0);
window.close();
}

View File

@ -0,0 +1,76 @@
<?xml version="1.0"?>
<!--
- 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.
-
-
- Contributor(s):
- Javier Delgadillo <javi@netscape.com>
- Bob Lord <lord@netscape.com>
-->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://pippki/locale/newserver.dtd">
<window
id="ssl_warning" title="&newserver.title;"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
debug="false"
height="350"
width="400"
onload="onLoad();"
>
<script src="chrome://global/content/strres.js" />
<script src="newserver.js" />
<box orient="vertical" style="margin: 5px;" flex="1">
<html id="message1" />
<separator/>
<html>&newserver.message2;</html>
<separator/>
<html>&newserver.message3;</html>
<separator/>
<html id="message4" />
<radiogroup id="trustSiteCert" pref="false" orient="vertical">
<radio group="trustSiteCert"
value="&newserver.acceptperm;"
id="acceptRadio"
data="0"/>
<radio group="trustSiteCert"
value="&newserver.accepttemp;"
id="tmpAcceptRadio"
data="1" checked="true"/>
<radio group="trustSiteCert"
id="rejectRadio"
value="&newserver.reject;" data="2"/>
</radiogroup>
<!--
<box>
<button id="examineCert-button" class="dialog" value="Examine Certificate"
onclick=""/>
</box>
<separator/>
-->
<box>
<button id="ok-button" class="dialog" value="&newserver.okButton.label;"
style="width: 8ex" onclick="doOK();" disabled="false"/>
<button id="cancel-button" class="dialog" value="&newserver.cancelButton.label;"
style="width: 8ex" onclick="doCancel();" />
<button id="help-button" class="dialog" value="&newserver.helpButton.label;"
style="width: 8ex" onclick="alert('Will bring up help one day');" />
</box>
</box>
</window>

View File

@ -1,12 +1,16 @@
pippki.jar:
content/pippki/contents.rdf (content/contents.rdf)
content/pippki/changepassword.xul (content/changepassword.xul)
content/pippki/password.js (content/password.js)
content/pippki/PrefOverlay.xul (content/PrefOverlay.xul)
content/pippki/contents.rdf (content/contents.rdf)
content/pippki/changepassword.xul (content/changepassword.xul)
content/pippki/password.js (content/password.js)
content/pippki/PrefOverlay.xul (content/PrefOverlay.xul)
content/pippki/SecurityPrefs.xul (content/SecurityPrefs.xul)
content/pippki/SSLPrefs.xul (content/SSLPrefs.xul)
locale/en-US/pippki/contents.rdf (locale/en-US/contents.rdf)
locale/en-US/pippki/pippki.dtd (locale/en-US/pippki.dtd)
locale/en-US/pippki/SSLPrefs.dtd (locale/en-US/SSLPrefs.dtd)
locale/en-US/pippki/pippki.properties (locale/en-US/pippki.properties)
locale/en-US/pippki/PrefOverlay.dtd (locale/en-US/PrefOverlay.dtd)
content/pippki/SSLPrefs.xul (content/SSLPrefs.xul)
content/pippki/newserver.js (content/newserver.js)
content/pippki/newserver.xul (content/newserver.xul)
locale/en-US/pippki/contents.rdf (locale/en-US/contents.rdf)
locale/en-US/pippki/pippki.dtd (locale/en-US/pippki.dtd)
locale/en-US/pippki/SSLPrefs.dtd (locale/en-US/SSLPrefs.dtd)
locale/en-US/pippki/pippki.properties (locale/en-US/pippki.properties)
locale/en-US/pippki/PrefOverlay.dtd (locale/en-US/PrefOverlay.dtd)
locale/en-US/pippki/newserver.properties (locale/en-US/newserver.properties)
locale/en-US/pippki/newserver.dtd (locale/en-US/newserver.dtd)

View File

@ -0,0 +1,27 @@
<!--
- 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.
-
-
- Contributor(s):
- Javier Delgadillo <javi@netscape.com>
- Bob Lord <lord@netscape.com>
-->
<!-- Values for newserver.xul -->
<!ENTITY newserver.title "Security Error: Unknown CA">
<!ENTITY newserver.message2 "Although the Certificate Authority is unrecognized, you can choose to explicitly accept the certificate used by this web site.">
<!ENTITY newserver.message3 "Before accepting this certificate, you should examine this site's certificate carefully.">
<!ENTITY newserver.acceptperm "Accept this certificate permanently">
<!ENTITY newserver.accepttemp "Accept this certificate temporarily for this session">
<!ENTITY newserver.reject "Do not accept this certificate and do not connect to this web site">
<!ENTITY newserver.helpButton.label "Help">
<!ENTITY newserver.okButton.label "OK">
<!ENTITY newserver.cancelButton.label "Cancel">

View File

@ -0,0 +1,27 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Javier Delgadillo <javi@netscape.com>
# Bob Lord <lord@netscape.com>
#
newServerMessage1="%S" is a web site that uses a security certificate to identify itself. However, %S does not recognize the Certificate Authority that issued this certificate.
newServerMessage4=Are you willing to accept this certificate for the purpose of identifying the web site "%S"?

View File

@ -19,7 +19,8 @@
*
* Contributor(s):
* Terry Hayes <thayes@netscape.com>
*/
* Javier Delgadillo <javi@netscape.com>
*/
/*
* Dialog services for PIP.
@ -40,6 +41,7 @@
#include "nsIStringBundle.h"
#include "nsIPref.h"
#include "nsIInterfaceRequestor.h"
#include "nsIX509Cert.h"
#include "nsNSSDialogs.h"
@ -132,7 +134,10 @@ nsNSSDialogs::~nsNSSDialogs()
{
}
NS_IMPL_ISUPPORTS2(nsNSSDialogs, nsINSSDialogs, nsISecurityWarningDialogs)
NS_IMPL_THREADSAFE_ISUPPORTS4(nsNSSDialogs, nsINSSDialogs,
nsITokenPasswordDialogs,
nsISecurityWarningDialogs,
nsIBadCertListener)
nsresult
nsNSSDialogs::Init()
@ -186,27 +191,80 @@ nsNSSDialogs::SetPassword(nsIInterfaceRequestor *ctx,
}
/* boolean unknownIssuer (in nsIChannelSecurityInfo socketInfo,
in nsIX509Cert cert); */
in nsIX509Cert cert, out addType); */
NS_IMETHODIMP
nsNSSDialogs::UnknownIssuer(nsIChannelSecurityInfo *socketInfo,
nsIX509Cert *cert, PRBool *_retval)
nsIX509Cert *cert, PRInt16 *outAddType,
PRBool *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv;
PRInt32 addType;
*_retval = PR_FALSE;
nsCOMPtr<nsIDialogParamBlock> block = do_CreateInstance(kDialogParamBlockCID);
if (!block)
return NS_ERROR_FAILURE;
nsXPIDLString commonName;
rv = cert->GetCommonName(getter_Copies(commonName));
if (NS_FAILED(rv))
return rv;
rv = block->SetString(1, commonName);
if (NS_FAILED(rv))
return rv;
rv = nsNSSDialogHelper::openDialog(nsnull,
"chrome://pippki/content/newserver.xul",
block);
if (NS_FAILED(rv))
return rv;
PRInt32 status;
rv = block->GetInt(1, &status);
if (NS_FAILED(rv))
return rv;
if (status == 0) {
*_retval = PR_FALSE;
} else {
// The user wants to continue, let's figure out
// what to do with this cert.
rv = block->GetInt(2, &addType);
switch (addType) {
case 0:
*outAddType = ADD_TRUSTED_PERMANENTLY;
*_retval = PR_TRUE;
break;
case 1:
*outAddType = ADD_TRUSTED_FOR_SESSION;
*_retval = PR_TRUE;
break;
default:
*outAddType = UNINIT_ADD_FLAG;
*_retval = PR_FALSE;
break;
}
}
return NS_OK;
}
/* boolean mismatchDomain (in nsIChannelSecurityInfo socketInfo,
in nsIX509Cert cert); */
NS_IMETHODIMP
nsNSSDialogs::MismatchDomain(nsIChannelSecurityInfo *socketInfo,
nsIX509Cert *cert, PRBool *_retval)
/* boolean mismatchDomain (in nsIChannelSecurityInfo socketInfo,
in nsIX509Cert cert); */
NS_IMETHODIMP
nsNSSDialogs::MismatchDomain(nsIChannelSecurityInfo *socketInfo,
nsIX509Cert *cert, PRBool *_retVal)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* boolean certExpired (in nsIChannelSecurityInfo socketInfo,
in nsIX509Cert cert); */
NS_IMETHODIMP
nsNSSDialogs::CertExpired(nsIChannelSecurityInfo *socketInfo,
/* boolean certExpired (in nsIChannelSecurityInfo socketInfo,
in nsIX509Cert cert); */
NS_IMETHODIMP
nsNSSDialogs::CertExpired(nsIChannelSecurityInfo *socketInfo,
nsIX509Cert *cert, PRBool *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;

View File

@ -40,8 +40,13 @@ interface nsIChannelSecurityInfo;
[scriptable, uuid(86960956-edb0-11d4-998b-00b0d02354a0)]
interface nsIBadCertListener : nsISupports {
const short UNINIT_ADD_FLAG = -1;
const short ADD_TRUSTED_FOR_SESSION =1;
const short ADD_TRUSTED_PERMANENTLY = 2;
boolean unknownIssuer(in nsIChannelSecurityInfo socketInfo,
in nsIX509Cert cert);
in nsIX509Cert cert,
out short certAddType);
boolean mismatchDomain(in nsIChannelSecurityInfo socketInfo,
in nsIX509Cert cert);

View File

@ -38,7 +38,9 @@
[scriptable, uuid(f0980f60-ee3d-11d4-998b-00b0d02354a0)]
interface nsIX509Cert : nsISupports {
/*
* We'l add methods as we need them.
* attributes for certs
*/
readonly attribute wstring commonName;
};

View File

@ -58,6 +58,7 @@ CPPSRCS = \
nsTLSSocketProvider.cpp \
nsSDR.cpp \
nsPK11TokenDB.cpp \
nsNSSCertificate.cpp \
$(NULL)
REQUIRES = nspr security

View File

@ -82,6 +82,7 @@ OBJS = \
.\$(OBJDIR)\nsTLSSocketProvider.obj \
.\$(OBJDIR)\nsSDR.obj \
.\$(OBJDIR)\nsPK11TokenDB.obj \
.\$(OBJDIR)\nsNSSCertificate.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@ -0,0 +1,78 @@
/*
* 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 the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: nsNSSCertificate.cpp,v 1.1 2001/02/16 22:17:44 javi%netscape.com Exp $
*/
#include "nsNSSCertificate.h"
#include "nsString.h"
/* nsNSSCertificate */
NS_IMPL_ISUPPORTS1(nsNSSCertificate, nsIX509Cert)
nsNSSCertificate::nsNSSCertificate(const char *certDER, int derLen)
{
NS_INIT_ISUPPORTS();
mCert = CERT_DecodeCertFromPackage(certDER, derLen);
}
nsNSSCertificate::nsNSSCertificate(CERTCertificate *cert)
{
NS_INIT_ISUPPORTS();
if (cert)
mCert = CERT_DupCertificate(cert);
}
nsNSSCertificate::~nsNSSCertificate()
{
if (mCert)
CERT_DestroyCertificate(mCert);
}
NS_IMETHODIMP
nsNSSCertificate::GetCommonName(PRUnichar **aCommonName)
{
NS_ENSURE_ARG(aCommonName);
*aCommonName = nsnull;
if (mCert) {
char *commonName = CERT_GetCommonName(&mCert->subject);
if (commonName) {
nsAutoString cn = NS_ConvertASCIItoUCS2(commonName);
*aCommonName = cn.ToNewUnicode();
}
}
return NS_OK;
}

View File

@ -0,0 +1,61 @@
/*
* 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 the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Ian McGreer <mcgreer@netscape.com>
* Javier Delgadillo <javi@netscape.com>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*
*/
#ifndef _NS_NSSCERTIFICATE_H_
#define _NS_NSSCERTIFICATE_H_
#include "nsIX509Cert.h"
#include "prtypes.h"
#include "cert.h"
#include "secitem.h"
/* Certificate */
class nsNSSCertificate : public nsIX509Cert
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIX509CERT
nsNSSCertificate(const char *certDER, int derLen);
nsNSSCertificate(CERTCertificate *cert);
/* from a request? */
virtual ~nsNSSCertificate();
private:
CERTCertificate *mCert;
};
#endif /* _NS_NSSCERTIFICATE_H_ */

View File

@ -43,12 +43,16 @@
#include "nsIWebProgressListener.h"
#include "nsIChannel.h"
#include "nsIBadCertListener.h"
#include "nsNSSCertificate.h"
#include "nsXPIDLString.h"
#include "nsNSSHelper.h"
#include "ssl.h"
#include "secerr.h"
#include "sslerr.h"
#include "certdb.h"
//#define DEBUG_SSL_VERBOSE
@ -426,6 +430,96 @@ nsCertErrorNeedsDialog(int error)
(error == SEC_ERROR_EXPIRED_CERTIFICATE));
}
static char* defaultServerNickname(CERTCertificate* cert)
{
char* nickname = nsnull;
int count;
PRBool conflict;
char* servername = nsnull;
servername = CERT_GetCommonName(&cert->subject);
if (servername == NULL) {
return nsnull;
}
count = 1;
while (1) {
if (count == 1) {
nickname = PR_smprintf("%s", servername);
}
else {
nickname = PR_smprintf("%s #%d", servername, count);
}
if (nickname == NULL) {
break;
}
conflict = SEC_CertNicknameConflict(nickname, &cert->derSubject,
cert->dbhandle);
if (conflict == PR_SUCCESS) {
break;
}
PR_Free(nickname);
count++;
}
PR_FREEIF(servername);
return nickname;
}
static nsresult
addCertToDB(CERTCertificate *peerCert, PRInt16 addType)
{
CERTCertTrust trust;
SECStatus rv;
nsresult retVal = NS_ERROR_FAILURE;
char *nickname;
switch (addType) {
case nsIBadCertListener::ADD_TRUSTED_PERMANENTLY:
nickname = defaultServerNickname(peerCert);
if (nsnull == nickname)
break;
memset((void*)&trust, 0, sizeof(trust));
rv = CERT_DecodeTrustString(&trust, "P");
if (rv != SECSuccess) {
return NS_ERROR_FAILURE;
}
rv = CERT_AddTempCertToPerm(peerCert, nickname, &trust);
if (rv == SECSuccess)
retVal = NS_OK;
PR_Free(nickname);
break;
case nsIBadCertListener::ADD_TRUSTED_FOR_SESSION:
// XXX We need an API from NSS to do this so
// that we don't have to access the fields
// in the cert directly.
peerCert->keepSession = PR_TRUE;
CERTCertTrust *trustPtr;
if (!peerCert->trust) {
trustPtr = (CERTCertTrust*)PORT_ArenaZAlloc(peerCert->arena,
sizeof(CERTCertTrust));
if (!trustPtr)
break;
peerCert->trust = trustPtr;
} else {
trustPtr = peerCert->trust;
}
rv = CERT_DecodeTrustString(trustPtr, "P");
if (rv != SECSuccess)
break;
retVal = NS_OK;
break;
default:
PR_ASSERT(!"Invalid value for addType passed to addCertDB");
break;
}
return retVal;
}
static PRBool
nsContinueDespiteCertError(nsNSSSocketInfo *infoObject,
PRFileDesc *sslSocket,
@ -433,6 +527,9 @@ nsContinueDespiteCertError(nsNSSSocketInfo *infoObject,
{
PRBool retVal = PR_FALSE;
nsIBadCertListener *badCertHandler;
PRInt16 addType = nsIBadCertListener::UNINIT_ADD_FLAG;
nsNSSCertificate *nssCert;
CERTCertificate *peerCert;
nsresult rv;
rv = getNSSDialogs((void**)&badCertHandler,
@ -441,24 +538,36 @@ nsContinueDespiteCertError(nsNSSSocketInfo *infoObject,
return PR_FALSE;
nsIChannelSecurityInfo *csi = NS_STATIC_CAST(nsIChannelSecurityInfo*,
infoObject);
peerCert = SSL_PeerCertificate(sslSocket);
nssCert = new nsNSSCertificate(peerCert);
CERT_DestroyCertificate(peerCert); //nssCert gets its own reference
//to the certificate, so let's
//not leak one here.
if (!nssCert)
return PR_FALSE;
NS_ADDREF(nssCert);
nsIX509Cert *callBackCert = NS_STATIC_CAST(nsIX509Cert*, nssCert);
switch (error) {
case SEC_ERROR_UNKNOWN_ISSUER:
case SEC_ERROR_CA_CERT_INVALID:
case SEC_ERROR_UNTRUSTED_ISSUER:
rv = badCertHandler->UnknownIssuer(csi, nsnull, &retVal);
rv = badCertHandler->UnknownIssuer(csi, callBackCert, &addType, &retVal);
break;
case SSL_ERROR_BAD_CERT_DOMAIN:
rv = badCertHandler->MismatchDomain(csi, nsnull, &retVal);
rv = badCertHandler->MismatchDomain(csi, callBackCert, &retVal);
break;
case SEC_ERROR_EXPIRED_CERTIFICATE:
rv = badCertHandler->CertExpired(csi, nsnull, & retVal);
rv = badCertHandler->CertExpired(csi, callBackCert, & retVal);
break;
default:
rv = NS_ERROR_FAILURE;
break;
}
if (retVal && addType != nsIBadCertListener::UNINIT_ADD_FLAG) {
addCertToDB(peerCert, addType);
}
NS_RELEASE(badCertHandler);
NS_RELEASE(nssCert);
return NS_FAILED(rv) ? PR_FALSE : retVal;
}