Adding new smime extension files.
NOT PART OF THE BUILD
This commit is contained in:
mscott%netscape.com 2001-11-01 22:35:58 +00:00
Родитель 45e7f547c9
Коммит bac2087fab
19 изменённых файлов: 1883 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,133 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributors:
* ddrinan@netscape.com
* Scott MacGregor <mscott@netscape.com>
*/
var gIdentity;
var gPref = null;
var gEncryptionCertName = null;
var gEncryptIfPossible = null;
var gEncryptAlways = null;
var gSignCertName = null;
var gSignMessages = null;
function onInit()
{
// initialize all of our elements based on the current identity values....
gEncryptionCertName = document.getElementById("identity.encryption_cert_name");
gEncryptIfPossible = document.getElementById("identity.encrypt_mail_if_possible");
gEncryptAlways = document.getElementById("identity.encrypt_mail_always");
gSignCertName = document.getElementById("identity.signing_cert_name");
gSignMessages = document.getElementById("identity.sign_mail");
gEncryptionCertName.value = gIdentity.getUnicharAttribute("encryption_cert_name");
gEncryptIfPossible.checked = gIdentity.getBoolAttribute("encrypt_mail_if_possible");
gEncryptAlways.checked = gIdentity.getBoolAttribute("encrypt_mail_always");
if (!gEncryptionCertName.value)
{
gEncryptAlways.setAttribute("disabled", true);
}
// we currently don't support encrypt if possible so keep it disabled for now...
gEncryptIfPossible.setAttribute("disabled", true);
gSignCertName.value = gIdentity.getUnicharAttribute("signing_cert_name");
gSignMessages.checked = gIdentity.getBoolAttribute("sign_mail");
if (!gSignCertName.value)
{
gSignMessages.setAttribute("disabled", true);
}
}
function onPreInit(account, accountValues)
{
gIdentity = account.defaultIdentity;
}
function onSave()
{
}
function onLockPreference()
{
dump("XXX on lock\n");
}
// Does the work of disabling an element given the array which contains xul id/prefstring pairs.
// Also saves the id/locked state in an array so that other areas of the code can avoid
// stomping on the disabled state indiscriminately.
function disableIfLocked( prefstrArray )
{
if (!gLockedPref)
gLockedPref = new Array;
for (i=0; i<prefstrArray.length; i++) {
var id = prefstrArray[i].id;
var element = document.getElementById(id);
if (gPref.prefIsLocked(prefstrArray[i].prefstring)) {
element.disabled = true;
gLockedPref[id] = true;
} else {
element.removeAttribute("disabled");
gLockedPref[id] = false;
}
}
}
function smimeSelectCert(smime_cert)
{
var picker = Components.classes["@mozilla.org/user_cert_picker;1"]
.getService(Components.interfaces.nsIUserCertPicker);
var canceled = new Object;
var x509cert = 0;
var certUsage;
if (smime_cert == "identity.encryption_cert_name") {
certUsage = 5;
} else if (smime_cert == "identity.signing_cert_name") {
certUsage = 4;
}
try {
var smimeBundle = document.getElementById("bundle_smime");
x509cert = picker.pickByUsage(window,
smimeBundle.getString("prefPanel-smime"),
smimeBundle.getString("smimeCertPrompt"),
certUsage, // this is from enum SECCertUsage
false, false, canceled);
} catch(e) {
// XXX display error message in the future
}
if (!canceled.value && x509cert) {
var certInfo = document.getElementById(smime_cert);
if (certInfo) {
certInfo.setAttribute("disabled", "false");
certInfo.value = x509cert.nickname;
if (smime_cert == "identity.encryption_cert_name") {
gEncryptAlways.removeAttribute("disabled");
} else {
gSignMessages.removeAttribute("disabled");
}
}
}
}

Просмотреть файл

@ -0,0 +1,97 @@
<?xml version="1.0"?>
<!--
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 Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1998-2001 Netscape Communications Corporation. All
Rights Reserved.
Contributors:
ddrinan@netscape.com
Scott MacGregor <mscott@netscape.com>
-->
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
<?xul-overlay href="chrome://global/content/dialogOverlay.xul"?>
<!DOCTYPE window SYSTEM "chrome://messenger/locale/am-smime.dtd">
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
class="color-dialog"
onload="parent.onPanelLoaded('am-smime.xul');"
orient="vertical">
<stringbundle id="bundle_smime" src="chrome://messenger/locale/am-smime.properties"/>
<script type="application/x-javascript" src="chrome://messenger/content/AccountManager.js"/>
<script type="application/x-javascript" src="chrome://messenger/content/am-smime.js"/>
<hbox class="box-smallheader" title="&securityTitle.label;" />
<groupbox orient="vertical" id="encryption.titlebox">
<caption label="&encryptionGroupTitle.label;"/>
<label value="&encryptionCert.message;"/>
<separator class="thin"/>
<textbox id="identity.encryption_cert_name" iscontrolcontainer="true" wsm_persist="true" genericattr="true" flex="1"
pref="true" preftype="wstring" prefattribute="value"
prefstring="mail.identity.%identitykey%.encryption_cert_name" readonly="true" disabled="true"/>
<separator class="thin"/>
<hbox>
<spacer flex="1"/>
<button id="encryptionCertSelectButton"
label="&certificate.button;"
oncommand="smimeSelectCert('identity.encryption_cert_name')"/>
</hbox>
<checkbox id="identity.encrypt_mail_if_possible" iscontrolcontainer="true" wsm_persist="true" genericattr="true" pref="true"
preftype="bool" prefattribute="value"
prefstring="mail.identity.%identitykey%.encrypt_mail_if_possible"
label="&ifPossibleEncryptMessage.label;" />
<checkbox id="identity.encrypt_mail_always" iscontrolcontainer="true" wsm_persist="true" genericattr="true" pref="true"
preftype="bool" prefattribute="value"
prefstring="mail.identity.%identitykey%.encrypt_mail_always"
label="&alwaysEncryptMessage.label;" />
</groupbox>
<separator class="thin"/>
<groupbox orient="vertical" id="signing.titlebox">
<caption label="&signingGroupTitle.label;"/>
<label value="&signingCert.message;"/>
<separator class="thin"/>
<textbox id="identity.signing_cert_name" iscontrolcontainer="true" wsm_persist="true" genericattr="true" flex="1"
pref="true" preftype="wstring" prefattribute="value"
prefstring="mail.identity.%identitykey%.signing_cert_name" readonly="true" disabled="true"/>
<separator class="thin"/>
<hbox>
<spacer flex="1"/>
<button id="signingCertSelectButton"
label="&certificate.button;"
oncommand="smimeSelectCert('identity.signing_cert_name')"/>
</hbox>
<checkbox id="identity.sign_mail" iscontrolcontainer="true" wsm_persist="true" genericattr="true" pref="true"
preftype="bool" prefattribute="value"
prefstring="mail.identity.%identitykey%.sign_mail"
label="&signMessage.label;"/>
</groupbox>
</page>

