mu: include signers in signature report

Include the names/email address of signer in the reports, so we can use
them in mu4e.
This commit is contained in:
djcb
2017-08-27 17:32:23 +03:00
parent e09419f85b
commit 6eceb5eee3
3 changed files with 105 additions and 39 deletions

View File

@ -235,7 +235,7 @@ get_digestkey_algo_name (GMimeDigestAlgo algo)
/* get data from the 'certificate' */ /* get data from the 'certificate' */
static char* static char*
get_cert_data (GMimeCertificate *cert) get_cert_details (GMimeCertificate *cert)
{ {
const char /**email,*/ *name, *digest_algo, *pubkey_algo, const char /**email,*/ *name, *digest_algo, *pubkey_algo,
*keyid, *trust; *keyid, *trust;
@ -274,15 +274,23 @@ get_cert_data (GMimeCertificate *cert)
static char* static char*
get_verdict_report (GMimeSignature *msig) get_verdict_report (GMimeSignature *msig)
{ {
time_t t; time_t t;
const char *status, *created, *expires; const char *created, *expires, *verdict;
gchar *certdata, *report; char *certdata, *report;
switch (g_mime_signature_get_status (msig)) { switch (g_mime_signature_get_status (msig)) {
case GMIME_SIGNATURE_STATUS_GOOD: status = "good"; break; case GMIME_SIGNATURE_STATUS_GOOD:
case GMIME_SIGNATURE_STATUS_ERROR: status = "error"; break; verdict = "good";
case GMIME_SIGNATURE_STATUS_BAD: status = "bad"; break; break;
default: g_return_val_if_reached (NULL); case GMIME_SIGNATURE_STATUS_ERROR:
verdict = "error";
break;
case GMIME_SIGNATURE_STATUS_BAD:
verdict = "bad";
break;
default:
g_return_val_if_reached (NULL);
return NULL;
} }
t = g_mime_signature_get_created (msig); t = g_mime_signature_get_created (msig);
@ -291,41 +299,69 @@ get_verdict_report (GMimeSignature *msig)
t = g_mime_signature_get_expires (msig); t = g_mime_signature_get_expires (msig);
expires = (t == 0 || t == (time_t)-1) ? "?" : mu_date_str_s ("%x", t); expires = (t == 0 || t == (time_t)-1) ? "?" : mu_date_str_s ("%x", t);
certdata = get_cert_data (g_mime_signature_get_certificate (msig)); certdata = get_cert_details (g_mime_signature_get_certificate (msig));
report = g_strdup_printf ("%s; created:%s, expires:%s, %s", report = g_strdup_printf ("%s\ncreated:%s, expires:%s, %s",
status, created, expires, verdict, created, expires,
certdata ? certdata : "?"); certdata ? certdata : "?");
g_free (certdata); g_free (certdata);
return report; return report;
} }
static char*
get_signers (GHashTable *signerhash)
{
GString *gstr;
GHashTableIter iter;
const char *name;
if (!signerhash || g_hash_table_size(signerhash) == 0)
return NULL;
gstr = g_string_new (NULL);
g_hash_table_iter_init (&iter, signerhash);
while (g_hash_table_iter_next (&iter, (gpointer)&name, NULL)) {
if (gstr->len != 0)
g_string_append_c (gstr, ',');
gstr = g_string_append (gstr, name);
}
return g_string_free (gstr, FALSE);
}
static MuMsgPartSigStatusReport* static MuMsgPartSigStatusReport*
get_status_report (GMimeSignatureList *sigs) get_status_report (GMimeSignatureList *sigs)
{ {
int i; int i;
MuMsgPartSigStatus status; MuMsgPartSigStatus status;
MuMsgPartSigStatusReport *status_report; MuMsgPartSigStatusReport *status_report;
char *report; char *report;
GHashTable *signerhash;
status = MU_MSG_PART_SIG_STATUS_GOOD; /* let's start positive! */ status = MU_MSG_PART_SIG_STATUS_GOOD; /* let's start positive! */
signerhash = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0, report = NULL; i != g_mime_signature_list_length (sigs); for (i = 0, report = NULL; i != g_mime_signature_list_length (sigs);
++i) { ++i) {
GMimeSignature *msig; GMimeSignature *msig;
GMimeSignatureStatus sigstat; GMimeCertificate *cert;
gchar *rep; GMimeSignatureStatus sigstat;
gchar *rep;
msig = g_mime_signature_list_get_signature (sigs, i); msig = g_mime_signature_list_get_signature (sigs, i);
sigstat = g_mime_signature_get_status (msig); sigstat = g_mime_signature_get_status (msig);
switch (sigstat) { switch (sigstat) {
case GMIME_SIGNATURE_STATUS_GOOD: break; case GMIME_SIGNATURE_STATUS_GOOD:
break;
case GMIME_SIGNATURE_STATUS_ERROR: case GMIME_SIGNATURE_STATUS_ERROR:
status = MU_MSG_PART_SIG_STATUS_ERROR; break; status = MU_MSG_PART_SIG_STATUS_ERROR;
break;
case GMIME_SIGNATURE_STATUS_BAD: case GMIME_SIGNATURE_STATUS_BAD:
status = MU_MSG_PART_SIG_STATUS_BAD; break; status = MU_MSG_PART_SIG_STATUS_BAD;
break;
default: g_return_val_if_reached (NULL); default: g_return_val_if_reached (NULL);
} }
@ -335,11 +371,21 @@ get_status_report (GMimeSignatureList *sigs)
report ? "; " : "", i + 1, report ? "; " : "", i + 1,
rep); rep);
g_free (rep); g_free (rep);
cert = g_mime_signature_get_certificate (msig);
if (cert && g_mime_certificate_get_name (cert))
g_hash_table_add (
signerhash,
(gpointer)g_mime_certificate_get_name (cert));
} }
status_report = g_slice_new (MuMsgPartSigStatusReport); status_report = g_slice_new0 (MuMsgPartSigStatusReport);
status_report->verdict = status; status_report->verdict = status;
status_report->report = report; status_report->report = report;
status_report->signers = get_signers(signerhash);
g_hash_table_unref (signerhash);
return status_report; return status_report;
} }
@ -351,6 +397,8 @@ mu_msg_part_sig_status_report_destroy (MuMsgPartSigStatusReport *report)
return; return;
g_free ((char*)report->report); g_free ((char*)report->report);
g_free ((char*)report->signers);
g_slice_free (MuMsgPartSigStatusReport, report); g_slice_free (MuMsgPartSigStatusReport, report);
} }

