Store contacts PGP keys
Contacts PGP keys are retrieved from presence/message signatures;
they're displayed with /info.
--- 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);
--- 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 "<x xmlns='jabber:x:signed'>"
+
+ // 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);
}
--- 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;
--- 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 <glib.h>
#include <time.h>
+#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);