# HG changeset patch # User Mikael Berthe # Date 1164557301 -3600 # Node ID ebbde723614b813d5afd20ae5f5f745005d8f090 # Parent 8a395c2cafc4719ee0686caffc81327df2fdc81c Store contacts PGP keys Contacts PGP keys are retrieved from presence/message signatures; they're displayed with /info. diff -r 8a395c2cafc4 -r ebbde723614b mcabber/src/commands.c --- a/mcabber/src/commands.c Sun Nov 26 10:42:25 2006 +0100 +++ b/mcabber/src/commands.c Sun Nov 26 17:08:21 2006 +0100 @@ -1302,11 +1302,13 @@ enum imstatus rstatus; const char *rst_msg; time_t rst_time; + struct pgp_data *rpgp; rprio = buddy_getresourceprio(bud, resources->data); rstatus = buddy_getstatus(bud, resources->data); rst_msg = buddy_getstatusmsg(bud, resources->data); rst_time = buddy_getstatustime(bud, resources->data); + rpgp = buddy_resource_pgp(bud, resources->data); snprintf(buffer, 4095, "Resource: [%c] (%d) %s", imstatus2char[rstatus], rprio, (char*)resources->data); @@ -1322,6 +1324,19 @@ snprintf(buffer, 127, "Status timestamp: %s", tbuf); scr_WriteIncomingMessage(jid, buffer, 0, HBB_PREFIX_NONE); } +#ifdef HAVE_GPGME + if (rpgp && rpgp->sign_keyid) { + snprintf(buffer, 4095, "PGP key id: %s", rpgp->sign_keyid); + scr_WriteIncomingMessage(jid, buffer, 0, HBB_PREFIX_NONE); + if (rpgp->last_sigsum) { + gpgme_sigsum_t ss = rpgp->last_sigsum; + snprintf(buffer, 4095, "Last PGP signature: %s", + (ss & GPGME_SIGSUM_GREEN ? "good": + (ss & GPGME_SIGSUM_RED ? "bad" : "unknown"))); + scr_WriteIncomingMessage(jid, buffer, 0, HBB_PREFIX_NONE); + } + } +#endif } } else { if (name) scr_LogPrint(LPRINT_NORMAL, "Name: %s", name); diff -r 8a395c2cafc4 -r ebbde723614b mcabber/src/jabglue.c --- a/mcabber/src/jabglue.c Sun Nov 26 10:42:25 2006 +0100 +++ b/mcabber/src/jabglue.c Sun Nov 26 17:08:21 2006 +0100 @@ -1402,12 +1402,61 @@ "Warning: you're not connected to the server."); } +// check_signature(barejid, resourcename, xmldata, text) +// Verify the signature (in xmldata) of "text" for the contact +// barejid/resourcename. +// xmldata is the 'jabber:x:signed' stanza. +// If the key id is found, the contact's PGP data are updated. +static void check_signature(const char *barejid, const char *rname, + xmlnode xmldata, const char *text) +{ +#ifdef HAVE_GPGME + char *p, *key; + GSList *sl_buddy; + struct pgp_data *res_pgpdata; + gpgme_sigsum_t sigsum; + + // All parameters must be valid + if (!(xmldata && barejid && rname && text && *text)) + return; + + if (!gpg_enabled()) + return; + + // Get the resource PGP data structure + sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); + if (!sl_buddy) + return; + res_pgpdata = buddy_resource_pgp(sl_buddy->data, rname); + if (!res_pgpdata) + return; + + p = xmlnode_get_name(xmldata); + if (!p || strcmp(p, "x")) + return; // We expect "" + + // Get signature + p = xmlnode_get_data(xmldata); + if (!p) + return; + + key = gpg_verify(p, text, &sigsum); + if (key) { + g_free(res_pgpdata->sign_keyid); + res_pgpdata->sign_keyid = key; + res_pgpdata->last_sigsum = sigsum; + } +#endif +} + static void gotmessage(char *type, const char *from, const char *body, - const char *enc, time_t timestamp) + const char *enc, time_t timestamp, + xmlnode xmldata_signed) { char *jid; const char *rname, *s; char *decrypted = NULL; + /* bool sigchecked = FALSE; */ jid = jidtodisp(from); @@ -1417,9 +1466,19 @@ #ifdef HAVE_GPGME if (enc && gpg_enabled()) { decrypted = gpg_decrypt(enc); - if (decrypted) + if (decrypted) { body = decrypted; + /* + if (xmldata_signed) { + check_signature(jid, rname, xmldata_signed, decrypted); + sigchecked = TRUE; + } + */ + } } + // Check signature of an unencrypted message + if (xmldata_signed /* && !sigchecked */ && gpg_enabled()) + check_signature(jid, rname, xmldata_signed, decrypted); #endif // Check for unexpected groupchat messages @@ -1962,10 +2021,13 @@ // Not a MUC message, so this is a regular buddy... // Call hk_statuschange() if status has changed or if the // status message is different - const char *m = roster_getstatusmsg(r, rname); + const char *m; + m = roster_getstatusmsg(r, rname); if ((ust != roster_getstatus(r, rname)) || (!ustmsg && m && m[0]) || (ustmsg && (!m || strcmp(ustmsg, m)))) hk_statuschange(r, rname, bpprio, timestamp, ust, ustmsg); + // Presence signature processing + check_signature(r, rname, xml_get_xmlns(xmldata, NS_SIGNED), ustmsg); } g_free(r); @@ -2044,7 +2106,8 @@ #endif } if (from && body) - gotmessage(type, from, body, enc, timestamp); + gotmessage(type, from, body, enc, timestamp, + xml_get_xmlns(xmldata, NS_SIGNED)); g_free(tmp); } diff -r 8a395c2cafc4 -r ebbde723614b mcabber/src/roster.c --- a/mcabber/src/roster.c Sun Nov 26 10:42:25 2006 +0100 +++ b/mcabber/src/roster.c Sun Nov 26 17:08:21 2006 +0100 @@ -58,6 +58,9 @@ #ifdef JEP0085 struct jep0085 jep85; #endif +#ifdef HAVE_GPGME + struct pgp_data pgpdata; +#endif } res; /* This is a private structure type for the roster */ @@ -125,6 +128,9 @@ g_free(p_res->jep22.last_msgid_sent); g_free(p_res->jep22.last_msgid_rcvd); #endif +#ifdef HAVE_GPGME + g_free(p_res->pgpdata.sign_keyid); +#endif } // Free all nodes but the first (which is static) g_slist_free(*reslist); @@ -223,6 +229,9 @@ g_free(p_res->jep22.last_msgid_sent); g_free(p_res->jep22.last_msgid_rcvd); #endif +#ifdef HAVE_GPGME + g_free(p_res->pgpdata.sign_keyid); +#endif rost->resource = g_slist_delete_link(rost->resource, p_res_elt); return; } @@ -1117,6 +1126,18 @@ return NULL; } +struct pgp_data *buddy_resource_pgp(gpointer rosterdata, const char *resname) +{ +#ifdef HAVE_GPGME + roster *roster_usr = rosterdata; + res *p_res = get_resource(roster_usr, resname); + if (p_res) + return &p_res->pgpdata; +#endif + return NULL; +} + + enum imrole buddy_getrole(gpointer rosterdata, const char *resname) { roster *roster_usr = rosterdata; diff -r 8a395c2cafc4 -r ebbde723614b mcabber/src/roster.h --- a/mcabber/src/roster.h Sun Nov 26 10:42:25 2006 +0100 +++ b/mcabber/src/roster.h Sun Nov 26 17:08:21 2006 +0100 @@ -4,6 +4,8 @@ #include #include +#include "pgp.h" + #define SPECIAL_BUFFER_STATUS_ID "[status]" enum imstatus { @@ -97,6 +99,13 @@ CHATSTATES_SUPPORT_OK }; +struct pgp_data { + gchar *sign_keyid; +#ifdef HAVE_GPGME + gpgme_sigsum_t last_sigsum; +#endif +}; + /* Message event and chat state flags */ #define ROSTER_EVENT_NONE 0U /* JEP-22 Message Events */ @@ -177,6 +186,7 @@ guint buddy_resource_getevents(gpointer rosterdata, const char *resname); struct jep0022 *buddy_resource_jep22(gpointer rosterdata, const char *resname); struct jep0085 *buddy_resource_jep85(gpointer rosterdata, const char *resname); +struct pgp_data *buddy_resource_pgp(gpointer rosterdata, const char *resname); enum imrole buddy_getrole(gpointer rosterdata, const char *resname); enum imaffiliation buddy_getaffil(gpointer rosterdata, const char *resname); const char *buddy_getrjid(gpointer rosterdata, const char *resname);