Fix for bug 29152 (Cannot do formsigning - crypto.signText). r=kaie, sr=jst.

This commit is contained in:
peterv%propagandism.org 2004-03-06 15:52:44 +00:00
parent 460fe2328f
commit 545ad9d0ad
15 changed files with 902 additions and 43 deletions

View File

@ -50,7 +50,8 @@ interface nsIDOMCrypto : nsISupports
in boolean doForcedBackup);
DOMString popChallengeResponse(in DOMString challenge);
DOMString random(in long numBytes);
DOMString signText(/* ... */);
DOMString signText(in DOMString stringToSign,
in DOMString caOption /* ... */);
void alert(in DOMString message);
void logout();
void disableRightClick();

View File

@ -0,0 +1,101 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 Communicator.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
var dialogParams;
var itemCount = 0;
function onLoad()
{
dialogParams = window.arguments[0].QueryInterface(nsIDialogParamBlock);
var hostname = dialogParams.GetString(0);
var bundle = document.getElementById("pippki_bundle");
var intro = bundle.getFormattedString("formSigningIntro", [hostname]);
setText("sign.intro", intro);
document.getElementById("sign.text").value = dialogParams.GetString(1);
var selectElement = document.getElementById("nicknames");
itemCount = dialogParams.GetInt(0);
for (var index = 0; index < itemCount; ++index) {
var menuItemNode = document.createElement("menuitem");
var nick = dialogParams.GetString(2 + 2 * index);
menuItemNode.setAttribute("value", index);
menuItemNode.setAttribute("label", nick); // this is displayed
selectElement.firstChild.appendChild(menuItemNode);
if (index == 0) {
selectElement.selectedItem = menuItemNode;
}
}
setDetails();
document.getElementById("pw").focus();
window.sizeToContent();
doSetOKCancel(doOK, doCancel, null, null);
}
function setDetails()
{
var index = parseInt(document.getElementById("nicknames").value);
if (index == "NaN")
return;
var details = dialogParams.GetString(2 + (2 * index + 1));
document.getElementById("certdetails").value = details;
}
function onCertSelected()
{
setDetails();
}
function doOK()
{
dialogParams.SetInt(0, 1);
var index = parseInt(document.getElementById("nicknames").value);
dialogParams.SetInt(1, index);
var password = document.getElementById("pw").value;
dialogParams.SetString(0, password);
window.close();
}
function doCancel()
{
dialogParams.SetInt(0, 0);
window.close();
}

View File

@ -0,0 +1,88 @@
<?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 Communicator.
-
- The Initial Developer of the Original Code is
- Netscape Communications Corporation.
- Portions created by the Initial Developer are Copyright (C) 2002
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
-
- 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 LGPL or the GPL. 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 window [
<!ENTITY % pippkiDTD SYSTEM "chrome://pippki/locale/pippki.dtd" >
%pippkiDTD;
]>
<?xul-overlay href="chrome://global/content/dialogOverlay.xul"?>
<window id="formsigning" title="&formSigning.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
class="dialog"
onload="onLoad();">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<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/formsigning.js"/>
<script type="application/x-javascript" src="chrome://help/content/contextHelp.js" />
<vbox>
<description id="sign.intro" style="max-width: 50em;"/>
<textbox readonly="true" id="sign.text" multiline="true"
style="height: 10em;" wrap="off"/>
<separator class="thin"/>
<groupbox>
<caption label="&formSigning.cert;"/>
<broadcaster id="certSelected" oncommand="onCertSelected();"/>
<menulist id="nicknames" observes="certSelected">
<!-- The items in this menulist must never be sorted,
but remain in the order filled by the application
-->
<menupopup/>
</menulist>
<textbox readonly="true" id="certdetails" multiline="true"
style="height: 10em;" wrap="off"/>
<separator/>
</groupbox>
<separator class="thin"/>
<vbox>
<description style="max-width: 30em;">&formSigning.confirmPassword;</description>
<hbox>
<textbox id="pw" type="password" size="20"/>
</hbox>
<separator/>
</vbox>
<keyset id="dialogKeys"/>
<hbox id="okCancelHelpButtonsRight"/>
</vbox>
</window>

