Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions | Variables
mimemcms.cpp File Reference
#include "nsICMSMessage.h"
#include "nsICMSMessageErrors.h"
#include "nsICMSDecoder.h"
#include "nsICryptoHash.h"
#include "mimemcms.h"
#include "mimecryp.h"
#include "nsMimeTypes.h"
#include "nspr.h"
#include "nsMimeStringResources.h"
#include "mimemsg.h"
#include "mimemoz2.h"
#include "nsIURI.h"
#include "nsIMsgWindow.h"
#include "nsIMsgMailNewsUrl.h"
#include "nsIMimeMiscStatus.h"
#include "nsIMsgSMIMEHeaderSink.h"
#include "nsCOMPtr.h"
#include "nsIX509Cert.h"

Go to the source code of this file.

Classes

struct  MimeMultCMSdata

Defines

#define MIME_SUPERCLASS   mimeMultipartSignedClass

Typedefs

typedef struct MimeMultCMSdata MimeMultCMSdata

Functions

 MimeDefClass (MimeMultipartSignedCMS, MimeMultipartSignedCMSClass, mimeMultipartSignedCMSClass,&MIME_SUPERCLASS)
static int MimeMultipartSignedCMS_initialize (MimeObject *)
static voidMimeMultCMS_init (MimeObject *)
static int MimeMultCMS_data_hash (char *, PRInt32, void *)
static int MimeMultCMS_sig_hash (char *, PRInt32, void *)
static int MimeMultCMS_data_eof (void *, PRBool)
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 int MimeMultipartSignedCMSClassInitialize (MimeMultipartSignedCMSClass *clazz)
PRBool MimeEncryptedCMS_encrypted_p (MimeObject *obj)
void MimeCMSGetFromSender (MimeObject *obj, nsXPIDLCString &from_addr, nsXPIDLCString &from_name, nsXPIDLCString &sender_addr, nsXPIDLCString &sender_name)
PRBool MimeCMSHeadersAndCertsMatch (MimeObject *obj, nsICMSMessage *, PRBool *signing_cert_without_email_address)
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)
char * MimeCMS_MakeSAURL (MimeObject *obj)
char * IMAP_CreateReloadAllPartsUrl (const char *url)
int MIMEGetRelativeCryptoNestLevel (MimeObject *obj)

Variables

int SEC_ERROR_CERT_ADDR_MISMATCH

Define Documentation

Definition at line 58 of file mimemcms.cpp.


Typedef Documentation


Function Documentation

char* IMAP_CreateReloadAllPartsUrl ( const char *  url)
char* MimeCMS_MakeSAURL ( MimeObject obj)
void MimeCMSGetFromSender ( MimeObject obj,
nsXPIDLCString from_addr,
nsXPIDLCString from_name,
nsXPIDLCString sender_addr,
nsXPIDLCString sender_name 
)

Definition at line 524 of file mimecms.cpp.

{
  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);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool MimeCMSHeadersAndCertsMatch ( MimeObject obj,
nsICMSMessage ,
PRBool signing_cert_without_email_address 
)
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 
)

Definition at line 568 of file mimecms.cpp.

