зеркало из https://github.com/mozilla/pjs.git
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 second checkin attempt
This commit is contained in:
Родитель
67587ec2e2
Коммит
c23d791bbb
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче