/** * test_last_status_new - Is the last message new * @param fp File to check * @retval true if the last message is new */ static bool test_last_status_new(FILE *fp) { struct Email *e = NULL; struct Envelope *tmp_envelope = NULL; bool rc = false; if (fseek_last_message(fp) == -1) return false; e = mutt_email_new(); tmp_envelope = mutt_rfc822_read_header(fp, e, false, false); if (!(e->read || e->old)) rc = true; mutt_env_free(&tmp_envelope); mutt_email_free(&e); return rc; }
/** * 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; }