{
  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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 155 of file mimecms.cpp.

{
  PRBool encrypted;

  if (!obj) return PR_FALSE;
  if (mime_typep(obj, (MimeObjectClass *) &mimeEncryptedCMSClass))
  {
    MimeEncrypted *enc = (MimeEncrypted *) obj;
    MimeCMSdata *data = (MimeCMSdata *) enc->crypto_closure;
    if (!data || !data->content_info) return PR_FALSE;
                data->content_info->ContentIsEncrypted(&encrypted);
          return encrypted;
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 347 of file mimecms.cpp.

{
  /*
    the part id of any mimeobj is mime_part_address(obj)
    our currently displayed crypto part is obj
    the part shown as the toplevel object in the current window is
        obj->options->part_to_load
        possibly stored in the toplevel object only ???
        but hopefully all nested mimeobject point to the same displayooptions

    we need to find out the nesting level of our currently displayed crypto object
    wrt the shown part in the toplevel window
  */

  // if we are showing the toplevel message, aTopMessageNestLevel == 0
  int aTopMessageNestLevel = 0;
  MimeObject *aTopShownObject = nsnull;
  if (obj && obj->options->part_to_load) {
    PRBool aAlreadyFoundTop = PR_FALSE;
    for (MimeObject *walker = obj; walker; walker = walker->parent) {
      if (aAlreadyFoundTop) {
        if (!mime_typep(walker, (MimeObjectClass *) &mimeEncryptedClass)
            && !mime_typep(walker, (MimeObjectClass *) &mimeMultipartSignedClass)) {
          ++aTopMessageNestLevel;
        }
      }
      if (!aAlreadyFoundTop && !strcmp(mime_part_address(walker), walker->options->part_to_load)) {
        aAlreadyFoundTop = PR_TRUE;
        aTopShownObject = walker;
      }
      if (!aAlreadyFoundTop && !walker->parent) {
        // 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;
      }
    }
  }

  PRBool CryptoObjectIsChildOfTopShownObject = PR_FALSE;
  if (!aTopShownObject) {
    // no sub part specified, top message is displayed, and
    // our crypto object is definitively a child of it
    CryptoObjectIsChildOfTopShownObject = PR_TRUE;
  }

  // if we are the child of the topmost message, aCryptoPartNestLevel == 1
  int aCryptoPartNestLevel = 0;
  if (obj) {
    for (MimeObject *walker = obj; walker; walker = walker->parent) {
      // Crypto mime objects are transparent wrt nesting.
      if (!mime_typep(walker, (MimeObjectClass *) &mimeEncryptedClass)
          && !mime_typep(walker, (MimeObjectClass *) &mimeMultipartSignedClass)) {
        ++aCryptoPartNestLevel;
      }
      if (aTopShownObject && walker->parent == aTopShownObject) {
        CryptoObjectIsChildOfTopShownObject = PR_TRUE;
      }
    }
  }

  if (!CryptoObjectIsChildOfTopShownObject) {
    return -1;
  }

  return aCryptoPartNestLevel - aTopMessageNestLevel;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeMultCMS_data_eof ( void crypto_closure,
PRBool  abort_p 
) [static]

Definition at line 297 of file mimemcms.cpp.

{
  MimeMultCMSdata *data = (MimeMultCMSdata *) crypto_closure;
  if (!data || !data->data_hash_context) {
    return -1;
  }

  nsCAutoString hashString;
  data->data_hash_context->Finish(PR_FALSE, hashString);
  PR_SetError(0, 0);
  
  data->item_len  = hashString.Length();
  data->item_data = new unsigned char[data->item_len];
  if (!data->item_data) return MIME_OUT_OF_MEMORY;
  
  memcpy(data->item_data, hashString.get(), data->item_len);

  // Release our reference to nsICryptoHash //
  data->data_hash_context = 0;

  /* At this point, data->item.data contains a digest for the first part.
   When we process the signature, the security library will compare this
   digest to what's in the signature object. */

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeMultCMS_data_hash ( char *  buf,
PRInt32  size,
void crypto_closure 
) [static]

Definition at line 282 of file mimemcms.cpp.

{
  MimeMultCMSdata *data = (MimeMultCMSdata *) crypto_closure;
  if (!data || !data->data_hash_context) {
    return -1;
  }

  PR_SetError(0, 0);
  nsresult rv = data->data_hash_context->Update((unsigned char *) buf, size);
  data->decoding_failed = NS_FAILED(rv);

  return 0;
}

Here is the caller graph for this function:

static void MimeMultCMS_free ( void crypto_closure) [static]

Definition at line 404 of file mimemcms.cpp.

{
  MimeMultCMSdata *data = (MimeMultCMSdata *) crypto_closure;
  if (!data) return;

  delete data;
}

Here is the caller graph for this function:

static char * MimeMultCMS_generate ( void crypto_closure) [static]

Definition at line 413 of file mimemcms.cpp.

{
  MimeMultCMSdata *data = (MimeMultCMSdata *) crypto_closure;
  PRBool encrypted_p;
  if (!data) return 0;
  encrypted_p = data->parent_is_encrypted_p;
  nsCOMPtr<nsIX509Cert> signerCert;

  int aRelativeNestLevel = MIMEGetRelativeCryptoNestLevel(data->self);

  if (aRelativeNestLevel < 0)
    return nsnull;

  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.
    
    if (data->smimeHeaderSink)
      data->smimeHeaderSink->SignedStatus(aRelativeNestLevel, 
                                          nsICMSMessageErrors::VERIFY_NOT_YET_ATTEMPTED, 
                                          nsnull);
    return nsnull;
  }

  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)
  {
#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
  }

  return nsnull;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void * MimeMultCMS_init ( MimeObject obj) [static]

Definition at line 165 of file mimemcms.cpp.

{
  MimeHeaders *hdrs = obj->headers;
  MimeMultCMSdata *data = 0;
  char *ct, *micalg;
  PRInt16 hash_type;
  nsresult rv;

  ct = MimeHeaders_get (hdrs, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);
  if (!ct) return 0; /* #### bogus message?  out of memory? */
  micalg = MimeHeaders_get_parameter (ct, PARAM_MICALG, NULL, NULL);
  PR_Free(ct);
  ct = 0;
  if (!micalg) return 0; /* #### bogus message?  out of memory? */

  if (!nsCRT::strcasecmp(micalg, PARAM_MICALG_MD5) ||
      !nsCRT::strcasecmp(micalg, PARAM_MICALG_MD5_2))
    hash_type = nsICryptoHash::MD5;
  else if (!nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1) ||
       !nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1_2) ||
       !nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1_3) ||
       !nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1_4) ||
       !nsCRT::strcasecmp(micalg, PARAM_MICALG_SHA1_5))
    hash_type = nsICryptoHash::SHA1;
  else if (!nsCRT::strcasecmp(micalg, PARAM_MICALG_MD2))
    hash_type = nsICryptoHash::MD2;
  else
    hash_type = -1;

  PR_Free(micalg);
  micalg = 0;

  if (hash_type == -1) return 0; /* #### bogus message? */

  data = new MimeMultCMSdata;
  if (!data)
    return 0;

  data->self = obj;
  data->hash_type = hash_type;

  data->data_hash_context = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
  if (NS_FAILED(rv)) return 0;

  rv = data->data_hash_context->Init(data->hash_type);
  if (NS_FAILED(rv)) return 0;

  PR_SetError(0,0);

  data->parent_holds_stamp_p =
  (obj->parent && mime_crypto_stamped_p(obj->parent));

  data->parent_is_encrypted_p =
  (obj->parent && MimeEncryptedCMS_encrypted_p (obj->parent));

  /* If the parent of this object is a crypto-blob, then it's the grandparent
   who would have written out the headers and prepared for a stamp...
   (This s##t s$%#s.)
   */
  if (data->parent_is_encrypted_p &&
    !data->parent_holds_stamp_p &&
    obj->parent && obj->parent->parent)
  data->parent_holds_stamp_p =
    mime_crypto_stamped_p (obj->parent->parent);

  mime_stream_data *msd = (mime_stream_data *) (data->self->options->stream_closure);
  if (msd)
  {
    nsIChannel *channel = msd->channel;  // note the lack of ref counting...
    if (channel)
    {
      nsCOMPtr<nsIURI> uri;
      nsCOMPtr<nsIMsgWindow> msgWindow;
      nsCOMPtr<nsIMsgHeaderSink> headerSink;
      nsCOMPtr<nsIMsgMailNewsUrl> msgurl;
      nsCOMPtr<nsISupports> securityInfo;
      channel->GetURI(getter_AddRefs(uri));
      if (uri)
      {
        nsCAutoString urlSpec;
        rv = uri->GetSpec(urlSpec);

        // We only want to update the UI if the current mime transaction
        // is intended for display.
        // If the current transaction is intended for background processing,
        // we can learn that by looking at the additional header=filter
        // string contained in the URI.
        //
        // If we find something, we do not set smimeHeaderSink,
        // which will prevent us from giving UI feedback.
        //
        // If we do not find header=filter, we assume the result of the
        // processing will be shown in the UI.
        
        if (!strstr(urlSpec.get(), "?header=filter") &&
            !strstr(urlSpec.get(), "&header=filter")&&
            !strstr(urlSpec.get(), "?header=attach") &&
            !strstr(urlSpec.get(), "&header=attach"))
        {
          msgurl = do_QueryInterface(uri);
          if (msgurl)
            msgurl->GetMsgWindow(getter_AddRefs(msgWindow));
          if (msgWindow)
            msgWindow->GetMsgHeaderSink(getter_AddRefs(headerSink));
          if (headerSink)
            headerSink->GetSecurityInfo(getter_AddRefs(securityInfo));
          if (securityInfo)
            data->smimeHeaderSink = do_QueryInterface(securityInfo);
         }
       }
    } // if channel
  } // if msd

  return data;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeMultCMS_sig_eof ( void crypto_closure,
PRBool  abort_p 
) [static]

Definition at line 379 of file mimemcms.cpp.

{
  MimeMultCMSdata *data = (MimeMultCMSdata *) crypto_closure;

  if (!data) {
    return -1;
  }

  /* Hand an EOF to the crypto library.

   We save away the value returned and will use it later to emit a
   blurb about whether the signature validation was cool.
   */

  if (data->sig_decoder_context) {
    data->sig_decoder_context->Finish(getter_AddRefs(data->content_info));

    // Release our reference to nsICMSDecoder //
    data->sig_decoder_context = 0;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeMultCMS_sig_hash ( char *  buf,
PRInt32  size,
void crypto_closure 
) [static]

Definition at line 363 of file mimemcms.cpp.

{
  MimeMultCMSdata *data = (MimeMultCMSdata *) crypto_closure;
  nsresult rv;

  if (!data || !data->sig_decoder_context) {
    return -1;
  }

  rv = data->sig_decoder_context->Update(buf, size);
  data->decoding_failed = NS_FAILED(rv);

  return 0;
}

Here is the caller graph for this function:

static int MimeMultCMS_sig_init ( void crypto_closure,
MimeObject multipart_object,
MimeHeaders signature_hdrs 
) [static]

Definition at line 326 of file mimemcms.cpp.

{
  MimeMultCMSdata *data = (MimeMultCMSdata *) crypto_closure;
  char *ct;
  int status = 0;
  nsresult rv;

  if (!signature_hdrs) {
    return -1;
  }

  ct = MimeHeaders_get (signature_hdrs, HEADER_CONTENT_TYPE, PR_TRUE, PR_FALSE);

  /* Verify that the signature object is of the right type. */
  if (!ct || /* is not a signature type */
             (nsCRT::strcasecmp(ct, APPLICATION_XPKCS7_SIGNATURE) != 0
              && nsCRT::strcasecmp(ct, APPLICATION_PKCS7_SIGNATURE) != 0)) {
    status = -1; /* #### error msg about bogus message */
  }
  PR_FREEIF(ct);
  if (status < 0) return status;

  data->sig_decoder_context = do_CreateInstance(NS_CMSDECODER_CONTRACTID, &rv);
  if (NS_FAILED(rv)) return 0;

  rv = data->sig_decoder_context->Start(nsnull, nsnull);
  if (NS_FAILED(rv)) {
    status = PR_GetError();
    if (status >= 0) status = -1;
  }
  return status;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MimeMultipartSignedCMS_initialize ( MimeObject object) [static]

Definition at line 97 of file mimemcms.cpp.

{
  return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
}

Here is the caller graph for this function:


Variable Documentation