Просмотреть файл

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://chrome.mozilla.org/rdf#">
<!-- list all the packages being supplied by this jar -->
<RDF:Seq about="urn:mozilla:package:root">
<RDF:li resource="urn:mozilla:package:messenger-smime"/>
</RDF:Seq>
<!-- package information -->
<RDF:Description about="urn:mozilla:package:messenger-smime"
chrome:displayName="Messenger"
chrome:author="mozilla.org"
chrome:name="messenger-smime"
chrome:localeVersion="0.9.4"
chrome:skinVersion="0.9.4">
</RDF:Description>
<!-- overlay information -->
<RDF:Seq about="urn:mozilla:overlays">
<RDF:li resource="chrome://messenger/content/messengercompose/messengercompose.xul"/>
</RDF:Seq>
<RDF:Seq about="chrome://messenger/content/messengercompose/messengercompose.xul">
<RDF:li>chrome://messenger-smime/content/msgCompSMIMEOverlay.xul</RDF:li>
</RDF:Seq>
</RDF:RDF>

Просмотреть файл

@ -0,0 +1,45 @@
#!nmake
#
# 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):
DEPTH=..\..\..\..\..
CHROME_DIR=packages\messenger
CHROME_CONTENT_DIR=messenger\content
CHROME_MISC_DIR=.
CHROME_TYPE=content
CHROME_CONTENT = \
.\am-smime.xul \
.\am-smime.js \
.\msgCompSMIMEOverlay.js \
.\msgCompSMIMEOverlay.xul \
.\contents.rdf \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install::
$(MAKE_INSTALL) .\smime.js $(DIST)\bin\defaults\pref
include <$(DEPTH)\config\rules.mak>
chrome::
$(REGCHROME) content messenger-smime messenger.jar

Просмотреть файл

@ -0,0 +1,115 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributors:
* ddrinan@netscape.com
* Scott MacGreogr <mscott@netscape.com>
*/
var ismimeCompFields = Components.interfaces.nsIMsgSMIMECompFields;
var smimeCompFieldsContractID = "@mozilla.org/messenger-smime/composefields;1";
// InitializeSecurityInfo --> when we want to override the default smime behavior for the current message,
// we need to make sure we have a security info object on the msg compose fields....
function GetSecurityInfo()
{
var smimeComposefields;
var msgCompFields = msgCompose.compFields;
if (msgCompFields)
{
if (!msgCompFields.securityInfo)
{
smimeComposefields = Components.classes[smimeCompFieldsContractID].createInstance(ismimeCompFields);
if (smimeComposefields)
{
msgCompFields.securityInfo = smimeComposefields;
// set up the intial security state....
smimeComposefields.alwaysEncryptMessage = gCurrentIdentity.getBoolAttribute("encrypt_mail_always");
smimeComposefields.signMessage = gCurrentIdentity.getBoolAttribute("sign_mail");
}
}
else
{
smimeComposefields = msgCompFields.securityInfo;
}
} // if we have message compose fields...
return smimeComposefields
}
function encryptMessage()
{
var checkedNode = document.getElementById("menu_securityEncryptAlways");
var checked = checkedNode.getAttribute("checked");
var smimeCompFields = GetSecurityInfo();
if (checked)
{
var encryptionCertName = gCurrentIdentity.getUnicharAttribute("encryption_cert_name");
if (!encryptionCertName)
{
alert(gComposeMsgsBundle.getString("chooseEncryptionCertMsg"));
checkedNode.removeAttribute("checked");
smimeCompFields.signMessage = false;
return;
}
smimeCompFields.alwaysEncryptMessage = true;
checkedNode.setAttribute("checked", true);
}
else
{
smimeCompFields.alwaysEncryptMessage = false;
checkedNode.removeAttribute("checked");
}
}
function signMessage()
{
var checkedNode = document.getElementById("menu_securitySign");
var checked = checkedNode.getAttribute("checked");
var smimeCompFields = GetSecurityInfo();
if (checked) // if checked, make sure we have a cert name...
{
var signingCertName = gCurrentIdentity.getUnicharAttribute("signing_cert_name");
if (!signingCertName)
{
alert(gComposeMsgsBundle.getString("chooseSigningCertMsg"));
checkedNode.removeAttribute("checked");
smimeCompFields.signMessage = false;
return;
}
smimeCompFields.signMessage = true;
checkedNode.setAttribute("checked", true);
}
else
{
smimeCompFields.signMessage = false;
checkedNode.removeAttribute("checked");
}
}
function setSecuritySettings()
{
var smimeCompFields = GetSecurityInfo();
document.getElementById("menu_securityEncryptAlways").setAttribute("checked", smimeCompFields.alwaysEncryptMessage);
document.getElementById("menu_securitySign").setAttribute("checked", smimeCompFields.signMessage);
}

Просмотреть файл

@ -0,0 +1,45 @@
<?xml version="1.0"?>
<!--
- 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 Communicator client code, released
- March 31, 1998.
-
- The Initial Developer of the Original Code is Netscape
- Communications Corporation. Portions created by Netscape are
- Copyright (C) 1999 Netscape Communications Corporation. All
- Rights Reserved.
-
- Contributor(s):
- David Drinan <ddrinan@netscape.com>
- Scott MacGregor <mscott@netscape.com
-->
<!DOCTYPE overlay SYSTEM "chrome://messenger-smime/locale/msgCompSMIMEOverlay.dtd">
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script language="JavaScript" src="chrome://messenger-smime/content/msgCompSMIMEOverlay.js"/>
<menupopup id="optionsMenuPopup">
<menuseparator insertafter="fccMenu"/>
<menu label="&securityMenu.label;">
<menupopup onpopupshowing="setSecuritySettings()">
<menuitem id="menu_securityEncryptIfPossible" type="checkbox" label="&menu_securityEncryptIfPossible.label;" disabled="true"/>
<menuitem id="menu_securityEncryptAlways" type="checkbox" label="&menu_securityEncryptAlways.label;" oncommand="encryptMessage()"/>
<menuitem id="menu_securitySign" type="checkbox" label="&menu_securitySign.label;" oncommand="signMessage()"/>
</menupopup>
</menu>
</menupopup>
</overlay>

Просмотреть файл

@ -0,0 +1,11 @@
/*
Add any default pref values we want for smime
*/
pref("mail.identity.default.encryption_cert_name","");
pref("mail.identity.default.encrypt_mail_if_possible", false);
pref("mail.identity.default.encrypt_mail_always", false);
pref("mail.identity.default.signing_cert_name", "");
pref("mail.identity.default.sign_mail", false);

