Example #1
0
int mutt_protect (HEADER *msg, char *keylist)
{
  BODY *pbody = NULL, *tmp_pbody = NULL;
  BODY *tmp_smime_pbody = NULL;
  BODY *tmp_pgp_pbody = NULL;
  int flags = (WithCrypto & APPLICATION_PGP)? msg->security: 0;
  int i;

  if (!WithCrypto)
    return -1;

  if (!(msg->security & (ENCRYPT | SIGN)))
    return 0;

  if ((msg->security & SIGN) && !crypt_valid_passphrase (msg->security))
    return (-1);

  if ((WithCrypto & APPLICATION_PGP) && ((msg->security & PGPINLINE) == PGPINLINE))
  {
    if ((msg->content->type != TYPETEXT) ||
        ascii_strcasecmp (msg->content->subtype, "plain"))
    {
      if ((i = query_quadoption (OPT_PGPMIMEAUTO,
              _("Inline PGP can't be used with attachments.  Revert to PGP/MIME?"))) != MUTT_YES)
      {
        mutt_error _("Mail not sent: inline PGP can't be used with attachments.");
        return -1;
      }
    }
    else
    {
      /* they really want to send it inline... go for it */
      if (!isendwin ()) mutt_endwin _("Invoking PGP...");
      pbody = crypt_pgp_traditional_encryptsign (msg->content, flags, keylist);
      if (pbody)
      {
        msg->content = pbody;
        return 0;
      }

      /* otherwise inline won't work...ask for revert */
      if ((i = query_quadoption (OPT_PGPMIMEAUTO, _("Message can't be sent inline.  Revert to using PGP/MIME?"))) != MUTT_YES)
      {
        mutt_error _("Mail not sent.");
        return -1;
      }
    }

    /* go ahead with PGP/MIME */
  }

  if (!isendwin ()) mutt_endwin (NULL);

  if ((WithCrypto & APPLICATION_SMIME))
    tmp_smime_pbody = msg->content;
  if ((WithCrypto & APPLICATION_PGP))
    tmp_pgp_pbody   = msg->content;

  if (option (OPTCRYPTUSEPKA) && (msg->security & SIGN))
    {
      /* Set sender (necessary for e.g. PKA).  */

      if ((WithCrypto & APPLICATION_SMIME)
	  && (msg->security & APPLICATION_SMIME))
	crypt_smime_set_sender (msg->env->from->mailbox);
      else if ((WithCrypto & APPLICATION_PGP)
	  && (msg->security & APPLICATION_PGP))
	crypt_pgp_set_sender (msg->env->from->mailbox);
    }

  if (msg->security & SIGN)
  {
    if ((WithCrypto & APPLICATION_SMIME)
        && (msg->security & APPLICATION_SMIME))
    {
      if (!(tmp_pbody = crypt_smime_sign_message (msg->content)))
	return -1;
      pbody = tmp_smime_pbody = tmp_pbody;
    }

    if ((WithCrypto & APPLICATION_PGP)
        && (msg->security & APPLICATION_PGP)
        && (!(flags & ENCRYPT) || option (OPTPGPRETAINABLESIG)))
    {
      if (!(tmp_pbody = crypt_pgp_sign_message (msg->content)))
        return -1;

      flags &= ~SIGN;
      pbody = tmp_pgp_pbody = tmp_pbody;
    }

    if (WithCrypto
        && (msg->security & APPLICATION_SMIME)
	&& (msg->security & APPLICATION_PGP))
    {
	/* here comes the draft ;-) */
    }
  }


  if (msg->security & ENCRYPT)
  {
    if ((WithCrypto & APPLICATION_SMIME)
        && (msg->security & APPLICATION_SMIME))
    {
      if (!(tmp_pbody = crypt_smime_build_smime_entity (tmp_smime_pbody,
                                                        keylist)))
      {
	/* signed ? free it! */
	return (-1);
      }
      /* free tmp_body if messages was signed AND encrypted ... */
      if (tmp_smime_pbody != msg->content && tmp_smime_pbody != tmp_pbody)
      {
	/* detatch and don't delete msg->content,
	   which tmp_smime_pbody->parts after signing. */
	tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
	msg->content->next = NULL;
	mutt_free_body (&tmp_smime_pbody);
      }
      pbody = tmp_pbody;
    }

    if ((WithCrypto & APPLICATION_PGP)
        && (msg->security & APPLICATION_PGP))
    {
      if (!(pbody = crypt_pgp_encrypt_message (tmp_pgp_pbody, keylist,
                                               flags & SIGN)))
      {

	/* did we perform a retainable signature? */
	if (flags != msg->security)
	{
	  /* remove the outer multipart layer */
	  tmp_pgp_pbody = mutt_remove_multipart (tmp_pgp_pbody);
	  /* get rid of the signature */
	  mutt_free_body (&tmp_pgp_pbody->next);
	}

	return (-1);
      }

      /* destroy temporary signature envelope when doing retainable 
       * signatures.

       */
      if (flags != msg->security)
      {
	tmp_pgp_pbody = mutt_remove_multipart (tmp_pgp_pbody);
	mutt_free_body (&tmp_pgp_pbody->next);
      }
    }
  }

  if(pbody)
      msg->content = pbody;

  return 0;
}
Example #2
0
/**
 * mutt_protect - Encrypt and/or sign a message
 * @param msg     Header of the message
 * @param keylist List of keys to encrypt to (space-separated)
 * @retval  0 Success
 * @retval -1 Error
 */