View File

@ -65,11 +65,11 @@ enum _MuMsgPartSigStatus {
}; };
typedef enum _MuMsgPartSigStatus MuMsgPartSigStatus; typedef enum _MuMsgPartSigStatus MuMsgPartSigStatus;
struct _MuMsgPartSigStatusReport { typedef struct {
MuMsgPartSigStatus verdict; MuMsgPartSigStatus verdict;
const char *report; const char *report;
}; const char *signers;
typedef struct _MuMsgPartSigStatusReport MuMsgPartSigStatusReport; } MuMsgPartSigStatusReport;
/** /**
* destroy a MuMsgPartSignatureStatusReport object * destroy a MuMsgPartSignatureStatusReport object
@ -178,7 +178,7 @@ gboolean mu_msg_part_save (MuMsg *msg, MuMsgOptions opts,
*/ */
gchar* mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts, gchar* mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts,
guint partidx, GError **err) guint partidx, GError **err)
G_GNUC_WARN_UNUSED_RESULT; G_GNUC_WARN_UNUSED_RESULT;
@ -217,7 +217,7 @@ gchar* mu_msg_part_get_path (MuMsg *msg, MuMsgOptions opts,
*/ */
gchar* mu_msg_part_get_cache_path (MuMsg *msg, MuMsgOptions opts, gchar* mu_msg_part_get_cache_path (MuMsg *msg, MuMsgOptions opts,
guint partidx, GError **err) guint partidx, GError **err)
G_GNUC_WARN_UNUSED_RESULT; G_GNUC_WARN_UNUSED_RESULT;
/** /**

View File

@ -279,25 +279,40 @@ struct _PartInfo {
}; };
typedef struct _PartInfo PartInfo; typedef struct _PartInfo PartInfo;
static const char* static char*
sig_verdict (MuMsgPart *mpart) sig_verdict (MuMsgPart *mpart)
{ {
MuMsgPartSigStatusReport *report; char *signers, *s;
const char *verdict;
MuMsgPartSigStatusReport *report;
report = mpart->sig_status_report; report = mpart->sig_status_report;
if (!report) if (!report)
return ""; return g_strdup ("");
switch (report->verdict) { switch (report->verdict) {
case MU_MSG_PART_SIG_STATUS_GOOD: case MU_MSG_PART_SIG_STATUS_GOOD:
return ":signature verified"; verdict = ":signature verified";
break;
case MU_MSG_PART_SIG_STATUS_BAD: case MU_MSG_PART_SIG_STATUS_BAD:
return ":signature bad"; verdict = ":signature bad";
break;
case MU_MSG_PART_SIG_STATUS_ERROR: case MU_MSG_PART_SIG_STATUS_ERROR:
return ":signature unverified"; verdict = ":signature unverified";
break;
default: default:
return ""; verdict = "";
break;
} }
if (!report->signers)
return g_strdup (verdict);
signers = mu_str_escape_c_literal (report->signers, TRUE);
s = g_strdup_printf ("%s :signers %s", verdict, signers);
g_free (signers);
return s;
} }
static const char* static const char*
@ -354,7 +369,7 @@ static void
each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo) each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo)
{ {
char *name, *encname, *tmp, *parttype; char *name, *encname, *tmp, *parttype;
char *tmpfile, *cid; char *tmpfile, *cid, *verdict;
name = mu_msg_part_get_filename (part, TRUE); name = mu_msg_part_get_filename (part, TRUE);
encname = name ? encname = name ?
@ -364,9 +379,11 @@ each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo)
tmpfile = get_temp_file_maybe (msg, part, pinfo->opts); tmpfile = get_temp_file_maybe (msg, part, pinfo->opts);
parttype = get_part_type_string (part->part_type); parttype = get_part_type_string (part->part_type);
verdict = sig_verdict (part);
cid = mu_str_escape_c_literal(mu_msg_part_get_content_id(part), cid = mu_str_escape_c_literal(mu_msg_part_get_content_id(part),
TRUE); TRUE);
tmp = g_strdup_printf tmp = g_strdup_printf
("%s(:index %d :name %s :mime-type \"%s/%s\"%s%s " ("%s(:index %d :name %s :mime-type \"%s/%s\"%s%s "
":type %s " ":type %s "
@ -381,12 +398,13 @@ each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo)
mu_msg_part_maybe_attachment (part) ? "t" : "nil", mu_msg_part_maybe_attachment (part) ? "t" : "nil",
cid ? " :cid" : "", cid ? cid : "", cid ? " :cid" : "", cid ? cid : "",
(int)part->size, (int)part->size,
sig_verdict (part), verdict,
dec_verdict (part)); dec_verdict (part));
g_free (encname); g_free (encname);
g_free (tmpfile); g_free (tmpfile);
g_free (parttype); g_free (parttype);
g_free (verdict);
g_free (cid); g_free (cid);
g_free (pinfo->parts); g_free (pinfo->parts);