View File

@ -44,9 +44,9 @@ pippki.jar:
content/pippki/domainMismatch.js (content/domainMismatch.js)
content/pippki/serverCertExpired.xul (content/serverCertExpired.xul)
content/pippki/serverCertExpired.js (content/serverCertExpired.js)
content/pippki/clientauthask.xul (content/clientauthask.xul)
content/pippki/clientauthask.xul (content/clientauthask.xul)
content/pippki/clientauthask.js (content/clientauthask.js)
content/pippki/certpicker.xul (content/certpicker.xul)
content/pippki/certpicker.xul (content/certpicker.xul)
content/pippki/certpicker.js (content/certpicker.js)
content/pippki/certViewer.xul (content/certViewer.xul)
content/pippki/certDump.xul (content/certDump.xul)
@ -67,10 +67,12 @@ pippki.jar:
content/pippki/serverCrlNextupdate.xul (content/serverCrlNextupdate.xul)
content/pippki/createCertInfo.xul (content/createCertInfo.xul)
content/pippki/createCertInfo.js (content/createCertInfo.js)
content/pippki/crlImportDialog.xul (content/crlImportDialog.xul)
content/pippki/crlImportDialog.js (content/crlImportDialog.js)
content/pippki/pref-crlupdate.xul (content/pref-crlupdate.xul)
content/pippki/crlImportDialog.xul (content/crlImportDialog.xul)
content/pippki/crlImportDialog.js (content/crlImportDialog.js)
content/pippki/pref-crlupdate.xul (content/pref-crlupdate.xul)
content/pippki/pref-crlupdate.js (content/pref-crlupdate.js)
content/pippki/formsigning.xul (content/formsigning.xul)
content/pippki/formsigning.js (content/formsigning.js)
en-US.jar:
* locale/en-US/pippki/contents.rdf (locale/en-US/contents.rdf)

View File

@ -115,3 +115,8 @@
<!-- Access Keys -->
<!ENTITY createCertInfo.okButtonAccessKey "o">
<!-- Form Signing confirmation prompt -->
<!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:">

View File

@ -175,3 +175,6 @@ importEmailCertPrompt=Select File containing somebody's Email certificate to imp
importCACertsPrompt=Select File containing CA certificate(s) to import
importWebSiteCertPrompt=Select File containing Web Site certificate to import
file_browse_Certificate_spec=Certificate Files
# Form Signing confirmation prompt
formSigningIntro=The site '%S' has requested that you sign the following text message:

View File

@ -57,6 +57,7 @@ CPPSRCS = \
nsPKIParamBlock.cpp \
nsASN1Tree.cpp \
nsNSSDialogHelper.cpp \
nsFormSigningDialog.cpp \
$(NULL)
REQUIRES = nspr \

View File