Просмотреть файл

@ -0,0 +1,11 @@
<!ENTITY securityTitle.label "Security">
<!ENTITY encryptionGroupTitle.label "Encryption">
<!ENTITY ifPossibleEncryptMessage.label "Encrypt messages if possible">
<!ENTITY alwaysEncryptMessage.label "Always encrypt messages">
<!ENTITY encryptionCert.message "Personal certificate used for encryption:">
<!ENTITY encryptionCert.notselected "No certificate set">
<!ENTITY certificate.button "Select Certificate">
<!ENTITY signingGroupTitle.label "Signing">
<!ENTITY signMessage.label "Digitally sign messages">
<!ENTITY signingCert.message "Personal certificate used for signing:">
<!ENTITY signingCert.notselected "No certificate set">

Просмотреть файл

@ -0,0 +1,3 @@
prefPanel-smime=Secure Mail
smimeCertPrompt=Select the certificate that you want to use:

Просмотреть файл

@ -0,0 +1,23 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<!-- list all the skins being supplied by this package -->
<RDF:Seq about="urn:mozilla:locale:root">
<RDF:li resource="urn:mozilla:locale:en-US"/>
</RDF:Seq>
<!-- locale information -->
<RDF:Description about="urn:mozilla:locale:en-US">
<chrome:packages>
<RDF:Seq about="urn:mozilla:locale:en-US:packages">
<RDF:li resource="urn:mozilla:locale:en-US:messenger-smime"/>
</RDF:Seq>
</chrome:packages>
</RDF:Description>
<!-- Version Information. State that we work only with major version of this
package. -->
<RDF:Description about="urn:mozilla:locale:en-US:messenger-smime"
chrome:localeVersion="0.9.4"/>
</RDF:RDF>

Просмотреть файл

@ -0,0 +1,38 @@
#!nmake
#
# 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):
DEPTH=..\..\..\..\..\..
CHROME_DIR=locales\en-US
CHROME_L10N_DIR=messenger\locale
CHROME_L10N = \
.\am-smime.dtd \
.\am-smime.properties \
.\msgCompSMIMEOverlay.dtd \
.\contents.rdf \
$(NULL)
include <$(DEPTH)\config\rules.mak>
chrome::
$(REGCHROME) locale en-US/messenger-smime en-US.jar

Просмотреть файл

@ -0,0 +1,7 @@
<!--LOCALIZATION NOTE msgCompSMIMEOverlay.dtd UI for s/mime hooks in message composition -->
<!ENTITY securityMenu.label "Security">
<!ENTITY menu_securityEncryptIfPossible.label "Encrypt if Possible">
<!ENTITY menu_securityEncryptAlways.label "Always Encrypt">
<!ENTITY menu_securitySign.label "Sign">

Просмотреть файл

@ -0,0 +1,26 @@
#!nmake
#
# 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):
DEPTH=..\..\..\..\..
DIRS= en-US
include <$(DEPTH)\config\rules.mak>

Просмотреть файл

@ -0,0 +1 @@
smime-service.js

Просмотреть файл

@ -0,0 +1,88 @@
#
# 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):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = msgsmime
LIBRARY_NAME = msgsmime_s
META_COMPONENT = mail
REQUIRES = xpcom \
string \
dom \
editor \
uriloader \
msgbase \
mailnews \
necko \
mime \
pref \
intl \
locale \
unicharutil \
layout \
content \
msgbaseutil \
msgdb \
rdf \
appshell \
msgimap \
msgnews \
uconv \
docshell \
webshell \
addrbook \
widget \
htmlparser \
txmgr \
exthandler \
mork \
wallet \
nkcache \
mimetype \
windowwatcher \
pipnss \
msgcompose \
$(NULL)
CPPSRCS = \
nsMsgComposeSecure.cpp \
$(NULL)
EXPORTS = \
nsMsgComposeSecure.h \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
ifeq ($(OS_ARCH), Linux)
DEFINES += -D_BSD_SOURCE
endif
install:: ./smime-service.js
$(INSTALL) $< $(DIST)/bin/components

Просмотреть файл

@ -0,0 +1,87 @@
#!nmake
#
# 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):
DEPTH=..\..\..\..
MODULE= msgsmime
REQUIRES = xpcom \
string \
dom \
editor \
uriloader \
msgbase \
msgsearch \
mailnews \
necko \
mime \
pref \
intl \
locale \
uconv \
unicharutil \
layout \
msgbaseutil \
msgdb \
rdf \
appshell \
msgimap \
msgnews \
docshell \
webshell \
addrbook \
widget \
htmlparser \
txmgr \
exthandler \
mork \
wallet \
nkcache \
mimetype \
windowwatcher \
content \
msgcompo \
pipnss \
$(NULL)
include <$(DEPTH)\config\config.mak>
################################################################################
## exports
EXPORTS= nsMsgComposeSecure.h \
$(NULL)
################################################################################
## library
LIBRARY_NAME=msgsmime_s
CPP_OBJS= .\$(OBJDIR)\nsMsgComposeSecure.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
$(MAKE_INSTALL) .\smime-service.js $(DIST)\bin\components
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

Просмотреть файл

