diff --git a/lib/mu-msg-crypto.c b/lib/mu-msg-crypto.c index b77fc90c..26aef0ed 100644 --- a/lib/mu-msg-crypto.c +++ b/lib/mu-msg-crypto.c @@ -115,7 +115,7 @@ get_gpg (GError **err) } return g_strdup (envpath); } - + if (!(path = g_find_program_in_path ("gpg")) && !(path = g_find_program_in_path ("gpg2"))) { mu_util_g_set_error (err, MU_ERROR, "gpg/gpg2 not found"); @@ -134,7 +134,7 @@ get_gpg_crypto_context (MuMsgOptions opts, GError **err) cctx = NULL; if (!(gpg = get_gpg (err))) return NULL; - + cctx = g_mime_gpg_context_new ( (GMimePasswordRequestFunc)password_requester, gpg); g_free (gpg); @@ -165,7 +165,7 @@ get_crypto_context (MuMsgOptions opts, MuMsgPartPasswordFunc password_func, cctx = get_gpg_crypto_context (opts, err); if (!cctx) return NULL; - + /* use gobject to pass data to the callback func */ cbdata = g_new0 (CallbackData, 1); cbdata->pw_func = password_func ? password_func : dummy_password_func; @@ -355,10 +355,21 @@ mu_msg_part_sig_status_report_destroy (MuMsgPartSigStatusReport *report) } -MuMsgPartSigStatusReport* +static inline void +tag_with_sig_status(GObject *part, + MuMsgPartSigStatusReport *report) +{ + g_object_set_data_full + (part, SIG_STATUS_REPORT, report, + (GDestroyNotify)mu_msg_part_sig_status_report_destroy); +} + + +void mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, MuMsgOptions opts, GError **err) { + /* the signature status */ MuMsgPartSigStatusReport *report; GMimeCryptoContext *ctx; GMimeSignatureList *sigs; @@ -369,7 +380,7 @@ mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, MuMsgOptions opts, if (!ctx) { mu_util_g_set_error (err, MU_ERROR_CRYPTO, "failed to get crypto context"); - return NULL; + return; } sigs = g_mime_multipart_signed_verify (sig, ctx, err); @@ -378,13 +389,42 @@ mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, MuMsgOptions opts, if (err && !*err) mu_util_g_set_error (err, MU_ERROR_CRYPTO, "verification failed"); - return NULL; + return; } report = get_status_report (sigs); g_mime_signature_list_clear (sigs); - return report; + /* tag this part with the signature status check */ + tag_with_sig_status(G_OBJECT(sig), report); +} + + +static inline void +check_decrypt_result(GMimeMultipartEncrypted *part, GMimeDecryptResult *res, + GError **err) +{ + GMimeSignatureList *sigs; + MuMsgPartSigStatusReport *report; + + if (res) { + /* Check if the decrypted part had any embed signatures */ + sigs = res->signatures; + if (sigs) { + report = get_status_report (sigs); + g_mime_signature_list_clear (sigs); + + /* tag this part with the signature status check */ + tag_with_sig_status(G_OBJECT(part), report); + } + else { + if (err && !*err) + mu_util_g_set_error (err, MU_ERROR_CRYPTO, + "verification failed"); + } + g_object_unref (res); + } + } @@ -417,10 +457,7 @@ mu_msg_crypto_decrypt_part (GMimeMultipartEncrypted *enc, MuMsgOptions opts, dec = g_mime_multipart_encrypted_decrypt (enc, ctx, &res, err); g_object_unref (ctx); - /* we don't use the 3rd param 'res' * (GMimeDecryptResult), - * but we must unref it. */ - if (res) - g_object_unref (res); + check_decrypt_result(enc, res, err); if (!dec) { if (err && !*err) diff --git a/lib/mu-msg-file.c b/lib/mu-msg-file.c index 1e6bd6f3..debc22df 100644 --- a/lib/mu-msg-file.c +++ b/lib/mu-msg-file.c @@ -287,6 +287,8 @@ msg_cflags_cb (GMimeObject *parent, GMimeObject *part, MuFlags *flags) if (GMIME_IS_MULTIPART_SIGNED(part)) *flags |= MU_FLAG_SIGNED; + /* FIXME: An encrypted part might be signed at the same time. + * In that case the signed flag is lost. */ if (GMIME_IS_MULTIPART_ENCRYPTED(part)) *flags |= MU_FLAG_ENCRYPTED; diff --git a/lib/mu-msg-part.c b/lib/mu-msg-part.c index 1de0fde2..8b9a7cf9 100644 --- a/lib/mu-msg-part.c +++ b/lib/mu-msg-part.c @@ -316,30 +316,18 @@ get_disposition (GMimeObject *mobj) return MU_MSG_PART_TYPE_NONE; } -#define SIG_STATUS_REPORT "sig-status-report" - /* call 'func' with information about this MIME-part */ -static gboolean +static inline void check_signature (MuMsg *msg, GMimeMultipartSigned *part, MuMsgOptions opts) { - /* the signature status */ - MuMsgPartSigStatusReport *sigrep; GError *err; - err = NULL; - sigrep = mu_msg_crypto_verify_part (part, opts, &err); + err = NULL; + mu_msg_crypto_verify_part (part, opts, &err); if (err) { g_warning ("error verifying signature: %s", err->message); g_clear_error (&err); } - - /* tag this part with the signature status check */ - g_object_set_data_full - (G_OBJECT(part), SIG_STATUS_REPORT, - sigrep, - (GDestroyNotify)mu_msg_part_sig_status_report_destroy); - - return TRUE; } @@ -454,14 +442,20 @@ handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent, msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_HTML; } - /* put the verification info in the pgp-signature part */ + /* put the verification info in the pgp-signature and every + * descendent of a pgp-encrypted part */ msgpart.sig_status_report = NULL; - if (g_ascii_strcasecmp (msgpart.subtype, "pgp-signature") == 0) + if (g_ascii_strcasecmp (msgpart.subtype, "pgp-signature") == 0 || + decrypted) { msgpart.sig_status_report = (MuMsgPartSigStatusReport*) g_object_get_data (G_OBJECT(parent), SIG_STATUS_REPORT); + if (msgpart.sig_status_report) + msgpart.part_type |= MU_MSG_PART_TYPE_SIGNED; + } + msgpart.data = (gpointer)part; msgpart.index = (*index)++; @@ -501,7 +495,7 @@ handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart, if (mmsg) return handle_mime_object (msg, mmsg->mime_part, - (GMimeObject *) mmsg, + parent, opts, index, decrypted, @@ -513,8 +507,8 @@ handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart, } static gboolean -handle_multipart (MuMsg *msg, GMimeMultipart *mpart, MuMsgOptions opts, - unsigned *index, gboolean decrypted, +handle_multipart (MuMsg *msg, GMimeMultipart *mpart, GMimeObject *parent, + MuMsgOptions opts, unsigned *index, gboolean decrypted, MuMsgPartForeachFunc func, gpointer user_data) { gboolean res; @@ -524,7 +518,7 @@ handle_multipart (MuMsg *msg, GMimeMultipart *mpart, MuMsgOptions opts, res = TRUE; for (i = 0; i < mpart->children->len; i++) { part = (GMimeObject *) mpart->children->pdata[i]; - res &= handle_mime_object (msg, part, (GMimeObject *) mpart, + res &= handle_mime_object (msg, part, parent, opts, index, decrypted, func, user_data); } @@ -548,15 +542,11 @@ handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent, parent, opts, index, decrypted, func, user_data); else if ((opts & MU_MSG_OPTION_VERIFY) && GMIME_IS_MULTIPART_SIGNED (mobj)) { - gboolean verified, multipart; - - verified = check_signature + check_signature (msg, GMIME_MULTIPART_SIGNED (mobj), opts); - multipart = handle_multipart - (msg, GMIME_MULTIPART (mobj), opts, + return handle_multipart + (msg, GMIME_MULTIPART (mobj), (GObject*)mobj, opts, index, decrypted, func, user_data); - - return verified && multipart; } else if ((opts & MU_MSG_OPTION_DECRYPT) && GMIME_IS_MULTIPART_ENCRYPTED (mobj)) return handle_encrypted_part @@ -564,7 +554,7 @@ handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent, opts, index, func, user_data); else if (GMIME_IS_MULTIPART (mobj)) return handle_multipart - (msg, GMIME_MULTIPART (mobj), opts, + (msg, GMIME_MULTIPART (mobj), parent, opts, index, decrypted, func, user_data); return TRUE; } diff --git a/lib/mu-msg-part.h b/lib/mu-msg-part.h index 1650821f..5dd82a16 100644 --- a/lib/mu-msg-part.h +++ b/lib/mu-msg-part.h @@ -25,6 +25,8 @@ #include #include /* for ssize_t */ +#define SIG_STATUS_REPORT "sig-status-report" + G_BEGIN_DECLS enum _MuMsgPartType { diff --git a/lib/mu-msg-priv.h b/lib/mu-msg-priv.h index 56687218..8f617191 100644 --- a/lib/mu-msg-priv.h +++ b/lib/mu-msg-priv.h @@ -115,10 +115,9 @@ typedef char* (*MuMsgPartPasswordFunc) (const char *user_id, const char *promp * * @return a status report object, free with mu_msg_part_sig_status_report_destroy */ -MuMsgPartSigStatusReport* mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, - MuMsgOptions opts, - GError **err) - G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +void mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, + MuMsgOptions opts, + GError **err); /** * decrypt the given encrypted mime multipart