@ -0,0 +1,123 @@
/* ***** 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 Communicator.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 "nsFormSigningDialog.h"
#include "nsNSSDialogHelper.h"
#include "nsCOMPtr.h"
#include "nsIDialogParamBlock.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsLiteralString.h"
#include "nsXPIDLString.h"
nsFormSigningDialog::nsFormSigningDialog()
{
}
nsFormSigningDialog::~nsFormSigningDialog()
{
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsFormSigningDialog, nsIFormSigningDialog);
NS_IMETHODIMP
nsFormSigningDialog::ConfirmSignText(nsIInterfaceRequestor *aContext,
const nsAString &aHost,
const nsAString &aSignText,
const PRUnichar **aCertNickList,
const PRUnichar **aCertDetailsList,
PRUint32 aCount, PRInt32 *aSelectedIndex,
nsAString &aPassword, PRBool *aCanceled)
{
*aCanceled = PR_TRUE;
// Get the parent window for the dialog
nsCOMPtr<nsIDOMWindowInternal> parent = do_GetInterface(aContext);
nsresult rv;
nsCOMPtr<nsIDialogParamBlock> block =
do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
block->SetNumberStrings(3 + aCount * 2);
rv = block->SetString(0, PromiseFlatString(aHost).get());
NS_ENSURE_SUCCESS(rv, rv);
rv = block->SetString(1, PromiseFlatString(aSignText).get());
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 i;
for (i = 0; i < aCount; ++i) {
rv = block->SetString(2 + 2 * i, aCertNickList[i]);
NS_ENSURE_SUCCESS(rv, rv);
rv = block->SetString(2 + (2 * i + 1), aCertDetailsList[i]);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = block->SetInt(0, aCount);
NS_ENSURE_SUCCESS(rv, rv);
rv = nsNSSDialogHelper::openDialog(parent,
"chrome://pippki/content/formsigning.xul",
block);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 status;
rv = block->GetInt(0, &status);
NS_ENSURE_SUCCESS(rv, rv);
if (status == 0) {
*aCanceled = PR_TRUE;
}
else {
*aCanceled = PR_FALSE;
rv = block->GetInt(1, aSelectedIndex);
NS_ENSURE_SUCCESS(rv, rv);
nsXPIDLString pw;
rv = block->GetString(0, getter_Copies(pw));
NS_ENSURE_SUCCESS(rv, rv);
aPassword = pw;
}
return NS_OK;
}

View File

@ -0,0 +1,56 @@
/* ***** 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 Communicator.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
#ifndef __NS_NSFORMSIGNINGDIALOG_H__
#define __NS_NSFORMSIGNINGDIALOG_H__
#include "nsIFormSigningDialog.h"
#define NS_FORMSIGNINGDIALOG_CID \
{ 0xa4bd2161, 0x7892, 0x4389, \
{ 0x8d, 0x5a, 0x31, 0x11, 0xa6, 0xd1, 0x7e, 0xc7 }}
class nsFormSigningDialog : public nsIFormSigningDialog
{
public:
nsFormSigningDialog();
~nsFormSigningDialog();
NS_DECL_ISUPPORTS
NS_DECL_NSIFORMSIGNINGDIALOG
};
#endif

View File

@ -27,10 +27,12 @@
#include "nsNSSDialogs.h"
#include "nsPKIParamBlock.h"
#include "nsASN1Tree.h"
#include "nsFormSigningDialog.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"
@ -103,6 +105,12 @@ static const nsModuleComponentInfo components[] =
NS_PKIPARAMBLOCK_CID,
NS_PKIPARAMBLOCK_CONTRACTID,
nsPKIParamBlockConstructor
},
{ "Form Signing Dialog",
NS_FORMSIGNINGDIALOG_CID,
NS_FORMSIGNINGDIALOG_CONTRACTID,
nsFormSigningDialogConstructor
}
};

View File

@ -45,6 +45,7 @@ MODULE = pipnss
GRE_MODULE = 1
XPIDLSRCS = \
nsIFormSigningDialog.idl \
nsIBadCertListener.idl \
nsICertSelect.idl \
nsIX509Cert.idl \

View File

@ -0,0 +1,71 @@
/* ***** 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 Communicator.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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;
/**
* nsIFormSigningDialog
* Provides UI for form signing.
*/
[scriptable, uuid(4fe04d6d-4b66-4023-a0bc-b43ce68b3e15)]
interface nsIFormSigningDialog : nsISupports
{
/**
* confirmSignText
* UI shown when a web site calls crypto.signText,
* asking the user to confirm the confirm the signing request.
*
* returns true if the user confirmed, false on cancel
*/
boolean confirmSignText(in nsIInterfaceRequestor ctxt,
in AString host,
in AString signText,
[array, size_is(count)] in wstring certNickList,
[array, size_is(count)] in wstring certDetailsList,
in PRUint32 count,
out PRInt32 selectedIndex,
out AString password);
};
/**
* NS_FORMSIGNINGDIALOG_CONTRACTID - contract id to obtain an instance
* that implements nsIFormSigningDialog.
*/
%{C++
#define NS_FORMSIGNINGDIALOG_CONTRACTID "@mozilla.org/nsFormSigningDialog;1"
%}