@ -0,0 +1,921 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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):
* David Drinan <ddrinan@netscape.com>
*/
#include "nsMsgComposeSecure.h"
#include "nspr.h"
#include "nsCOMPtr.h"
#include "nsICMS.h"
#include "nsIX509Cert.h"
#include "nsIMimeConverter.h"
#include "nsMimeStringResources.h"
#include "nsMimeTypes.h"
#include "nsIX509Cert.h"
#include "nsIX509CertDB.h"
#include "nsMsgBaseCID.h"
#include "nsIMsgHeaderParser.h"
#include "nsFileStream.h"
#include "nsIServiceManager.h"
#include "nsIMsgIdentity.h"
#include "nsIMsgCompFields.h"
static NS_DEFINE_CID(kMsgHeaderParserCID, NS_MSGHEADERPARSER_CID);
// XXX These strings should go in properties file XXX //
#define MIME_MULTIPART_SIGNED_BLURB "This is a cryptographically signed message in MIME format."
#define MIME_SMIME_ENCRYPTED_CONTENT_DESCRIPTION "S/MIME Encrypted Message"
#define MIME_SMIME_SIGNATURE_CONTENT_DESCRIPTION "S/MIME Cryptographic Signature"
#define MK_MIME_ERROR_WRITING_FILE -1
#define SEC_ERROR_NO_EMAIL_CERT -100
static void mime_crypto_write_base64 (void *closure, const char *buf,
unsigned long size);
static nsresult mime_encoder_output_fn(const char *buf, PRInt32 size, void *closure);
static nsresult mime_nested_encoder_output_fn (const char *buf, PRInt32 size, void *closure);
static int make_multipart_signed_header_string(PRBool outer_p,
char **header_return,
char **boundary_return);
extern "C" char *mime_make_separator(const char *prefix);
// mscott --> FIX ME...for now cloning code from compose\nsMsgEncode.h/.cpp
#include "prprf.h"
#include "prmem.h"
#include "nsCOMPtr.h"
#include "nsMsgMimeCID.h"
#include "nsIMimeConverter.h"
/* This is the next generation string retrieval call */
static NS_DEFINE_CID(kCMimeConverterCID, NS_MIME_CONVERTER_CID);
MimeEncoderData *
MIME_B64EncoderInit(nsresult (*output_fn) (const char *buf, PRInt32 size, void *closure), void *closure)
{
MimeEncoderData *returnEncoderData = nsnull;
nsIMimeConverter *converter;
nsresult res = nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
NS_GET_IID(nsIMimeConverter), (void **)&converter);
if (NS_SUCCEEDED(res) && nsnull != converter)
{
res = converter->B64EncoderInit(output_fn, closure, &returnEncoderData);
NS_RELEASE(converter);
}
return NS_SUCCEEDED(res) ? returnEncoderData : nsnull;
}
MimeEncoderData *
MIME_QPEncoderInit(nsresult (*output_fn) (const char *buf, PRInt32 size, void *closure), void *closure)
{
MimeEncoderData *returnEncoderData = nsnull;
nsIMimeConverter *converter;
nsresult res = nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
NS_GET_IID(nsIMimeConverter), (void **)&converter);
if (NS_SUCCEEDED(res) && nsnull != converter)
{
res = converter->QPEncoderInit(output_fn, closure, &returnEncoderData);
NS_RELEASE(converter);
}
return NS_SUCCEEDED(res) ? returnEncoderData : nsnull;
}
MimeEncoderData *
MIME_UUEncoderInit(char *filename, nsresult (*output_fn) (const char *buf, PRInt32 size, void *closure), void *closure)
{
MimeEncoderData *returnEncoderData = nsnull;
nsIMimeConverter *converter;
nsresult res = nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
NS_GET_IID(nsIMimeConverter), (void **)&converter);
if (NS_SUCCEEDED(res) && nsnull != converter)
{
res = converter->UUEncoderInit(filename, output_fn, closure, &returnEncoderData);
NS_RELEASE(converter);
}
return NS_SUCCEEDED(res) ? returnEncoderData : nsnull;
}
nsresult
MIME_EncoderDestroy(MimeEncoderData *data, PRBool abort_p)
{
//MimeEncoderData *returnEncoderData = nsnull;
nsIMimeConverter *converter;
nsresult res = nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
NS_GET_IID(nsIMimeConverter), (void **)&converter);
if (NS_SUCCEEDED(res) && nsnull != converter)
{
res = converter->EncoderDestroy(data, abort_p);
NS_RELEASE(converter);
}
return NS_SUCCEEDED(res) ? 0 : -1;
}
nsresult
MIME_EncoderWrite(MimeEncoderData *data, const char *buffer, PRInt32 size)
{
// MimeEncoderData *returnEncoderData = nsnull;
nsIMimeConverter *converter;
PRInt32 written = 0;
nsresult res = nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
NS_GET_IID(nsIMimeConverter), (void **)&converter);
if (NS_SUCCEEDED(res) && nsnull != converter) {
res = converter->EncoderWrite(data, buffer, size, &written);
NS_RELEASE(converter);
}
return NS_SUCCEEDED(res) ? 0 : -1;
}
static void
GenerateGlobalRandomBytes(unsigned char *buf, PRInt32 len)
{
static PRBool firstTime = PR_TRUE;
if (firstTime)
{
// Seed the random-number generator with current time so that
// the numbers will be different every time we run.
PRInt32 aTime;
LL_L2I(aTime, PR_Now());
srand( (unsigned)aTime );
firstTime = PR_FALSE;
}
for( PRInt32 i = 0; i < len; i++ )
buf[i] = rand() % 10;
}
char
*mime_make_separator(const char *prefix)
{
unsigned char rand_buf[13];
GenerateGlobalRandomBytes(rand_buf, 12);
return PR_smprintf("------------%s"
"%02X%02X%02X%02X"
"%02X%02X%02X%02X"
"%02X%02X%02X%02X",
prefix,
rand_buf[0], rand_buf[1], rand_buf[2], rand_buf[3],
rand_buf[4], rand_buf[5], rand_buf[6], rand_buf[7],
rand_buf[8], rand_buf[9], rand_buf[10], rand_buf[11]);
}
// end of copied code which needs fixed....
/////////////////////////////////////////////////////////////////////////////////////////
// Implementation of nsMsgSMIMEComposeFields
/////////////////////////////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS1(nsMsgSMIMEComposeFields, nsIMsgSMIMECompFields)
nsMsgSMIMEComposeFields::nsMsgSMIMEComposeFields()
{
NS_INIT_ISUPPORTS();
}
nsMsgSMIMEComposeFields::~nsMsgSMIMEComposeFields()
{
}
NS_IMETHODIMP nsMsgSMIMEComposeFields::SetSignMessage(PRBool value)
{
mSignMessage = value;
return NS_OK;
}
NS_IMETHODIMP nsMsgSMIMEComposeFields::GetSignMessage(PRBool *_retval)
{
*_retval = mSignMessage;
return NS_OK;
}
NS_IMETHODIMP nsMsgSMIMEComposeFields::SetAlwaysEncryptMessage(PRBool value)
{
mAlwaysEncryptMessage = value;
return NS_OK;
}
NS_IMETHODIMP nsMsgSMIMEComposeFields::GetAlwaysEncryptMessage(PRBool *_retval)
{
*_retval = mAlwaysEncryptMessage;
return NS_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Implementation of nsMsgComposeSecure
/////////////////////////////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS1(nsMsgComposeSecure, nsIMsgComposeSecure)
nsMsgComposeSecure::nsMsgComposeSecure()
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
mStream = 0;
mDataHash = 0;
mSigEncoderData = 0;
mMultipartSignedBoundary = 0;
mSelfSigningCert = 0;
mSelfEncryptionCert = 0;
mCerts = 0;
mEncryptionCinfo = 0;
mEncryptionContext = 0;
mCryptoEncoderData = 0;
}
nsMsgComposeSecure::~nsMsgComposeSecure()
{
/* destructor code */
if (mEncryptionContext) {
mEncryptionContext->Finish();
}
if (mSigEncoderData) {
MIME_EncoderDestroy (mSigEncoderData, PR_TRUE);
}
if (mCryptoEncoderData) {
MIME_EncoderDestroy (mCryptoEncoderData, PR_TRUE);
}
PR_FREEIF(mMultipartSignedBoundary);
}
NS_IMETHODIMP nsMsgComposeSecure::RequiresCryptoEncapsulation(nsIMsgIdentity * aIdentity, nsIMsgCompFields * aCompFields, PRBool * aRequiresEncryptionWork)
{
NS_ENSURE_ARG_POINTER(aRequiresEncryptionWork);
nsresult rv = NS_OK;
*aRequiresEncryptionWork = PR_FALSE;
PRBool alwaysEncryptMessages = PR_FALSE;
PRBool signMessage = PR_FALSE;
rv = ExtractEncryptionState(aIdentity, aCompFields, &signMessage, &alwaysEncryptMessages);
if (alwaysEncryptMessages || signMessage)
*aRequiresEncryptionWork = PR_TRUE;
return NS_OK;
}
nsresult nsMsgComposeSecure::ExtractEncryptionState(nsIMsgIdentity * aIdentity, nsIMsgCompFields * aComposeFields, PRBool * aSignMessage, PRBool * aEncrypt)
{
if (!aComposeFields && !aIdentity)
return NS_OK; // kick out...invalid args....
nsCOMPtr<nsISupports> securityInfo;
if (aComposeFields)
aComposeFields->GetSecurityInfo(getter_AddRefs(securityInfo));
if (securityInfo) // if we were given security comp fields, use them.....
{
nsCOMPtr<nsIMsgSMIMECompFields> smimeCompFields = do_QueryInterface(securityInfo);
if (smimeCompFields)
{
smimeCompFields->GetSignMessage(aSignMessage);
smimeCompFields->GetAlwaysEncryptMessage(aEncrypt);
}
}
else if (aIdentity) // get the default info from the identity....
{
aIdentity->GetBoolAttribute("encrypt_mail_always", aEncrypt);
aIdentity->GetBoolAttribute("sign_mail", aSignMessage);
}
return NS_OK;
}
/* void beginCryptoEncapsulation (in nsOutputFileStream aStream, in boolean aEncrypt, in boolean aSign, in string aRecipeints, in boolean aIsDraft); */
NS_IMETHODIMP nsMsgComposeSecure::BeginCryptoEncapsulation(nsOutputFileStream * aStream, const char * aRecipients, nsIMsgCompFields * aCompFields, nsIMsgIdentity * aIdentity, PRBool aIsDraft)
{
nsresult rv = NS_OK;
PRBool encryptMessages = PR_FALSE;
PRBool signMessage = PR_FALSE;
ExtractEncryptionState(aIdentity, aCompFields, &signMessage, &encryptMessages);
if (!signMessage && !encryptMessages) return NS_ERROR_FAILURE;
mStream = aStream;
mIsDraft = aIsDraft;
if (encryptMessages && signMessage)
mCryptoState = mime_crypto_signed_encrypted;
else if (encryptMessages)
mCryptoState = mime_crypto_encrypted;
else if (signMessage)
mCryptoState = mime_crypto_clear_signed;
else
PR_ASSERT(0);
aIdentity->GetUnicharAttribute("signing_cert_name", getter_Copies(mSigningCertName));
aIdentity->GetUnicharAttribute("encryption_cert_name", getter_Copies(mEncryptionCertName));
rv = MimeCryptoHackCerts(aRecipients, encryptMessages, signMessage);
if (NS_FAILED(rv)) {
goto FAIL;
}
switch (mCryptoState)
{
case mime_crypto_clear_signed:
rv = MimeInitMultipartSigned(PR_TRUE);
break;
case mime_crypto_opaque_signed:
PR_ASSERT(0); /* #### no api for this yet */
rv = -1;
break;
case mime_crypto_signed_encrypted:
rv = MimeInitEncryption(PR_TRUE);
break;
case mime_crypto_encrypted:
rv = MimeInitEncryption(PR_FALSE);
break;
case mime_crypto_none:
/* This can happen if mime_crypto_hack_certs() decided to turn off
encryption (by asking the user.) */
rv = 1;
break;
default:
PR_ASSERT(0);
break;
}
FAIL:
return rv;
}
/* void finishCryptoEncapsulation (in boolean aAbort); */
NS_IMETHODIMP nsMsgComposeSecure::FinishCryptoEncapsulation(PRBool aAbort)
{
nsresult rv;
if (!aAbort) {
switch (mCryptoState) {
case mime_crypto_clear_signed:
rv = MimeFinishMultipartSigned (PR_TRUE);
break;
case mime_crypto_opaque_signed:
PR_ASSERT(0); /* #### no api for this yet */
rv = NS_ERROR_FAILURE;
break;
case mime_crypto_signed_encrypted:
rv = MimeFinishEncryption (PR_TRUE);
break;
case mime_crypto_encrypted:
rv = MimeFinishEncryption (PR_FALSE);
break;
default:
PR_ASSERT(0);
rv = NS_ERROR_FAILURE;
break;
}
}
return rv;
}
nsresult nsMsgComposeSecure::MimeInitMultipartSigned(PRBool aOuter)
{
/* First, construct and write out the multipart/signed MIME header data.
*/
nsresult rv = NS_OK;
char *header = 0;
PRInt32 L;
rv = make_multipart_signed_header_string(aOuter, &header,
&mMultipartSignedBoundary);
if (NS_FAILED(rv)) goto FAIL;
L = nsCRT::strlen(header);
if (aOuter){
/* If this is the outer block, write it to the file. */
if (PRInt32(mStream->write(header, L)) < L) {
rv = MK_MIME_ERROR_WRITING_FILE;
}
} else {
/* If this is an inner block, feed it through the crypto stream. */
rv = MimeCryptoWriteBlock (header, L);
}
PR_Free(header);
if (NS_FAILED(rv)) goto FAIL;
/* Now initialize the crypto library, so that we can compute a hash
on the object which we are signing.
*/
mHashType = nsIHash::HASH_AlgSHA1;
PR_SetError(0,0);
mDataHash = do_CreateInstance(NS_HASH_CONTRACTID, &rv);
if (NS_FAILED(rv)) return 0;
rv = mDataHash->Create(mHashType);
if (NS_FAILED(rv)) {
goto FAIL;
}
PR_SetError(0,0);
rv = mDataHash->Begin();
FAIL:
return rv;
}
nsresult nsMsgComposeSecure::MimeInitEncryption(PRBool aSign)
{
nsresult rv;
/* First, construct and write out the opaque-crypto-blob MIME header data.
*/
char *s =
PR_smprintf("Content-Type: " APPLICATION_XPKCS7_MIME
"; name=\"smime.p7m\"" CRLF
"Content-Transfer-Encoding: " ENCODING_BASE64 CRLF
"Content-Disposition: attachment"
"; filename=\"smime.p7m\"" CRLF
"Content-Description: %s" CRLF
CRLF,
MIME_SMIME_ENCRYPTED_CONTENT_DESCRIPTION);
PRInt32 L;
if (!s) return NS_ERROR_OUT_OF_MEMORY;
L = nsCRT::strlen(s);
if (PRInt32(mStream->write(s, L)) < L) {
return NS_ERROR_FAILURE;
}
PR_Free(s);
s = 0;
/* Now initialize the crypto library, so that we can filter the object
to be encrypted through it.
*/
if (!mIsDraft) {
PRUint32 numCerts;
mCerts->Count(&numCerts);
PR_ASSERT(numCerts > 0);
if (numCerts == 0) return NS_ERROR_FAILURE;
}
/* Initialize the base64 encoder. */
PR_ASSERT(!mCryptoEncoderData);
mCryptoEncoderData = MIME_B64EncoderInit(mime_encoder_output_fn,
this);
if (!mCryptoEncoderData) {
return NS_ERROR_OUT_OF_MEMORY;
}
/* Initialize the encrypter (and add the sender's cert.) */
PR_ASSERT(mSelfEncryptionCert);
PR_SetError(0,0);
mEncryptionCinfo = do_CreateInstance(NS_CMSMESSAGE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return 0;
rv = mEncryptionCinfo->CreateEncrypted(mCerts); // XXX Fix this later XXX //
if (NS_FAILED(rv)) {
goto FAIL;
}
mEncryptionContext = do_CreateInstance(NS_CMSENCODER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return 0;
rv = mEncryptionContext->Start(mEncryptionCinfo, mime_crypto_write_base64, mCryptoEncoderData); // XXX Fix this later XXX //
if (NS_FAILED(rv)) {
goto FAIL;
}
/* If we're signing, tack a multipart/signed header onto the front of
the data to be encrypted, and initialize the sign-hashing code too.
*/
if (aSign) {
rv = MimeInitMultipartSigned(PR_FALSE);
if (NS_FAILED(rv)) goto FAIL;
}
FAIL:
return rv;
}
nsresult nsMsgComposeSecure::MimeFinishMultipartSigned (PRBool aOuter)
{
int status;
nsresult rv;
PRUint32 sec_item_len;
unsigned char * sec_item_data;
nsCOMPtr<nsICMSMessage> cinfo = do_CreateInstance(NS_CMSMESSAGE_CONTRACTID, &rv);
nsCOMPtr<nsICMSEncoder> encoder = do_CreateInstance(NS_CMSENCODER_CONTRACTID, &rv);
PRStatus ds_status = PR_FAILURE;
char * header = nsnull;
/* Compute the hash...
*/
mDataHash->ResultLen(mHashType, &sec_item_len);
sec_item_data = (unsigned char *) PR_MALLOC(sec_item_len);
if (!sec_item_data) {
status = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
PR_SetError(0,0);
mDataHash->End(sec_item_data, &sec_item_len, sec_item_len);
status = PR_GetError();
if (status < 0) {
rv = NS_ERROR_FAILURE;
goto FAIL;
}
PR_SetError(0,0);
mDataHash = 0;
status = PR_GetError();
if (status < 0) goto FAIL;
/* Write out the headers for the signature.
*/
PRInt32 L;
header =
PR_smprintf(CRLF
"--%s" CRLF
"Content-Type: " APPLICATION_XPKCS7_SIGNATURE
"; name=\"smime.p7s\"" CRLF
"Content-Transfer-Encoding: " ENCODING_BASE64 CRLF
"Content-Disposition: attachment; "
"filename=\"smime.p7s\"" CRLF
"Content-Description: %s" CRLF
CRLF,
mMultipartSignedBoundary,
MIME_SMIME_SIGNATURE_CONTENT_DESCRIPTION);
if (!header) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
L = nsCRT::strlen(header);
if (aOuter) {
/* If this is the outer block, write it to the file. */
if (PRInt32(mStream->write(header, L)) < L) {
rv = MK_MIME_ERROR_WRITING_FILE;
}
} else {
/* If this is an inner block, feed it through the crypto stream. */
rv = MimeCryptoWriteBlock (header, L);
}
PR_Free(header);
if (status < 0) goto FAIL;
/* Create the signature...
*/
PR_ASSERT(mHashType == nsIHash::HASH_AlgSHA1);
PR_ASSERT (mSelfSigningCert);
PR_SetError(0,0);
rv = cinfo->CreateSigned(mSelfSigningCert, mSelfEncryptionCert, sec_item_data, sec_item_len);
if (NS_FAILED(rv)) {
goto FAIL;
}
/* Initialize the base64 encoder for the signature data.
*/
PR_ASSERT(!mSigEncoderData);
mSigEncoderData =
MIME_B64EncoderInit((aOuter
? mime_encoder_output_fn
: mime_nested_encoder_output_fn),
this);
if (!mSigEncoderData) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
/* Write out the signature.
*/
PR_SetError(0,0);
rv = encoder->Start(cinfo, mime_crypto_write_base64, mSigEncoderData);
if (NS_FAILED(rv)) {
goto FAIL;
}
// We're not passing in any data, so no update needed.
rv = encoder->Finish();
if (NS_FAILED(rv)) {
goto FAIL;
}
/* Shut down the sig's base64 encoder.
*/
rv = MIME_EncoderDestroy(mSigEncoderData, PR_FALSE);
mSigEncoderData = 0;
if (NS_FAILED(rv)) {
goto FAIL;
}
/* Now write out the terminating boundary.
*/
{
PRInt32 L;
char *header = PR_smprintf(CRLF "--%s--" CRLF,
mMultipartSignedBoundary);
PR_Free(mMultipartSignedBoundary);
mMultipartSignedBoundary = 0;
if (!header) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto FAIL;
}
L = nsCRT::strlen(header);
if (aOuter) {
/* If this is the outer block, write it to the file. */
if (PRInt32(mStream->write(header, L)) < L)
rv = MK_MIME_ERROR_WRITING_FILE;
} else {
/* If this is an inner block, feed it through the crypto stream. */
rv = MimeCryptoWriteBlock (header, L);
}
}
FAIL:
PR_FREEIF(sec_item_data);
return rv;
}
/* Helper function for mime_finish_crypto_encapsulation() to close off
an opaque crypto object (for encrypted or signed-and-encrypted messages.)
*/
nsresult nsMsgComposeSecure::MimeFinishEncryption (PRBool aSign)
{
nsresult rv;
/* If this object is both encrypted and signed, close off the
signature first (since it's inside.) */
if (aSign) {
rv = MimeFinishMultipartSigned (PR_FALSE);
if (NS_FAILED(rv)) {
goto FAIL;
}
}
/* Close off the opaque encrypted blob.
*/
PR_ASSERT(mEncryptionContext);
rv = mEncryptionContext->Finish();
if (NS_FAILED(rv)) {
goto FAIL;
}
mEncryptionContext = 0;
PR_ASSERT(mEncryptionCinfo);
if (!mEncryptionCinfo) {
rv = NS_ERROR_FAILURE;
}
if (mEncryptionCinfo) {
mEncryptionCinfo = 0;
}
/* Shut down the base64 encoder. */
rv = MIME_EncoderDestroy(mCryptoEncoderData, PR_FALSE);
mCryptoEncoderData = 0;
FAIL:
return rv;
}
/* Used to figure out what certs should be used when encrypting this message.
*/
nsresult nsMsgComposeSecure::MimeCryptoHackCerts(const char *aRecipients, PRBool aEncrypt, PRBool aSign)
{
int status = 0;
char *all_mailboxes = 0, *mailboxes = 0, *mailbox_list = 0;
const char *mailbox = 0;
PRUint32 count = 0;
PRUint32 numCerts;
nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
nsCOMPtr<nsIMsgHeaderParser> pHeader;
nsresult res = nsComponentManager::CreateInstance(kMsgHeaderParserCID,
NULL, NS_GET_IID(nsIMsgHeaderParser),
(void **) getter_AddRefs(pHeader));
res = NS_NewISupportsArray(getter_AddRefs(mCerts));
if (NS_FAILED(res)) {
return res;
}
PRBool no_clearsigning_p = PR_FALSE;
PR_ASSERT(aEncrypt || aSign);
certdb->GetEmailEncryptionCert(mEncryptionCertName, getter_AddRefs(mSelfEncryptionCert));
certdb->GetEmailSigningCert(mSigningCertName, getter_AddRefs(mSelfSigningCert));
if ((mSelfSigningCert == nsnull) && aSign) {
status = SEC_ERROR_NO_EMAIL_CERT;
goto FAIL;
}
if ((mSelfEncryptionCert == nsnull) && aEncrypt) {
status = SEC_ERROR_NO_EMAIL_CERT;
goto FAIL;
}
pHeader->ExtractHeaderAddressMailboxes(nsnull,aRecipients, &all_mailboxes);
pHeader->RemoveDuplicateAddresses(nsnull, all_mailboxes, 0, PR_FALSE /*removeAliasesToMe*/, &mailboxes);
PR_FREEIF(all_mailboxes);
if (mailboxes) {
pHeader->ParseHeaderAddresses (nsnull, mailboxes, 0, &mailbox_list, &count);
}
PR_FREEIF(mailboxes);
if (count < 0) return count;
/* If the message is to be encrypted, then get the recipient certs */
if (aEncrypt) {
mailbox = mailbox_list;
for (; count > 0; count--) {
nsCOMPtr<nsIX509Cert> cert;
certdb->GetCertByEmailAddress(nsnull, mailbox, getter_AddRefs(cert));
if (!cert) {
mailbox += nsCRT::strlen(mailbox) + 1;
continue;
}
/* #### see if recipient requests `signedData'.
if (...) no_clearsigning_p = PR_TRUE;
(This is the only reason we even bother looking up the certs
of the recipients if we're sending a signed-but-not-encrypted
message.)
*/
mCerts->AppendElement(cert);
mailbox += nsCRT::strlen(mailbox) + 1;
}
mCerts->Count(&numCerts);
if (numCerts == 0) {
res = NS_ERROR_FAILURE; // XXX We should set a specific error in this case XXX //
goto FAIL;
}
}
FAIL:
PR_FREEIF(mailbox_list);
return res;
}
NS_IMETHODIMP nsMsgComposeSecure::MimeCryptoWriteBlock (const char *buf, PRInt32 size)
{
int status = 0;
nsresult rv;
/* If this is a From line, mangle it before signing it. You just know
that something somewhere is going to mangle it later, and that's
going to cause the signature check to fail.
(This assumes that, in the cases where From-mangling must happen,
this function is called a line at a time. That happens to be the
case.)
*/
if (size >= 5 && buf[0] == 'F' && !nsCRT::strncmp(buf, "From ", 5)) {
char mangle[] = ">";
status = MimeCryptoWriteBlock (mangle, 1);
if (status < 0)
return status;
}
/* If we're signing, or signing-and-encrypting, feed this data into
the computation of the hash. */
if (mDataHash) {
PR_SetError(0,0);
mDataHash->Update((unsigned char *) buf, size);
status = PR_GetError();
if (status < 0) goto FAIL;
}
PR_SetError(0,0);
if (mEncryptionContext) {
/* If we're encrypting, or signing-and-encrypting, write this data
by filtering it through the crypto library. */
rv = mEncryptionContext->Update(buf, size);
if (NS_FAILED(rv)) {
status = PR_GetError();
PR_ASSERT(status < 0);
if (status >= 0) status = -1;
goto FAIL;
}
} else {
/* If we're not encrypting (presumably just signing) then write this
data directly to the file. */
if (PRInt32(mStream->write (buf, size)) < size) {
return MK_MIME_ERROR_WRITING_FILE;
}
}
FAIL:
return status;
}
/* Returns a string consisting of a Content-Type header, and a boundary
string, suitable for moving from the header block, down into the body
of a multipart object. The boundary itself is also returned (so that
the caller knows what to write to close it off.)
*/
static int
make_multipart_signed_header_string(PRBool outer_p,
char **header_return,
char **boundary_return)
{
*header_return = 0;
*boundary_return = mime_make_separator("ms");
const char * crypto_multipart_blurb = nsnull;
if (!*boundary_return)
return NS_ERROR_OUT_OF_MEMORY;
if (outer_p) {
crypto_multipart_blurb = MIME_MULTIPART_SIGNED_BLURB;
}
*header_return =
PR_smprintf("Content-Type: " MULTIPART_SIGNED "; "
"protocol=\"" APPLICATION_XPKCS7_SIGNATURE "\"; "
"micalg=" PARAM_MICALG_SHA1 "; "
"boundary=\"%s\"" CRLF
CRLF
"%s%s"
"--%s" CRLF,
*boundary_return,
(crypto_multipart_blurb ? crypto_multipart_blurb : ""),
(crypto_multipart_blurb ? CRLF CRLF : ""),
*boundary_return);
if (!*header_return) {
PR_Free(*boundary_return);
*boundary_return = 0;
return NS_ERROR_OUT_OF_MEMORY;
}
return 0;
}
/* Used as the output function of a SEC_PKCS7EncoderContext -- we feed
plaintext into the crypto engine, and it calls this function with encrypted
data; then this function writes a base64-encoded representation of that
data to the file (by filtering it through the given MimeEncoderData object.)
Also used as the output function of SEC_PKCS7Encode() -- but in that case,
it's used to write the encoded representation of the signature. The only
difference is which MimeEncoderData object is used.
*/
static void
mime_crypto_write_base64 (void *closure, const char *buf,
unsigned long size)
{
MimeEncoderData *data = (MimeEncoderData *) closure;
int status = MIME_EncoderWrite (data, buf, size);
PR_SetError(status < 0 ? status : 0, 0);
}
/* Used as the output function of MimeEncoderData -- when we have generated
the signature for a multipart/signed object, this is used to write the
base64-encoded representation of the signature to the file.
*/
nsresult mime_encoder_output_fn(const char *buf, PRInt32 size, void *closure)
{
nsMsgComposeSecure *state = (nsMsgComposeSecure *) closure;
nsOutputFileStream *stream = state->GetOutputStream();
if (PRInt32(stream->write((char *) buf, size)) < size)
return MK_MIME_ERROR_WRITING_FILE;
else
return 0;
}
/* Like mime_encoder_output_fn, except this is used for the case where we
are both signing and encrypting -- the base64-encoded output of the
signature should be fed into the crypto engine, rather than being written
directly to the file.
*/
static nsresult
mime_nested_encoder_output_fn (const char *buf, PRInt32 size, void *closure)
{
nsMsgComposeSecure *state = (nsMsgComposeSecure *) closure;
return state->MimeCryptoWriteBlock ((char *) buf, size);
}

Просмотреть файл

@ -0,0 +1,92 @@
/* -*- Mode: idl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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):
*/
#ifndef _nsMsgComposeSecure_H_
#define _nsMsgComposeSecure_H_
#include "nsIMsgComposeSecure.h"
#include "nsIMsgSMIMECompFields.h"
#include "nsCOMPtr.h"
#include "nsICMS.h"
#include "nsIX509Cert.h"
#include "nsIMimeConverter.h"
class nsIMsgCompFields;
class nsMsgSMIMEComposeFields : public nsIMsgSMIMECompFields
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGSMIMECOMPFIELDS
nsMsgSMIMEComposeFields();
virtual ~nsMsgSMIMEComposeFields();
private:
PRBool mSignMessage;
PRBool mAlwaysEncryptMessage;
};
typedef enum {
mime_crypto_none, /* normal unencapsulated MIME message */
mime_crypto_clear_signed, /* multipart/signed encapsulation */
mime_crypto_opaque_signed, /* application/x-pkcs7-mime (signedData) */
mime_crypto_encrypted, /* application/x-pkcs7-mime */
mime_crypto_signed_encrypted /* application/x-pkcs7-mime */
} mimeDeliveryCryptoState;
class nsMsgComposeSecure : public nsIMsgComposeSecure
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGCOMPOSESECURE
nsMsgComposeSecure();
virtual ~nsMsgComposeSecure();
/* additional members */
nsOutputFileStream *GetOutputStream() { return mStream;}
private:
nsresult MimeInitMultipartSigned(PRBool aOuter);
nsresult MimeInitEncryption(PRBool aSign);
nsresult MimeFinishMultipartSigned (PRBool aOuter);
nsresult MimeFinishEncryption (PRBool aSign);
nsresult MimeCryptoHackCerts(const char *aRecipients, PRBool aEncrypt, PRBool aSign);
nsresult ExtractEncryptionState(nsIMsgIdentity * aIdentity, nsIMsgCompFields * aComposeFields, PRBool * aSignMessage, PRBool * aEncrypt);
mimeDeliveryCryptoState mCryptoState;
nsOutputFileStream *mStream;
PRInt16 mHashType;
nsCOMPtr<nsIHash> mDataHash;
MimeEncoderData *mSigEncoderData;
char *mMultipartSignedBoundary;
nsXPIDLString mSigningCertName;
nsCOMPtr<nsIX509Cert> mSelfSigningCert;
nsXPIDLString mEncryptionCertName;
nsCOMPtr<nsIX509Cert> mSelfEncryptionCert;
nsCOMPtr<nsISupportsArray> mCerts;
nsCOMPtr<nsICMSMessage> mEncryptionCinfo;
nsCOMPtr<nsICMSEncoder> mEncryptionContext;
MimeEncoderData *mCryptoEncoderData;
PRBool mIsDraft;
};
#endif

