bug 329990, Unwind S/Mime signature verification from UI thread

bug 332212, Incorrect calls to update chrome UI with sign/encrypt status
r/sr=mscott
This commit is contained in:
kaie%kuix.de 2006-04-04 06:44:26 +00:00
Родитель 18f6a01631
Коммит 0c9d77c956
6 изменённых файлов: 256 добавлений и 688 удалений

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

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Kai Engert <kengert@redhat.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -36,6 +37,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsICMSMessage.h"
#include "nsICMSMessage2.h"
#include "nsICMSMessageErrors.h"
#include "nsICMSDecoder.h"
#include "mimecms.h"
@ -53,6 +55,7 @@
#include "nsCOMPtr.h"
#include "nsIX509Cert.h"
#include "nsIMsgHeaderParser.h"
#include "nsIProxyObjectManager.h"
#define MIME_SUPERCLASS mimeEncryptedClass
@ -64,7 +67,6 @@ static int MimeCMS_write (const char *, PRInt32, void *);
static int MimeCMS_eof (void *, PRBool);
static char * MimeCMS_generate (void *);
static void MimeCMS_free (void *);
static void MimeCMS_get_content_info (MimeObject *, nsICMSMessage **, char **, PRInt32 *, PRInt32 *, PRBool *);
extern int SEC_ERROR_CERT_ADDR_MISMATCH;
@ -82,8 +84,6 @@ static int MimeEncryptedCMSClassInitialize(MimeEncryptedCMSClass *clazz)
eclass->crypto_generate_html = MimeCMS_generate;
eclass->crypto_free = MimeCMS_free;
clazz->get_content_info = MimeCMS_get_content_info;
return 0;
}
@ -96,8 +96,7 @@ typedef struct MimeCMSdata
nsCOMPtr<nsICMSMessage> content_info;
PRBool ci_is_encrypted;
char *sender_addr;
PRInt32 decode_error;
PRInt32 verify_error;
PRBool decoding_failed;
MimeObject *self;
PRBool parent_is_encrypted_p;
PRBool parent_holds_stamp_p;
@ -108,8 +107,7 @@ typedef struct MimeCMSdata
output_closure(nsnull),
ci_is_encrypted(PR_FALSE),
sender_addr(nsnull),
decode_error(PR_FALSE),
verify_error(PR_FALSE),
decoding_failed(PR_FALSE),
self(nsnull),
parent_is_encrypted_p(PR_FALSE),
parent_holds_stamp_p(PR_FALSE)
@ -130,30 +128,6 @@ typedef struct MimeCMSdata
}
} MimeCMSdata;
static void MimeCMS_get_content_info(MimeObject *obj,
nsICMSMessage **content_info_ret,
char **sender_email_addr_return,
PRInt32 *decode_error_ret,
PRInt32 *verify_error_ret,
PRBool *ci_is_encrypted)
{
MimeEncrypted *enc = (MimeEncrypted *) obj;
if (enc && enc->crypto_closure)
{
MimeCMSdata *data = (MimeCMSdata *) enc->crypto_closure;
*decode_error_ret = data->decode_error;
*verify_error_ret = data->verify_error;
*content_info_ret = data->content_info;
*ci_is_encrypted = data->ci_is_encrypted;
if (sender_email_addr_return)
*sender_email_addr_return = (data->sender_addr ? nsCRT::strdup(data->sender_addr) : 0);
}
}
/* SEC_PKCS7DecoderContentCallback for SEC_PKCS7DecoderStart() */
static void MimeCMS_content_callback (void *arg, const char *buf, unsigned long length)
{
@ -204,19 +178,14 @@ static void ParseRFC822Addresses (const char *line, nsXPIDLCString &names, nsXPI
}
}
extern char *IMAP_CreateReloadAllPartsUrl(const char *url);
PRBool MimeCMSHeadersAndCertsMatch(MimeObject *obj,
nsICMSMessage *content_info,
PRBool *signing_cert_without_email_address,
char **sender_email_addr_return)
PRBool MimeCMSHeadersAndCertsMatch(nsICMSMessage *content_info,
nsIX509Cert *signerCert,
const char *from_addr,
const char *from_name,
const char *sender_addr,
const char *sender_name,
PRBool *signing_cert_without_email_address)
{
MimeHeaders *msg_headers = 0;
nsXPIDLCString from_addr;
nsXPIDLCString from_name;
nsXPIDLCString sender_addr;
nsXPIDLCString sender_name;
nsXPIDLCString cert_addr;
PRBool match = PR_TRUE;
PRBool foundFrom = PR_FALSE;
@ -236,52 +205,6 @@ PRBool MimeCMSHeadersAndCertsMatch(MimeObject *obj,
*signing_cert_without_email_address = (!cert_addr);
}
if (!cert_addr) {
// no address, no match
return PR_FALSE;
}
/* Find the headers of the MimeMessage which is the parent (or grandparent)
of this object (remember, crypto objects nest.) */
{
MimeObject *o2 = obj;
msg_headers = o2->headers;
while (o2 &&
o2->parent &&
!mime_typep(o2->parent, (MimeObjectClass *) &mimeMessageClass))
{
o2 = o2->parent;
msg_headers = o2->headers;
}
}
if (!msg_headers) {
// no headers, no match
return PR_FALSE;
}
/* Find the names and addresses in the From and/or Sender fields.
*/
{
char *s;
/* Extract the name and address of the "From:" field. */
s = MimeHeaders_get(msg_headers, HEADER_FROM, PR_FALSE, PR_FALSE);
if (s)
{
ParseRFC822Addresses(s, from_name, from_addr);
PR_FREEIF(s);
}
/* Extract the name and address of the "Sender:" field. */
s = MimeHeaders_get(msg_headers, HEADER_SENDER, PR_FALSE, PR_FALSE);
if (s)
{
ParseRFC822Addresses(s, sender_name, sender_addr);
PR_FREEIF(s);
}
}
/* Now compare them --
consider it a match if the address in the cert matches either the
address in the From or Sender field
@ -294,9 +217,6 @@ PRBool MimeCMSHeadersAndCertsMatch(MimeObject *obj,
}
else
{
nsCOMPtr<nsIX509Cert> signerCert;
content_info->GetSignerCert(getter_AddRefs(signerCert));
if (signerCert)
{
if (from_addr && *from_addr)
@ -324,20 +244,100 @@ PRBool MimeCMSHeadersAndCertsMatch(MimeObject *obj,
}
}
if (sender_email_addr_return) {
if (match && foundFrom)
*sender_email_addr_return = nsCRT::strdup(from_addr);
if (match && foundSender)
*sender_email_addr_return = nsCRT::strdup(sender_addr);
else if (from_addr && *from_addr)
*sender_email_addr_return = nsCRT::strdup(from_addr);
else if (sender_addr && *sender_addr)
*sender_email_addr_return = nsCRT::strdup(sender_addr);
else
*sender_email_addr_return = 0;
return match;
}
class nsSMimeVerificationListener : public nsISMimeVerificationListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISMIMEVERIFICATIONLISTENER
nsSMimeVerificationListener(const char *aFromAddr, const char *aFromName,
const char *aSenderAddr, const char *aSenderName,
nsIMsgSMIMEHeaderSink *aHeaderSink, PRInt32 aMimeNestingLevel);
virtual ~nsSMimeVerificationListener() {}
protected:
nsCOMPtr<nsIMsgSMIMEHeaderSink> mHeaderSink;
PRInt32 mMimeNestingLevel;
nsXPIDLCString mFromAddr;
nsXPIDLCString mFromName;
nsXPIDLCString mSenderAddr;
nsXPIDLCString mSenderName;
};
NS_IMPL_ISUPPORTS1(nsSMimeVerificationListener, nsISMimeVerificationListener)
nsSMimeVerificationListener::nsSMimeVerificationListener(const char *aFromAddr, const char *aFromName,
const char *aSenderAddr, const char *aSenderName,
nsIMsgSMIMEHeaderSink *aHeaderSink, PRInt32 aMimeNestingLevel)
{
mHeaderSink = aHeaderSink;
mMimeNestingLevel = aMimeNestingLevel;
mFromAddr = aFromAddr;
mFromName = aFromName;
mSenderAddr = aSenderAddr;
mSenderName = aSenderName;
}
NS_IMETHODIMP nsSMimeVerificationListener::Notify(nsICMSMessage2 *aVerifiedMessage,
nsresult aVerificationResultCode)
{
// Only continue if we have a valid pointer to the UI
NS_ENSURE_TRUE(mHeaderSink, NS_OK);
NS_ENSURE_TRUE(aVerifiedMessage, NS_ERROR_FAILURE);
nsCOMPtr<nsICMSMessage> msg = do_QueryInterface(aVerifiedMessage);
NS_ENSURE_TRUE(msg, NS_ERROR_FAILURE);
nsCOMPtr<nsIX509Cert> signerCert;
msg->GetSignerCert(getter_AddRefs(signerCert));
PRInt32 signature_status = nsICMSMessageErrors::GENERAL_ERROR;
if (NS_FAILED(aVerificationResultCode))
{
if (NS_ERROR_MODULE_SECURITY == NS_ERROR_GET_MODULE(aVerificationResultCode))
signature_status = NS_ERROR_GET_CODE(aVerificationResultCode);
else if (NS_ERROR_NOT_IMPLEMENTED == aVerificationResultCode)
signature_status = nsICMSMessageErrors::VERIFY_ERROR_PROCESSING;
}
else
{
PRBool signing_cert_without_email_address;
PRBool good_p = MimeCMSHeadersAndCertsMatch(msg, signerCert,
mFromAddr.get(), mFromName.get(),
mSenderAddr.get(), mSenderName.get(),
&signing_cert_without_email_address);
if (!good_p)
{
if (signing_cert_without_email_address)
signature_status = nsICMSMessageErrors::VERIFY_CERT_WITHOUT_ADDRESS;
else
signature_status = nsICMSMessageErrors::VERIFY_HEADER_MISMATCH;
}
else
signature_status = nsICMSMessageErrors::SUCCESS;
}
return match;
nsCOMPtr<nsIProxyObjectManager> proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID));
if (proxyman)
{
nsCOMPtr<nsIMsgSMIMEHeaderSink> proxySink;
proxyman->GetProxyForObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsIMsgSMIMEHeaderSink),
mHeaderSink, PROXY_SYNC, getter_AddRefs(proxySink));
if (proxySink)
proxySink->SignedStatus(mMimeNestingLevel, signature_status, signerCert);
}
return NS_OK;
}
int MIMEGetRelativeCryptoNestLevel(MimeObject *obj)
@ -371,7 +371,10 @@ int MIMEGetRelativeCryptoNestLevel(MimeObject *obj)
aTopShownObject = walker;
}
if (!aAlreadyFoundTop && !walker->parent) {
aTopShownObject = walker;
// The mime part part_to_load is not a parent of the
// the crypto mime part passed in to this function as parameter obj.
// That means the crypto part belongs to another branch of the mime tree.
return -1;
}
}
}
@ -509,18 +512,83 @@ MimeCMS_write (const char *buf, PRInt32 buf_size, void *closure)
PR_SetError(0, 0);
rv = data->decoder_context->Update(buf, buf_size);
if (NS_FAILED(rv)) {
data->verify_error = -1;
}
data->decoding_failed = NS_FAILED(rv);
return 0;
}
void MimeCMSGetFromSender(MimeObject *obj,
nsXPIDLCString &from_addr,
nsXPIDLCString &from_name,
nsXPIDLCString &sender_addr,
nsXPIDLCString &sender_name)
{
MimeHeaders *msg_headers = 0;
/* Find the headers of the MimeMessage which is the parent (or grandparent)
of this object (remember, crypto objects nest.) */
MimeObject *o2 = obj;
msg_headers = o2->headers;
while (o2 &&
o2->parent &&
!mime_typep(o2->parent, (MimeObjectClass *) &mimeMessageClass))
{
o2 = o2->parent;
msg_headers = o2->headers;
}
if (!msg_headers)
return;
/* Find the names and addresses in the From and/or Sender fields.
*/
char *s;
/* Extract the name and address of the "From:" field. */
s = MimeHeaders_get(msg_headers, HEADER_FROM, PR_FALSE, PR_FALSE);
if (s)
{
ParseRFC822Addresses(s, from_name, from_addr);
PR_FREEIF(s);
}
/* Extract the name and address of the "Sender:" field. */
s = MimeHeaders_get(msg_headers, HEADER_SENDER, PR_FALSE, PR_FALSE);
if (s)
{
ParseRFC822Addresses(s, sender_name, sender_addr);
PR_FREEIF(s);
}
}
void MimeCMSRequestAsyncSignatureVerification(nsICMSMessage *aCMSMsg,
const char *aFromAddr, const char *aFromName,
const char *aSenderAddr, const char *aSenderName,
nsIMsgSMIMEHeaderSink *aHeaderSink, PRInt32 aMimeNestingLevel,
unsigned char* item_data, PRUint32 item_len)
{
nsCOMPtr<nsICMSMessage2> msg2 = do_QueryInterface(aCMSMsg);
if (!msg2)
return;
nsRefPtr<nsSMimeVerificationListener> listener =
new nsSMimeVerificationListener(aFromAddr, aFromName, aSenderAddr, aSenderName,
aHeaderSink, aMimeNestingLevel);
if (!listener)
return;
if (item_data)
msg2->AsyncVerifyDetachedSignature(listener, item_data, item_len);
else
msg2->AsyncVerifySignature(listener);
}
static int
MimeCMS_eof (void *crypto_closure, PRBool abort_p)
{
MimeCMSdata *data = (MimeCMSdata *) crypto_closure;
nsresult rv;
PRInt32 status = nsICMSMessageErrors::SUCCESS;
if (!data || !data->output_fn || !data->decoder_context) {
return -1;
@ -538,9 +606,8 @@ MimeCMS_eof (void *crypto_closure, PRBool abort_p)
PR_SetError(0, 0);
rv = data->decoder_context->Finish(getter_AddRefs(data->content_info));
if (NS_FAILED(rv))
data->verify_error = PR_GetError();
status = nsICMSMessageErrors::GENERAL_ERROR;
data->decoder_context = 0;
@ -549,9 +616,8 @@ MimeCMS_eof (void *crypto_closure, PRBool abort_p)
if (!data->smimeHeaderSink)
return 0;
if (aRelativeNestLevel < 0) {
if (aRelativeNestLevel < 0)
return 0;
}
PRInt32 maxNestLevel = 0;
data->smimeHeaderSink->MaxWantedNesting(&maxNestLevel);
@ -559,14 +625,8 @@ MimeCMS_eof (void *crypto_closure, PRBool abort_p)
if (aRelativeNestLevel > maxNestLevel)
return 0;
PRInt32 status = nsICMSMessageErrors::SUCCESS;
if (data->verify_error
|| data->decode_error
|| NS_FAILED(rv))
{
if (data->decoding_failed)
status = nsICMSMessageErrors::GENERAL_ERROR;
}
if (!data->content_info)
{
@ -598,34 +658,20 @@ MimeCMS_eof (void *crypto_closure, PRBool abort_p)
return 0;
}
rv = data->content_info->VerifySignature();
nsXPIDLCString from_addr;
nsXPIDLCString from_name;
nsXPIDLCString sender_addr;
nsXPIDLCString sender_name;
if (NS_FAILED(rv)) {
if (NS_ERROR_MODULE_SECURITY == NS_ERROR_GET_MODULE(rv)) {
status = NS_ERROR_GET_CODE(rv);
}
else if (NS_ERROR_NOT_IMPLEMENTED == rv) {
status = nsICMSMessageErrors::VERIFY_ERROR_PROCESSING;
}
}
else {
PRBool signing_cert_without_email_address;
if (MimeCMSHeadersAndCertsMatch(data->self, data->content_info, &signing_cert_without_email_address, &data->sender_addr))
{
status = nsICMSMessageErrors::SUCCESS;
}
else
{
if (signing_cert_without_email_address) {
status = nsICMSMessageErrors::VERIFY_CERT_WITHOUT_ADDRESS;
}
else {
status = nsICMSMessageErrors::VERIFY_HEADER_MISMATCH;
}
}
}
MimeCMSGetFromSender(data->self,
from_addr, from_name,
sender_addr, sender_name);
data->content_info->GetSignerCert(getter_AddRefs(certOfInterest));
MimeCMSRequestAsyncSignatureVerification(data->content_info,
from_addr, from_name,
sender_addr, sender_name,
data->smimeHeaderSink, aRelativeNestLevel,
nsnull, 0);
}
}
@ -637,14 +683,6 @@ MimeCMS_eof (void *crypto_closure, PRBool abort_p)
certOfInterest
);
}
else
{
data->smimeHeaderSink->SignedStatus(
aRelativeNestLevel,
status,
certOfInterest
);
}
return 0;
}
@ -658,153 +696,9 @@ MimeCMS_free (void *crypto_closure)
delete data;
}
char *
MimeCMS_MakeSAURL(MimeObject *obj)
{
char *stamp_url = 0;
/* Skip over any crypto objects which lie between us and a message/rfc822.
But if we reach an object that isn't a crypto object or a message/rfc822
then stop on the crypto object *before* it. That is, leave `obj' set to
either a crypto object, or a message/rfc822, but leave it set to the
innermost message/rfc822 above a consecutive run of crypto objects.
*/
while (1)
{
if (!obj->parent)
break;
else if (mime_typep (obj->parent, (MimeObjectClass *) &mimeMessageClass))
{
obj = obj->parent;
break;
}
#if 0 // XXX Fix later XXX //
else if (!mime_typep (obj->parent, (MimeObjectClass *) &mimeEncryptedClass) && !mime_typep (obj->parent,
(MimeObjectClass *) &mimeMultipartSignedClass))
#endif
else if (!mime_typep (obj->parent, (MimeObjectClass *) &mimeEncryptedClass))
{
break;
}
obj = obj->parent;
NS_ASSERTION(obj, "1.2 <mscott@netscape.com> 01 Nov 2001 17:59");
}
if (obj->options)
{
const char *base_url = obj->options->url;
char *id = (base_url ? mime_part_address (obj) : 0);
char *url = (id && base_url
? mime_set_url_part(base_url, id, PR_TRUE)
: 0);
char *url2 = (url ? nsEscape(url, url_XAlphas) : 0);
PR_FREEIF(id);
PR_FREEIF(url);
stamp_url = (char *) PR_MALLOC(strlen(url2) + 50);
if (stamp_url)
{
PL_strcpy(stamp_url, "about:security?advisor=");
PL_strcat(stamp_url, url2);
}
PR_FREEIF(url2);
}
return stamp_url;
}
static char *
MimeCMS_generate (void *crypto_closure)
{
MimeCMSdata *data = (MimeCMSdata *) crypto_closure;
PRBool self_signed_p = PR_FALSE;
PRBool self_encrypted_p = PR_FALSE;
PRBool union_encrypted_p = PR_FALSE;
PRBool good_p = PR_FALSE;
PRBool unverified_p = PR_FALSE;
if (!data || !data->output_fn) return 0;
if (data->content_info)
{
data->content_info->ContentIsSigned(&self_signed_p);
data->content_info->ContentIsEncrypted(&self_encrypted_p);
union_encrypted_p = (self_encrypted_p || data->parent_is_encrypted_p);
if (self_signed_p)
{
PR_SetError(0, 0);
good_p = data->content_info->VerifySignature();
if (!good_p)
{
if (!data->verify_error)
data->verify_error = PR_GetError();
if (data->verify_error >= 0)
data->verify_error = -1;
}
else
{
PRBool signing_cert_without_email_address;
good_p = MimeCMSHeadersAndCertsMatch(data->self, data->content_info, &signing_cert_without_email_address,
&data->sender_addr);
if (!good_p && !data->verify_error) {
// data->verify_error = SEC_ERROR_CERT_ADDR_MISMATCH; XXX Fix later XXX //
data->verify_error = -1;
}
}
}
#if 0
if (SEC_PKCS7ContainsCertsOrCrls(data->content_info))
{
/* #### call libsec telling it to import the certs */
}
#endif
/* Don't free these yet -- keep them around for the lifetime of the
MIME object, so that we can get at the security info of sub-parts
of the currently-displayed message. */
#if 0
SEC_PKCS7DestroyContentInfo(data->content_info);
data->content_info = 0;
#endif /* 0 */
}
else
{
/* No content info? Something's horked. Guess. */
self_encrypted_p = PR_TRUE;
union_encrypted_p = PR_TRUE;
if (!data->decode_error && !data->verify_error)
data->decode_error = -1;
}
unverified_p = data->self->options->missing_parts;
if (data->self && data->self->parent) {
mime_set_crypto_stamp(data->self->parent, self_signed_p, self_encrypted_p);
}
{
char *stamp_url = 0, *result = nsnull;
if (data->self)
{
if (unverified_p && data->self->options) {
// stamp_url = IMAP_CreateReloadAllPartsUrl(data->self->options->url); XXX Fix later XXX //
stamp_url = nsnull;
}
else {
stamp_url = MimeCMS_MakeSAURL(data->self);
}
}
result =
MimeHeaders_make_crypto_stamp (union_encrypted_p,
self_signed_p,
good_p,
unverified_p,
data->parent_holds_stamp_p,
stamp_url);
PR_FREEIF(stamp_url);
return result;
}
return nsnull;
}

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