View File

@ -244,6 +244,7 @@ CertInfoValid=Valid
CertInfoFrom=from
CertInfoTo=to
CertInfoPurposes=Purposes
CertInfoStoredIn=Stored in:
P12DefaultNickname=Imported Certificate
CrlImportSuccess=The browser successfully imported the certificate revocation list (CRL).
CrlImportFailure1=The browser cannot import the Certificate Revocation List (CRL).

View File

@ -36,6 +36,8 @@
#include "nsDOMCID.h"
#include "nsIDOMWindowInternal.h"
#include "nsIDOMClassInfo.h"
#include "nsIDOMDocument.h"
#include "nsIDocument.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
@ -51,6 +53,8 @@
#include "nsXPIDLString.h"
#include "nsIGenKeypairInfoDlg.h"
#include "nsIDOMCryptoDialogs.h"
#include "nsIFormSigningDialog.h"
#include "nsIProxyObjectManager.h"
#include "jsapi.h"
#include "jsdbgapi.h"
#include <ctype.h>
@ -59,6 +63,8 @@
#include "keyhi.h"
#include "cryptohi.h"
#include "seccomon.h"
#include "secerr.h"
#include "sechash.h"
extern "C" {
#include "crmf.h"
#include "pk11pqg.h"
@ -68,10 +74,12 @@ extern "C" {
#include "base64.h"
#include "certdb.h"
#include "secmod.h"
#include "nsISaveAsCharset.h"
#include "nsNSSCleaner.h"
NSSCleanupAutoPtrClass(SECKEYPrivateKey, SECKEY_DestroyPrivateKey)
NSSCleanupAutoPtrClass(PK11SlotInfo, PK11_FreeSlot)
NSSCleanupAutoPtrClass(CERTCertNicknames, CERT_FreeNicknames)
#include "nsNSSShutDown.h"
@ -81,10 +89,9 @@ NSSCleanupAutoPtrClass(PK11SlotInfo, PK11_FreeSlot)
*/
#define JS_ERROR "error:"
#define JS_ERROR_INVAL_PARAM JS_ERROR"invalidParameter:"
#define JS_ERROR_USER_CANCEL JS_ERROR"userCancel"
#define JS_ERROR_NOCERT JS_ERROR"noMatchingCert"
#define JS_ERROR_INTERNAL JS_ERROR"internalError"
#define JS_ERROR_ARGC_ERR JS_ERROR"incorrect number of parameters"
#undef REPORT_INCORRECT_NUM_ARGS
@ -2067,13 +2074,406 @@ nsCrypto::Random(PRInt32 aNumBytes, nsAString& aReturn)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCrypto::SignText(nsAString& aReturn)
static void
GetDocumentFromContext(JSContext *cx, nsIDocument **aDocument)
{
return NS_ERROR_NOT_IMPLEMENTED;
// Get the script context.
nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
if (!scriptContext) {
return;
}
nsCOMPtr<nsIDOMWindow> domWindow =
do_QueryInterface(scriptContext->GetGlobalObject());
if (!domWindow) {
return;
}
nsCOMPtr<nsIDOMDocument> domDocument;
domWindow->GetDocument(getter_AddRefs(domDocument));
if (!domDocument) {
return;
}
CallQueryInterface(domDocument, aDocument);
return;
}
void signTextOutputCallback(void *arg, const char *buf, unsigned long len)
{
((nsCString*)arg)->Append(buf, len);
}
#define NICKNAME_EXPIRED_STRING " (expired)"
#define NICKNAME_NOT_YET_VALID_STRING " (not yet valid)"
NS_IMETHODIMP
nsCrypto::SignText(const nsAString& aStringToSign, const nsAString& aCaOption,
nsAString& aResult)
{
// XXX This code should return error codes, but we're keeping this
// backwards compatible with NS4.x and so we can't throw exceptions.
NS_NAMED_LITERAL_STRING(internalError, JS_ERROR_INTERNAL);
aResult.Truncate();
nsCOMPtr<nsIXPCNativeCallContext> ncc;
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
if (xpc) {
xpc->GetCurrentNativeCallContext(getter_AddRefs(ncc));
}
if (!ncc) {
aResult.Append(internalError);
return NS_OK;
}
PRUint32 argc;
ncc->GetArgc(&argc);
JSContext *cx;
ncc->GetJSContext(&cx);
if (!cx) {
aResult.Append(internalError);
return NS_OK;
}
if (!aCaOption.Equals(NS_LITERAL_STRING("auto")) &&
!aCaOption.Equals(NS_LITERAL_STRING("ask"))) {
JS_ReportError(cx, "%s%s\n", JS_ERROR, "caOption argument must be ask or auto");
aResult.Append(internalError);
return NS_OK;
}
// It was decided to always behave as if "ask" were specified.
// XXX Should we warn in the JS Console for auto?
nsCOMPtr<nsIInterfaceRequestor> uiContext = new PipUIContext;
if (!uiContext) {
aResult.Append(internalError);
return NS_OK;
}
PRBool bestOnly = PR_TRUE;
PRBool validOnly = PR_TRUE;
CERTCertList* certList =
CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(), certUsageEmailSigner,
bestOnly, validOnly, uiContext);
PRUint32 numCAs = argc - 2;
if (numCAs > 0) {
nsAutoArrayPtr<char*> caNames(new char*[numCAs]);
if (!caNames) {
aResult.Append(internalError);
return NS_OK;
}
jsval *argv = nsnull;
ncc->GetArgvPtr(&argv);
PRUint32 i;
for (i = 2; i < argc; ++i) {
JSString *caName = JS_ValueToString(cx, argv[i]);
if (!caName) {
aResult.Append(internalError);
return NS_OK;
}
caNames[i] = JS_GetStringBytes(caName);
}
if (certList &&
CERT_FilterCertListByCANames(certList, numCAs, caNames,
certUsageEmailSigner) != SECSuccess) {
aResult.Append(internalError);
return NS_OK;
}
}
if (!certList || CERT_LIST_EMPTY(certList)) {
aResult.Append(NS_LITERAL_STRING(JS_ERROR_NOCERT));
return NS_OK;
}
nsCOMPtr<nsIFormSigningDialog> fsd =
do_CreateInstance(NS_FORMSIGNINGDIALOG_CONTRACTID);
if (!fsd) {
aResult.Append(internalError);
return NS_OK;
}
nsCOMPtr<nsIProxyObjectManager> proxyman =
do_GetService(NS_XPCOMPROXY_CONTRACTID);
if (!proxyman) {
aResult.Append(internalError);
return NS_OK;
}
nsCOMPtr<nsIFormSigningDialog> proxied_fsd;
nsresult rv = proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ,
NS_GET_IID(nsIFormSigningDialog),
fsd, PROXY_SYNC,
getter_AddRefs(proxied_fsd));
if (NS_FAILED(rv)) {
aResult.Append(internalError);
return NS_OK;
}
nsCOMPtr<nsIDocument> document;
GetDocumentFromContext(cx, getter_AddRefs(document));
if (!document) {
aResult.Append(internalError);
return NS_OK;
}
// Get the hostname from the URL of the document.
nsIURI* uri = document->GetDocumentURI();
if (!uri) {
aResult.Append(internalError);
return NS_OK;
}
nsCString host;
rv = uri->GetHost(host);
if (NS_FAILED(rv)) {
aResult.Append(internalError);
return NS_OK;
}
PRInt32 numberOfCerts = 0;
CERTCertListNode* node;
for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
node = CERT_LIST_NEXT(node)) {
++numberOfCerts;
}
CERTCertNicknames* nicknames =
CERT_NicknameStringsFromCertList(certList, NICKNAME_EXPIRED_STRING,
NICKNAME_NOT_YET_VALID_STRING);
if (!nicknames) {
aResult.Append(internalError);
return NS_OK;
}
CERTCertNicknamesCleaner cnc(nicknames);
NS_ASSERTION(nicknames->numnicknames == numberOfCerts,
"nicknames->numnicknames != numberOfCerts");
nsAutoArrayPtr<PRUnichar*> certNicknameList(new PRUnichar*[nicknames->numnicknames * 2]);
if (!certNicknameList) {
aResult.Append(internalError);
return NS_OK;
}
PRUnichar** certDetailsList = certNicknameList.get() + nicknames->numnicknames;
PRInt32 certsToUse;
for (node = CERT_LIST_HEAD(certList), certsToUse = 0;
!CERT_LIST_END(node, certList) && certsToUse < nicknames->numnicknames;
node = CERT_LIST_NEXT(node)) {
nsRefPtr<nsNSSCertificate> tempCert = new nsNSSCertificate(node->cert);
if (tempCert) {
nsAutoString nickWithSerial, details;
rv = tempCert->FormatUIStrings(NS_ConvertUTF8toUTF16(nicknames->nicknames[certsToUse]),
nickWithSerial, details);
if (NS_SUCCEEDED(rv)) {
certNicknameList[certsToUse] = ToNewUnicode(nickWithSerial);
if (certNicknameList[certsToUse]) {
certDetailsList[certsToUse] = ToNewUnicode(details);
if (!certDetailsList[certsToUse]) {
nsMemory::Free(certNicknameList[certsToUse]);
continue;
}
++certsToUse;
}
}
}
}
if (certsToUse == 0) {
aResult.Append(internalError);
return NS_OK;
}
NS_ConvertUTF8toUTF16 utf16Host(host);
CERTCertificate *signingCert = nsnull;
PRBool tryAgain, canceled;
nsAutoString password;
do {
// Throw up the form signing confirmation dialog and get back the index
// of the selected cert.
PRInt32 selectedIndex = -1;
rv = proxied_fsd->ConfirmSignText(uiContext, utf16Host, aStringToSign,
NS_CONST_CAST(const PRUnichar**, certNicknameList.get()),
NS_CONST_CAST(const PRUnichar**, certDetailsList),
certsToUse, &selectedIndex, password,
&canceled);
if (NS_FAILED(rv) || canceled) {
break; // out of tryAgain loop
}
PRInt32 j = 0;
for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
node = CERT_LIST_NEXT(node)) {
if (j == selectedIndex) {
signingCert = CERT_DupCertificate(node->cert);
break; // out of cert list iteration loop
}
++j;
}
if (!signingCert) {
rv = NS_ERROR_FAILURE;
break; // out of tryAgain loop
}
NS_ConvertUTF16toUTF8 pwUtf8(password);
tryAgain =
PK11_CheckUserPassword(signingCert->slot,
NS_CONST_CAST(char *, pwUtf8.get())) != SECSuccess;
// XXX we should show an error dialog before retrying
} while (tryAgain);
PRInt32 k;
for (k = 0; k < certsToUse; ++k) {
nsMemory::Free(certNicknameList[k]);
nsMemory::Free(certDetailsList[k]);
}
if (NS_FAILED(rv)) { // something went wrong inside the tryAgain loop
aResult.Append(internalError);
return NS_OK;
}
if (canceled) {
aResult.Append(NS_LITERAL_STRING(JS_ERROR_USER_CANCEL));
return NS_OK;
}
SECKEYPrivateKey* privKey = PK11_FindKeyByAnyCert(signingCert, uiContext);
if (!privKey) {
aResult.Append(internalError);
return NS_OK;
}
nsCAutoString charset(document->GetDocumentCharacterSet());
// XXX Doing what nsFormSubmission::GetEncoder does (see
// http://bugzilla.mozilla.org/show_bug.cgi?id=81203).
if (charset.Equals(NS_LITERAL_CSTRING("ISO-8859-1"))) {
charset.Assign(NS_LITERAL_CSTRING("windows-1252"));
}
nsCOMPtr<nsISaveAsCharset> encoder =
do_CreateInstance(NS_SAVEASCHARSET_CONTRACTID);
if (encoder) {
rv = encoder->Init(charset.get(),
(nsISaveAsCharset::attr_EntityAfterCharsetConv +
nsISaveAsCharset::attr_FallbackDecimalNCR),
0);
}
nsXPIDLCString buffer;
if (aStringToSign.Length() > 0) {
if (encoder && NS_SUCCEEDED(rv)) {
rv = encoder->Convert(PromiseFlatString(aStringToSign).get(),
getter_Copies(buffer));
if (NS_FAILED(rv)) {
aResult.Append(internalError);
return NS_OK;
}
}
else {
AppendUTF16toUTF8(aStringToSign, buffer);
}
}
HASHContext *hc = HASH_Create(HASH_AlgSHA1);
if (!hc) {
aResult.Append(internalError);
return NS_OK;
}
unsigned char hash[SHA1_LENGTH];
SECItem digest;
digest.data = hash;
HASH_Begin(hc);
HASH_Update(hc, NS_REINTERPRET_CAST(const unsigned char*, buffer.get()),
buffer.Length());
HASH_End(hc, digest.data, &digest.len, SHA1_LENGTH);
HASH_Destroy(hc);
nsCString p7;
SECStatus srv = SECFailure;
SEC_PKCS7ContentInfo *ci = SEC_PKCS7CreateSignedData(signingCert,
certUsageEmailSigner,
nsnull, SEC_OID_SHA1,
&digest, nsnull, uiContext);
if (ci) {
srv = SEC_PKCS7IncludeCertChain(ci, nsnull);
if (srv == SECSuccess) {
srv = SEC_PKCS7AddSigningTime(ci);
if (srv == SECSuccess) {
srv = SEC_PKCS7Encode(ci, signTextOutputCallback, &p7, nsnull, nsnull,
uiContext);
}
}
SEC_PKCS7DestroyContentInfo(ci);
}
if (srv != SECSuccess) {
aResult.Append(internalError);
return NS_OK;
}
SECItem binary_item;
binary_item.data = NS_REINTERPRET_CAST(unsigned char*,
NS_CONST_CAST(char*, p7.get()));
binary_item.len = p7.Length();
char *result = NSSBase64_EncodeItem(nsnull, nsnull, 0, &binary_item);
if (result) {
AppendASCIItoUTF16(result, aResult);
}
else {
aResult.Append(internalError);
}
PORT_Free(result);
return NS_OK;
}
NS_IMETHODIMP
nsCrypto::Alert(const nsAString& aMessage)