int mutt_protect(struct Email *msg, char *keylist)
{
  struct Body *pbody = NULL, *tmp_pbody = NULL;
  struct Body *tmp_smime_pbody = NULL;
  struct Body *tmp_pgp_pbody = NULL;
  int flags = (WithCrypto & APPLICATION_PGP) ? msg->security : 0;

  if (!WithCrypto)
    return -1;

  if (!(msg->security & (SEC_ENCRYPT | SEC_SIGN)))
    return 0;

  if ((msg->security & SEC_SIGN) && !crypt_valid_passphrase(msg->security))
    return -1;

  if (((WithCrypto & APPLICATION_PGP) != 0) && ((msg->security & PGP_INLINE) == PGP_INLINE))
  {
    if ((msg->content->type != TYPE_TEXT) ||
        (mutt_str_strcasecmp(msg->content->subtype, "plain") != 0))
    {
      if (query_quadoption(C_PgpMimeAuto,
                           _("Inline PGP can't be used with attachments.  "
                             "Revert to PGP/MIME?")) != MUTT_YES)
      {
        mutt_error(
            _("Mail not sent: inline PGP can't be used with attachments"));
        return -1;
      }
    }
    else if (mutt_str_strcasecmp("flowed", mutt_param_get(&msg->content->parameter, "format")) == 0)
    {
      if ((query_quadoption(C_PgpMimeAuto,
                            _("Inline PGP can't be used with format=flowed.  "
                              "Revert to PGP/MIME?"))) != MUTT_YES)
      {
        mutt_error(
            _("Mail not sent: inline PGP can't be used with format=flowed"));
        return -1;
      }
    }
    else
    {
      /* they really want to send it inline... go for it */
      if (!isendwin())
      {
        mutt_endwin();
        puts(_("Invoking PGP..."));
      }
      pbody = crypt_pgp_traditional_encryptsign(msg->content, flags, keylist);
      if (pbody)
      {
        msg->content = pbody;
        return 0;
      }

      /* otherwise inline won't work...ask for revert */
      if (query_quadoption(
              C_PgpMimeAuto,
              _("Message can't be sent inline.  Revert to using PGP/MIME?")) != MUTT_YES)
      {
        mutt_error(_("Mail not sent"));
        return -1;
      }
    }

    /* go ahead with PGP/MIME */
  }

  if (!isendwin())
    mutt_endwin();

  if (WithCrypto & APPLICATION_SMIME)
    tmp_smime_pbody = msg->content;
  if (WithCrypto & APPLICATION_PGP)
    tmp_pgp_pbody = msg->content;

  if (C_CryptUsePka && (msg->security & SEC_SIGN))
  {
    /* Set sender (necessary for e.g. PKA).  */
    const char *mailbox = NULL;
    struct Address *from = msg->env->from;

    if (!from)
      from = mutt_default_from();

    mailbox = from->mailbox;
    if (!mailbox && C_EnvelopeFromAddress)
      mailbox = C_EnvelopeFromAddress->mailbox;

    if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME))
      crypt_smime_set_sender(mailbox);
    else if (((WithCrypto & APPLICATION_PGP) != 0) && (msg->security & APPLICATION_PGP))
      crypt_pgp_set_sender(mailbox);

    if (!msg->env->from)
      mutt_addr_free(&from);
  }

  if (C_CryptProtectedHeadersWrite)
  {
    struct Envelope *protected_headers = mutt_env_new();
    mutt_str_replace(&protected_headers->subject, msg->env->subject);
    /* Note: if other headers get added, such as to, cc, then a call to
     * mutt_env_to_intl() will need to be added here too. */
    mutt_prepare_envelope(protected_headers, 0);

    mutt_env_free(&msg->content->mime_headers);
    msg->content->mime_headers = protected_headers;
  }

  if (msg->security & SEC_SIGN)
  {
    if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME))
    {
      tmp_pbody = crypt_smime_sign_message(msg->content);
      if (!tmp_pbody)
        goto bail;
      pbody = tmp_pbody;
      tmp_smime_pbody = tmp_pbody;
    }

    if (((WithCrypto & APPLICATION_PGP) != 0) && (msg->security & APPLICATION_PGP) &&
        (!(flags & SEC_ENCRYPT) || C_PgpRetainableSigs))
    {
      tmp_pbody = crypt_pgp_sign_message(msg->content);
      if (!tmp_pbody)
        goto bail;

      flags &= ~SEC_SIGN;
      pbody = tmp_pbody;
      tmp_pgp_pbody = tmp_pbody;
    }

    if ((WithCrypto != 0) && (msg->security & APPLICATION_SMIME) &&
        (msg->security & APPLICATION_PGP))
    {
      /* here comes the draft ;-) */
    }
  }

  if (msg->security & SEC_ENCRYPT)
  {
    if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME))
    {
      tmp_pbody = crypt_smime_build_smime_entity(tmp_smime_pbody, keylist);
      if (!tmp_pbody)
      {
        /* signed ? free it! */
        goto bail;
      }
      /* free tmp_body if messages was signed AND encrypted ... */
      if ((tmp_smime_pbody != msg->content) && (tmp_smime_pbody != tmp_pbody))
      {
        /* detach and don't delete msg->content,
         * which tmp_smime_pbody->parts after signing. */
        tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
        msg->content->next = NULL;
        mutt_body_free(&tmp_smime_pbody);
      }
      pbody = tmp_pbody;
    }

    if (((WithCrypto & APPLICATION_PGP) != 0) && (msg->security & APPLICATION_PGP))
    {
      pbody = crypt_pgp_encrypt_message(tmp_pgp_pbody, keylist, (flags & SEC_SIGN));
      if (!pbody)
      {
        /* did we perform a retainable signature? */
        if (flags != msg->security)
        {
          /* remove the outer multipart layer */
          tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
          /* get rid of the signature */
          mutt_body_free(&tmp_pgp_pbody->next);
        }

        goto bail;
      }

      /* destroy temporary signature envelope when doing retainable
       * signatures.

       */
      if (flags != msg->security)
      {
        tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
        mutt_body_free(&tmp_pgp_pbody->next);
      }
    }
  }

  if (pbody)
  {
    msg->content = pbody;
    return 0;
  }

bail:
  mutt_env_free(&msg->content->mime_headers);
  return -1;
}