@ -54,14 +54,6 @@ typedef struct MimeEncryptedCMS MimeEncryptedCMS;
struct MimeEncryptedCMSClass {
MimeEncryptedClass encrypted;
/* Callback used to access the SEC_PKCS7ContentInfo of this object. */
void (*get_content_info) (MimeObject *self,
nsICMSMessage **content_info_ret,
char **sender_email_addr_return,
PRInt32 *decode_error_ret,
PRInt32 *verify_error_ret,
PRBool * ci_is_encrypted);
};
extern MimeEncryptedCMSClass mimeEncryptedCMSClass;

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

@ -1160,201 +1160,6 @@ mime_crypto_stamped_p(MimeObject *obj)
return PR_FALSE;
}
/* Tells whether the given MimeObject is a message which has been encrypted
or signed. (Helper for MIME_GetMessageCryptoState()).
*/
void
mime_get_crypto_state (MimeObject *obj,
PRBool *signed_ret,
PRBool *encrypted_ret,
PRBool *signed_ok_ret,
PRBool *encrypted_ok_ret)
{
PRBool signed_p, encrypted_p;
if (signed_ret) *signed_ret = PR_FALSE;
if (encrypted_ret) *encrypted_ret = PR_FALSE;
if (signed_ok_ret) *signed_ok_ret = PR_FALSE;
if (encrypted_ok_ret) *encrypted_ok_ret = PR_FALSE;
NS_ASSERTION(obj, "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
if (!obj) return;
if (!mime_typep (obj, (MimeObjectClass *) &mimeMessageClass))
return;
signed_p = ((MimeMessage *) obj)->crypto_msg_signed_p;
encrypted_p = ((MimeMessage *) obj)->crypto_msg_encrypted_p;
if (signed_ret)
*signed_ret = signed_p;
if (encrypted_ret)
*encrypted_ret = encrypted_p;
if ((signed_p || encrypted_p) &&
(signed_ok_ret || encrypted_ok_ret))
{
nsICMSMessage *encrypted_ci = 0;
nsICMSMessage *signed_ci = 0;
PRInt32 decode_error = 0, verify_error = 0;
char *addr = mime_part_address(obj);
mime_find_security_info_of_part(addr, obj,
&encrypted_ci,
&signed_ci,
0, /* email_addr */
&decode_error, &verify_error);
if (encrypted_p && encrypted_ok_ret)
*encrypted_ok_ret = (encrypted_ci && decode_error >= 0);
if (signed_p && signed_ok_ret)
*signed_ok_ret = (verify_error >= 0 && decode_error >= 0);
PR_FREEIF(addr);
}
}
/* How the crypto code tells the MimeMessage object what the crypto stamp
on it says. */
void
mime_set_crypto_stamp(MimeObject *obj, PRBool signed_p, PRBool encrypted_p)
{
if (!obj) return;
if (mime_typep (obj, (MimeObjectClass *) &mimeMessageClass))
{
MimeMessage *msg = (MimeMessage *) obj;
if (!msg->crypto_msg_signed_p)
msg->crypto_msg_signed_p = signed_p;
if (!msg->crypto_msg_encrypted_p)
msg->crypto_msg_encrypted_p = encrypted_p;
/* If the `decrypt_p' option is on, record whether any decryption has
actually occurred. */
if (encrypted_p &&
obj->options &&
obj->options->decrypt_p &&
obj->options->state)
{
/* decrypt_p and write_html_p are incompatible. */
NS_ASSERTION(!obj->options->write_html_p, "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
obj->options->state->decrypted_p = PR_TRUE;
}
return; /* continue up the tree? I think that's not a good idea. */
}
if (obj->parent)
mime_set_crypto_stamp(obj->parent, signed_p, encrypted_p);
}
/* Given a part ID, looks through the MimeObject tree for a sub-part whose ID
number matches; if one is found, and if it represents a PKCS7-encrypted
object, returns information about the security status of that object.
`part' is not a URL -- it's of the form "1.3.5" and is interpreted relative
to the `obj' argument.
Returned values:
void **pkcs7_content_info_return
this is the SEC_PKCS7ContentInfo* of the object.
int32 *decode_error_return
this is the error code, if any, that the security library returned
while trying to parse the PKCS7 data (if this is negative, then it
probably means the message was corrupt in some way.)
int32 *verify_error_return
this is the error code, if any, that the security library returned
while trying to decrypt or verify or otherwise validate the data
(if this is negative, it might mean the message was corrupt, or might
mean the signature didn't match, or the cert was expired, or...)
*/
void
mime_find_security_info_of_part(const char *part, MimeObject *obj,
nsICMSMessage **pkcs7_encrypted_content_info_return,
nsICMSMessage **pkcs7_signed_content_info_return,
char **sender_email_addr_return,
PRInt32 *decode_error_return,
PRInt32 *verify_error_return)
{
obj = mime_address_to_part(part, obj);
*pkcs7_encrypted_content_info_return = 0;
*pkcs7_signed_content_info_return = 0;
*decode_error_return = 0;
*verify_error_return = 0;
if (sender_email_addr_return)
*sender_email_addr_return = 0;
if (!obj)
return;
/* If someone asks for the security info of a message/rfc822 object,
instead give them the security info of its child (the body of the
message.)
*/
if (mime_typep (obj, (MimeObjectClass *) &mimeMessageClass))
{
MimeContainer *cont = (MimeContainer *) obj;
if (cont->nchildren >= 1)
{
NS_ASSERTION(cont->nchildren == 1, "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
obj = cont->children[0];
}
}
while (obj &&
(mime_typep(obj, (MimeObjectClass *) &mimeEncryptedCMSClass) ||
mime_typep(obj, (MimeObjectClass *) &mimeMultipartSignedCMSClass)))
{
nsICMSMessage *ci = 0;
PRInt32 decode_error = 0, verify_error = 0;
PRBool ci_is_encrypted = PR_FALSE;
char *sender = 0;
if (mime_typep(obj, (MimeObjectClass *) &mimeEncryptedCMSClass)) {
(((MimeEncryptedCMSClass *) (obj->clazz))
->get_content_info) (obj, &ci, &sender, &decode_error, &verify_error, &ci_is_encrypted);
} else if (mime_typep(obj,
(MimeObjectClass *) &mimeMultipartSignedCMSClass)) {
(((MimeMultipartSignedCMSClass *) (obj->clazz))
->get_content_info) (obj, &ci, &sender, &decode_error, &verify_error, &ci_is_encrypted);
}
if (ci) {
if (ci_is_encrypted) {
*pkcs7_encrypted_content_info_return = ci;
} else {
*pkcs7_signed_content_info_return = ci;
}
}
if (sender_email_addr_return)
*sender_email_addr_return = sender;
else
PR_FREEIF(sender);
if (*decode_error_return >= 0)
*decode_error_return = decode_error;
if (*verify_error_return >= 0)
*verify_error_return = verify_error;
NS_ASSERTION(mime_typep(obj, (MimeObjectClass *) &mimeContainerClass) &&
((MimeContainer *) obj)->nchildren <= 1, "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
obj = ((((MimeContainer *) obj)->nchildren > 0)
? ((MimeContainer *) obj)->children[0]
: 0);
}
}
#endif // ENABLE_SMIME
/* Puts a part-number into a URL. If append_p is true, then the part number

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

@ -342,20 +342,6 @@ extern char *mime_find_content_type_of_part(const char *part, MimeObject *obj);
extern int mime_parse_url_options(const char *url, MimeDisplayOptions *);
#ifdef ENABLE_SMIME
/* Given a part ID, looks through the MimeObject tree for a sub-part whose ID
number matches; if one is found, and if it represents a PKCS7-encrypted
object, returns information about the security status of that object.
`part' is not a URL -- it's of the form "1.3.5" and is interpreted relative
to the `obj' argument.
*/
extern void mime_find_security_info_of_part(const char *part, MimeObject *obj,
nsICMSMessage **cms_encrypt_content_info_return,
nsICMSMessage **cms_sign_content_info_return,
char **sender_email_addr_return,
PRInt32 *decode_error_return,
PRInt32 *verify_error_return);
/* Asks whether the given object is one of the cryptographically signed
or encrypted objects that we know about. (MimeMessageClass uses this

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

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Kai Engert <kengert@redhat.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -68,9 +69,6 @@ static int MimeMultCMS_sig_eof (void *, PRBool);
static int MimeMultCMS_sig_init (void *, MimeObject *, MimeHeaders *);
static char * MimeMultCMS_generate (void *);
static void MimeMultCMS_free (void *);
static void MimeMultCMS_get_content_info (MimeObject *,
nsICMSMessage **,
char **, PRInt32 *, PRInt32 *, PRBool *);
extern int SEC_ERROR_CERT_ADDR_MISMATCH;
@ -91,8 +89,6 @@ MimeMultipartSignedCMSClassInitialize(MimeMultipartSignedCMSClass *clazz)
sclass->crypto_generate_html = MimeMultCMS_generate;
sclass->crypto_free = MimeMultCMS_free;
clazz->get_content_info = MimeMultCMS_get_content_info;
PR_ASSERT(!oclass->class_initialized);
return 0;
}
@ -111,8 +107,7 @@ typedef struct MimeMultCMSdata
nsCOMPtr<nsICMSDecoder> sig_decoder_context;
nsCOMPtr<nsICMSMessage> content_info;
char *sender_addr;
PRInt32 decode_error;
PRInt32 verify_error;
PRBool decoding_failed;
unsigned char* item_data;
PRUint32 item_len;
MimeObject *self;
@ -123,8 +118,7 @@ typedef struct MimeMultCMSdata
MimeMultCMSdata()
:hash_type(0),
sender_addr(nsnull),
decode_error(0),
verify_error(0),
decoding_failed(PR_FALSE),
item_data(nsnull),
self(nsnull),
parent_is_encrypted_p(PR_FALSE),
@ -147,38 +141,22 @@ typedef struct MimeMultCMSdata
}
} MimeMultCMSdata;
static void
MimeMultCMS_get_content_info(MimeObject *obj,
nsICMSMessage **content_info_ret,
char **sender_email_addr_return,
PRInt32 *decode_error_ret,
PRInt32 *verify_error_ret,
PRBool *ci_is_encrypted)
{
MimeMultipartSigned *msig = (MimeMultipartSigned *) obj;
if (msig && msig->crypto_closure)
{
MimeMultCMSdata *data = (MimeMultCMSdata *) msig->crypto_closure;
*decode_error_ret = data->decode_error;
*verify_error_ret = data->verify_error;
*content_info_ret = data->content_info;
*ci_is_encrypted = PR_FALSE;
if (sender_email_addr_return)
*sender_email_addr_return = (data->sender_addr
? nsCRT::strdup(data->sender_addr)
: 0);
}
}
/* #### MimeEncryptedCMS and MimeMultipartSignedCMS have a sleazy,
incestuous, dysfunctional relationship. */
extern PRBool MimeEncryptedCMS_encrypted_p (MimeObject *obj);
extern void MimeCMSGetFromSender(MimeObject *obj,
nsXPIDLCString &from_addr,
nsXPIDLCString &from_name,
nsXPIDLCString &sender_addr,
nsXPIDLCString &sender_name);
extern PRBool MimeCMSHeadersAndCertsMatch(MimeObject *obj,
nsICMSMessage *,
PRBool *signing_cert_without_email_address,
char **);
nsICMSMessage *,
PRBool *signing_cert_without_email_address);
extern void MimeCMSRequestAsyncSignatureVerification(nsICMSMessage *aCMSMsg,
const char *aFromAddr, const char *aFromName,
const char *aSenderAddr, const char *aSenderName,
nsIMsgSMIMEHeaderSink *aHeaderSink, PRInt32 aMimeNestingLevel,
unsigned char* item_data, PRUint32 item_len);
extern char *MimeCMS_MakeSAURL(MimeObject *obj);
extern char *IMAP_CreateReloadAllPartsUrl(const char *url);
extern int MIMEGetRelativeCryptoNestLevel(MimeObject *obj);
@ -233,16 +211,6 @@ MimeMultCMS_init (MimeObject *obj)
PR_SetError(0,0);
if (!data->decode_error)
{
data->decode_error = PR_GetError();
if (data->decode_error)
{
delete data;
return 0;
}
}
data->parent_holds_stamp_p =
(obj->parent && mime_crypto_stamped_p(obj->parent));
@ -319,10 +287,8 @@ MimeMultCMS_data_hash (char *buf, PRInt32 size, void *crypto_closure)
}
PR_SetError(0, 0);
data->data_hash_context->Update((unsigned char *) buf, size);
if (!data->verify_error) {
data->verify_error = PR_GetError();
}
nsresult rv = data->data_hash_context->Update((unsigned char *) buf, size);
data->decoding_failed = NS_FAILED(rv);
return 0;
}
@ -345,10 +311,6 @@ MimeMultCMS_data_eof (void *crypto_closure, PRBool abort_p)
memcpy(data->item_data, hashString.get(), data->item_len);
if (!data->verify_error) {
data->verify_error = PR_GetError();
}
// Release our reference to nsICryptoHash //
data->data_hash_context = 0;
@ -408,12 +370,7 @@ MimeMultCMS_sig_hash (char *buf, PRInt32 size, void *crypto_closure)
}
rv = data->sig_decoder_context->Update(buf, size);
if (NS_FAILED(rv)) {
if (!data->verify_error)
data->verify_error = PR_GetError();
if (data->verify_error >= 0)
data->verify_error = -1;
}
data->decoding_failed = NS_FAILED(rv);
return 0;
}
@ -438,10 +395,6 @@ MimeMultCMS_sig_eof (void *crypto_closure, PRBool abort_p)
// Release our reference to nsICMSDecoder //
data->sig_decoder_context = 0;
if (!data->content_info && !data->verify_error) {
data->verify_error = PR_GetError();
}
}
return 0;
@ -460,125 +413,71 @@ static char *
MimeMultCMS_generate (void *crypto_closure)
{
MimeMultCMSdata *data = (MimeMultCMSdata *) crypto_closure;
PRBool signed_p = PR_TRUE;
PRBool good_p = PR_FALSE;
PRBool encrypted_p;
PRBool unverified_p = PR_FALSE;
nsresult rv;
if (!data) return 0;
encrypted_p = data->parent_is_encrypted_p;
PRInt32 signature_status = nsICMSMessageErrors::GENERAL_ERROR;
nsCOMPtr<nsIX509Cert> signerCert;
int aRelativeNestLevel = MIMEGetRelativeCryptoNestLevel(data->self);
unverified_p = data->self->options->missing_parts;
if (aRelativeNestLevel < 0)
return nsnull;
if (unverified_p)
PRInt32 maxNestLevel = 0;
if (data->smimeHeaderSink && aRelativeNestLevel >= 0)
{
data->smimeHeaderSink->MaxWantedNesting(&maxNestLevel);
if (aRelativeNestLevel > maxNestLevel)
return nsnull;
}
if (data->self->options->missing_parts)
{
// We were not given all parts of the message.
// We are therefore unable to verify correctness of the signature.
signature_status = nsICMSMessageErrors::VERIFY_NOT_YET_ATTEMPTED;
if (data->smimeHeaderSink)
data->smimeHeaderSink->SignedStatus(aRelativeNestLevel,
nsICMSMessageErrors::VERIFY_NOT_YET_ATTEMPTED,
nsnull);
return nsnull;
}
else
if (!data->content_info)
{
/* No content_info at all -- since we're inside a multipart/signed,
that means that we've either gotten a message that was truncated
before the signature part, or we ran out of memory, or something
awful has happened.
*/
return nsnull;
}
nsXPIDLCString from_addr;
nsXPIDLCString from_name;
nsXPIDLCString sender_addr;
nsXPIDLCString sender_name;
MimeCMSGetFromSender(data->self,
from_addr, from_name,
sender_addr, sender_name);
MimeCMSRequestAsyncSignatureVerification(data->content_info,
from_addr, from_name,
sender_addr, sender_name,
data->smimeHeaderSink, aRelativeNestLevel,
data->item_data, data->item_len);
if (data->content_info)
{
rv = data->content_info->VerifyDetachedSignature(data->item_data, data->item_len);
data->content_info->GetSignerCert(getter_AddRefs(signerCert));
if (NS_FAILED(rv)) {
if (NS_ERROR_MODULE_SECURITY == NS_ERROR_GET_MODULE(rv)) {
signature_status = NS_ERROR_GET_CODE(rv);
}
if (!data->verify_error) {
data->verify_error = PR_GetError();
}
if (data->verify_error >= 0) {
data->verify_error = -1;
}
} else {
PRBool signing_cert_without_email_address;
good_p = MimeCMSHeadersAndCertsMatch(data->self,
data->content_info,
&signing_cert_without_email_address,
&data->sender_addr);
if (!good_p) {
if (signing_cert_without_email_address) {
signature_status = nsICMSMessageErrors::VERIFY_CERT_WITHOUT_ADDRESS;
}
else {
signature_status = nsICMSMessageErrors::VERIFY_HEADER_MISMATCH;
}
if (!data->verify_error) {
data->verify_error = -1;
// XXX Fix this data->verify_error = SEC_ERROR_CERT_ADDR_MISMATCH; XXX //
}
}
else
{
signature_status = nsICMSMessageErrors::SUCCESS;
}
}
#if 0 // XXX Fix this. What do we do here? //
if (SEC_CMSContainsCertsOrCrls(data->content_info))
{
/* #### call libsec telling it to import the certs */
}
#endif
/* Don't free these yet -- keep them around for the lifetime of the
MIME object, so that we can get at the security info of sub-parts
of the currently-displayed message. */
#if 0
SEC_CMSDestroyContentInfo(data->content_info);
data->content_info = 0;
#endif /* 0 */
}
else
{
/* No content_info at all -- since we're inside a multipart/signed,
that means that we've either gotten a message that was truncated
before the signature part, or we ran out of memory, or something
awful has happened. Anyway, it sure ain't good_p.
*/
}
PRInt32 maxNestLevel = 0;
if (data->smimeHeaderSink) {
if (aRelativeNestLevel >= 0) {
data->smimeHeaderSink->MaxWantedNesting(&maxNestLevel);
if (aRelativeNestLevel <= maxNestLevel)
{
data->smimeHeaderSink->SignedStatus(aRelativeNestLevel, signature_status, signerCert);
}
}
}
if (data->self && data->self->parent) {
mime_set_crypto_stamp(data->self->parent, signed_p, encrypted_p);
}
{
char *stamp_url = 0, *result;
if (data->self)
{
if (unverified_p && data->self->options) {
// XXX Fix this stamp_url = IMAP_CreateReloadAllPartsUrl(data->self->options->url); XXX //
} else {
stamp_url = MimeCMS_MakeSAURL(data->self);
}
}
result =
MimeHeaders_make_crypto_stamp (encrypted_p, signed_p, good_p,
unverified_p,
data->parent_holds_stamp_p,
stamp_url);
PR_FREEIF(stamp_url);
return result;
}
return nsnull;
}

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

@ -53,14 +53,6 @@ typedef struct MimeMultipartSignedCMS MimeMultipartSignedCMS;
struct MimeMultipartSignedCMSClass {
MimeMultipartSignedClass msigned;
/* Callback used to access the SEC_CMSContentInfo of this object. */
void (*get_content_info) (MimeObject *self,
nsICMSMessage **content_info_ret,
char **sender_email_addr_return,
PRInt32 *decode_error_ret,
PRInt32 *verify_error_ret,
PRBool * ci_is_encrypted);
};
extern MimeMultipartSignedCMSClass mimeMultipartSignedCMSClass;