Просмотреть файл

@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Seth Spitzer <sspitzer@netscape.com>
*/
/* components defined in this file */
const SMIME_EXTENSION_SERVICE_CONTRACTID =
"@mozilla.org/accounmanager/extension;1?name=smime";
const SMIME_EXTENSION_SERVICE_CID =
Components.ID("{f2809796-1dd1-11b2-8c1b-8f15f007c699}");
/* interafces used in this file */
const nsIMsgAccountManagerExtension = Components.interfaces.nsIMsgAccountManagerExtension;
const nsICategoryManager = Components.interfaces.nsICategoryManager;
const nsISupports = Components.interfaces.nsISupports;
function SMIMEService()
{}
SMIMEService.prototype.name = "smime";
SMIMEService.prototype.showPanel =
function (server)
{
// don't show the S/MIME panel for news accounts
return (server.type != "nntp");
}
/* factory for command line handler service (SMIMEService) */
var SMIMEFactory = new Object();
SMIMEFactory.createInstance =
function (outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
if (!iid.equals(nsIMsgAccountManagerExtension) && !iid.equals(nsISupports))
throw Components.results.NS_ERROR_INVALID_ARG;
return new SMIMEService();
}
var SMIMEModule = new Object();
SMIMEModule.registerSelf =
function (compMgr, fileSpec, location, type)
{
dump("*** Registering smime account manager extension.\n");
compMgr.registerComponentWithType(SMIME_EXTENSION_SERVICE_CID,
"SMIME Account Manager Extension Service",
SMIME_EXTENSION_SERVICE_CONTRACTID, fileSpec,
location, true, true, type);
catman = Components.classes["@mozilla.org/categorymanager;1"].getService(nsICategoryManager);
catman.addCategoryEntry("mailnews-accountmanager-extensions",
"smime account manager extension",
SMIME_EXTENSION_SERVICE_CONTRACTID, true, true);
}
SMIMEModule.unregisterSelf =
function(compMgr, fileSpec, location)
{
compMgr.unregisterComponentSpec(SMIME_EXTENSION_SERVICE_CID, fileSpec);
catman = Components.classes["@mozilla.org/categorymanager;1"].getService(nsICategoryManager);
catman.deleteCategoryEntry("mailnews-accountmanager-extensions",
SMIME_EXTENSION_SERVICE_CONTRACTID, true);
}
SMIMEModule.getClassObject =
function (compMgr, cid, iid) {
if (cid.equals(SMIME_EXTENSION_SERVICE_CID))
return SMIMEFactory;
if (!iid.equals(Components.interfaces.nsIFactory))
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
SMIMEModule.canUnload =
function(compMgr)
{
return true;
}
/* entrypoint */
function NSGetModule(compMgr, fileSpec) {
return SMIMEModule;
}