View File

@ -241,17 +241,11 @@ nsNSSCertificate::FormatUIStrings(const nsAutoString &nickname, nsAutoString &ni
if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoIssuedFor", info))) {
details.Append(info);
details.Append(NS_LITERAL_STRING("\n"));
}
if (NS_SUCCEEDED(x509Proxy->GetSubjectName(temp1)) && !temp1.IsEmpty()) {
details.Append(NS_LITERAL_STRING(" "));
if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertDumpSubject", info))) {
details.Append(info);
details.Append(NS_LITERAL_STRING(": "));
details.Append(PRUnichar(' '));
if (NS_SUCCEEDED(x509Proxy->GetSubjectName(temp1)) && !temp1.IsEmpty()) {
details.Append(temp1);
}
details.Append(temp1);
details.Append(NS_LITERAL_STRING("\n"));
details.Append(PRUnichar('\n'));
}
if (NS_SUCCEEDED(x509Proxy->GetSerialNumber(temp1)) && !temp1.IsEmpty()) {
@ -264,9 +258,9 @@ nsNSSCertificate::FormatUIStrings(const nsAutoString &nickname, nsAutoString &ni
nickWithSerial.Append(NS_LITERAL_STRING(" ["));
nickWithSerial.Append(temp1);
nickWithSerial.Append(NS_LITERAL_STRING("]"));
nickWithSerial.Append(PRUnichar(']'));
details.Append(NS_LITERAL_STRING("\n"));
details.Append(PRUnichar('\n'));
}
@ -289,24 +283,24 @@ nsNSSCertificate::FormatUIStrings(const nsAutoString &nickname, nsAutoString &ni
}
if (NS_SUCCEEDED(validity->GetNotBeforeLocalTime(temp1)) && !temp1.IsEmpty()) {
details.Append(NS_LITERAL_STRING(" "));
details.Append(PRUnichar(' '));
if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoFrom", info))) {
details.Append(info);
details.Append(PRUnichar(' '));
}
details.Append(NS_LITERAL_STRING(" "));
details.Append(temp1);
}
if (NS_SUCCEEDED(validity->GetNotAfterLocalTime(temp1)) && !temp1.IsEmpty()) {
details.Append(NS_LITERAL_STRING(" "));
details.Append(PRUnichar(' '));
if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoTo", info))) {
details.Append(info);
details.Append(PRUnichar(' '));
}
details.Append(NS_LITERAL_STRING(" "));
details.Append(temp1);
}
details.Append(NS_LITERAL_STRING("\n"));
details.Append(PRUnichar('\n'));
}
}
@ -315,37 +309,41 @@ nsNSSCertificate::FormatUIStrings(const nsAutoString &nickname, nsAutoString &ni
details.Append(NS_LITERAL_STRING(" "));
if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoPurposes", info))) {
details.Append(info);
details.Append(NS_LITERAL_STRING(": "));
}
details.Append(NS_LITERAL_STRING(": "));
details.Append(temp1);
details.Append(NS_LITERAL_STRING("\n"));
details.Append(PRUnichar('\n'));
}
if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoIssuedBy", info))) {
details.Append(info);
details.Append(NS_LITERAL_STRING("\n"));
details.Append(PRUnichar(' '));
if (NS_SUCCEEDED(x509Proxy->GetIssuerName(temp1)) && !temp1.IsEmpty()) {
details.Append(temp1);
}
details.Append(PRUnichar('\n'));
}
if (NS_SUCCEEDED(x509Proxy->GetIssuerName(temp1)) && !temp1.IsEmpty()) {
details.Append(NS_LITERAL_STRING(" "));
if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertDumpSubject", info))) {
details.Append(info);
details.Append(NS_LITERAL_STRING(": "));
if (NS_SUCCEEDED(nssComponent->GetPIPNSSBundleString("CertInfoStoredIn", info))) {
details.Append(info);
details.Append(PRUnichar(' '));
if (NS_SUCCEEDED(x509Proxy->GetTokenName(temp1)) && !temp1.IsEmpty()) {
details.Append(temp1);
}
details.Append(temp1);
details.Append(NS_LITERAL_STRING("\n"));
}
/*
the above produces output the following output:
Issued to:
Subject: $subjectName
Issued to: $subjectName
Serial number: $serialNumber
Valid from: $starting_date to $expriation_date
Valid from: $starting_date to $expiration_date
Purposes: $purposes
Issued by:
Subject: $issuerName
Issued by: $issuerName
Stored in: $token
*/
}