# HG changeset patch # User Mikael Berthe # Date 1164534145 -3600 # Node ID 8a395c2cafc4719ee0686caffc81327df2fdc81c # Parent d4b97a2423eb54727e7ef8fe2bcbea0db599292d Initial PGP support (decrypt) This patch initialize the PGP (GPG) sub-system, and adds a few PGP-related options to the configuration file. Encrypted messages can be processed. Presence is signed when the status message is non-empty. diff -r d4b97a2423eb -r 8a395c2cafc4 mcabber/mcabberrc.example --- a/mcabber/mcabberrc.example Sun Nov 26 10:30:52 2006 +0100 +++ b/mcabber/mcabberrc.example Sun Nov 26 10:42:25 2006 +0100 @@ -38,6 +38,17 @@ #set ssl_capath = #set ssl_ciphers = +# PGP support +# Set pgp to 1 to enable OpenPGP. +# To sign outgoing messages, select your private key id with +# the pgp_private_key option. You cannot change these options once +# mcabber is running. +#set pgp = 0 +#set pgp_private_key = "B0B92210" +# +# You can set your PGP passhrase here, although it's NOT advised. +#set pgp_passphrase = "PGPpassword" + # Conference nickname # This nickname is used when joining a room, when no nick is explicitly # specified by the user. Note that when the nickname option is not set, diff -r d4b97a2423eb -r 8a395c2cafc4 mcabber/src/jabglue.c --- a/mcabber/src/jabglue.c Sun Nov 26 10:30:52 2006 +0100 +++ b/mcabber/src/jabglue.c Sun Nov 26 10:42:25 2006 +0100 @@ -32,6 +32,7 @@ #include "hbuf.h" #include "histolog.h" #include "commands.h" +#include "pgp.h" #define JABBERPORT 5222 #define JABBERSSLPORT 5223 @@ -429,7 +430,20 @@ // (But we want to update internal status even when disconnected, // in order to avoid some problems during network failures) if (online) { - x = presnew(st, recipient, (st != invisible ? msg : NULL)); + const char *s_msg = (st != invisible ? msg : NULL); + x = presnew(st, recipient, s_msg); +#ifdef HAVE_GPGME + if (s_msg && *s_msg && gpg_enabled()) { + char *signature = gpg_sign(s_msg); + if (signature) { + xmlnode y; + y = xmlnode_insert_tag(x, "x"); + xmlnode_put_attrib(y, "xmlns", NS_SIGNED); + xmlnode_insert_cdata(y, signature, (unsigned) -1); + g_free(signature); + } + } +#endif jab_send(jc, x); xmlnode_free(x); } @@ -1393,12 +1407,21 @@ { char *jid; const char *rname, *s; + char *decrypted = NULL; jid = jidtodisp(from); rname = strchr(from, JID_RESOURCE_SEPARATOR); if (rname) rname++; +#ifdef HAVE_GPGME + if (enc && gpg_enabled()) { + decrypted = gpg_decrypt(enc); + if (decrypted) + body = decrypted; + } +#endif + // Check for unexpected groupchat messages // If we receive a groupchat message from a room we're not a member of, // this is probably a server issue and the best we can do is to send @@ -1426,6 +1449,7 @@ } g_free(jid); + g_free(decrypted); buddylist_build(); scr_DrawRoster(); @@ -1444,6 +1468,7 @@ scr_LogPrint(LPRINT_LOGNORM, "Blocked a message from <%s>", jid); } g_free(jid); + g_free(decrypted); } static const char *defaulterrormsg(int code) diff -r d4b97a2423eb -r 8a395c2cafc4 mcabber/src/main.c --- a/mcabber/src/main.c Sun Nov 26 10:30:52 2006 +0100 +++ b/mcabber/src/main.c Sun Nov 26 10:42:25 2006 +0100 @@ -40,6 +40,7 @@ #include "histolog.h" #include "hooks.h" #include "utils.h" +#include "pgp.h" #ifdef ENABLE_HGCSET # include "hgcset.h" @@ -186,7 +187,10 @@ } } -static void ask_password(void) +// ask_password(what) +// Return the password, or NULL. +// The string must be freed after use. +static char *ask_password(const char *what) { char *password, *p; size_t passsize = 128; @@ -195,15 +199,15 @@ password = g_new0(char, passsize); /* Turn echoing off and fail if we can't. */ - if (tcgetattr(fileno(stdin), &orig) != 0) return; + if (tcgetattr(fileno(stdin), &orig) != 0) return NULL; backup_termios = &orig; new = orig; new.c_lflag &= ~ECHO; - if (tcsetattr(fileno(stdin), TCSAFLUSH, &new) != 0) return; + if (tcsetattr(fileno(stdin), TCSAFLUSH, &new) != 0) return NULL; /* Read the password. */ - printf("Please enter password: "); + printf("Please enter %s: ", what); fgets(password, passsize, stdin); /* Restore terminal. */ @@ -216,9 +220,7 @@ for ( ; p > (char*)password ; p--) if (*p == '\n' || *p == '\r') *p = 0; - settings_set(SETTINGS_TYPE_OPTION, "password", password); - g_free(password); - return; + return password; } static void credits(void) @@ -230,6 +232,59 @@ g_free(v); } +void main_init_pgp(void) +{ +#ifdef HAVE_GPGME + const char *pk, *pp; + char *typed_passwd = NULL; + char *p; + bool pgp_invalid = FALSE; + bool pgp_agent; + + p = getenv("GPG_AGENT_INFO"); + pgp_agent = (p && strchr(p, ':')); + + pk = settings_opt_get("pgp_private_key"); + pp = settings_opt_get("pgp_passphrase"); + if (!pk) { + scr_LogPrint(LPRINT_LOGNORM, "WARNING: unkown PGP private key"); + pgp_invalid = TRUE; + } else if (!(pp || pgp_agent)) { + // Request PGP passphrase + pp = typed_passwd = ask_password("PGP passphrase"); + } + gpg_init(pk, pp); + // Erase password from the settings array + if (pp) { + memset((char*)pp, 0, strlen(pp)); + if (typed_passwd) + g_free(typed_passwd); + else + settings_set(SETTINGS_TYPE_OPTION, "pgp_passphrase", NULL); + } + if (!pgp_agent && pk && pp && gpg_test_passphrase()) { + // Let's check the pasphrase + int i; + for (i = 0; i < 2; i++) { + typed_passwd = ask_password("PGP passphrase"); // Ask again... + if (typed_passwd) { + gpg_set_passphrase(typed_passwd); + memset(typed_passwd, 0, strlen(typed_passwd)); + g_free(typed_passwd); + } + if (!gpg_test_passphrase()) + break; // Ok + } + if (i == 2) + pgp_invalid = TRUE; + } + if (pgp_invalid) + scr_LogPrint(LPRINT_LOGNORM, "WARNING: PGP key/pass invalid"); +#else /* not HAVE_GPGME */ + scr_LogPrint(LPRINT_LOGNORM, "WARNING: not compiled with PGP support"); +#endif /* HAVE_GPGME */ +} + int main(int argc, char **argv) { char *configFile = NULL; @@ -291,9 +346,16 @@ p = settings_opt_get("username"); if (p) printf("Username: %s\n", p); - ask_password(); + settings_set(SETTINGS_TYPE_OPTION, "password", + ask_password("Jabber password")); } + /* Initialize PGP system + We do it before ncurses initialization because we may need to request + a passphrase. */ + if (settings_opt_get_int("pgp")) + main_init_pgp(); + /* Initialize N-Curses */ scr_LogPrint(LPRINT_DEBUG, "Initializing N-Curses..."); scr_InitCurses(); @@ -346,6 +408,9 @@ } jb_disconnect(); +#ifdef HAVE_GPGME + gpg_terminate(); +#endif scr_TerminateCurses(); printf("\n\nThanks for using mcabber!\n");