mirror of https://github.com/djcb/mu.git
Fix #280
Since `parent` is not really used as a parent, I use it as the last visited encrypted part while going down the parts-tree. At the decryption of a part (`mu_msg_crypto_decrypt_part`) I check, through the GMimeDecryptResult, for signatures (`check_decrypt_result`) and add them to the part (`tag_with_sig_status`). Any nested parts hold that encrypted part as their parent. Finally at `handle_part`, for each part I check if it a descendent of an encrypted part. If so, I proceed checking for signatures and adding them to the `msgpart`.
This commit is contained in:
parent
9799d76fdb
commit
8456c1c2dc
|
@ -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)
|
||||
|
|
|
@ -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), parent, 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;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <glib.h>
|
||||
#include <unistd.h> /* for ssize_t */
|
||||
|
||||
#define SIG_STATUS_REPORT "sig-status-report"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
enum _MuMsgPartType {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue