1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-11-03 19:37:16 -05:00

Merge branch 'master' into plugins

Conflicts:
	src/event/server_events.c
This commit is contained in:
James Booth 2015-06-23 23:43:14 +01:00
commit 398c3c0ba6
8 changed files with 221 additions and 13 deletions

View File

@ -13,6 +13,9 @@ AX_PREFIX_CONFIG_H([src/prof_config.h], [PROF], [src/config.h])
AC_PROG_CC
AC_PROG_LIBTOOL
## Check for LFS
AC_SYS_LARGEFILE
### Get canonical host
AC_CANONICAL_HOST
PLATFORM="unknown"
@ -364,7 +367,7 @@ AM_CONDITIONAL([THEMES_INSTALL], "$THEMES_INSTALL")
PKG_CHECK_MODULES([cmocka], [cmocka], [],
[AC_MSG_NOTICE([cmocka is not found, will not be able to run tests])])
AC_CHECK_LIB([stabber], [stbbr_start], [],
AC_CHECK_LIB([stabber], [stbbr_start], [LIBS="$LIBS"],
[AC_MSG_NOTICE([stabber not found, will not be able to run functional tests])])
### Check for ncursesw/ncurses.h first, Arch linux uses ncurses.h for ncursesw

View File

@ -870,18 +870,19 @@ static struct cmd_t command_defs[] =
NULL } } },
{ "/pgp",
cmd_pgp, parse_args, 1, 2, NULL,
cmd_pgp, parse_args, 1, 3, NULL,
{ "/pgp command [args..]", "Open PGP commands.",
{ "/pgp command [args..]",
"---------------------",
"Open PGP commands.",
"",
"keys : List private keys.",
"libver : Show which version of the libgpgme library is being used.",
"fps : Show received fingerprints.",
"start [contact] : Start PGP encrypted chat, current contact will be used if not specified.",
"end : End PGP encrypted chat with the current recipient.",
"log on|off|redact : PGP message logging, default: redact.",
"keys : List all keys.",
"libver : Show which version of the libgpgme library is being used.",
"fps : Show known fingerprints.",
"setkey contact keyid : Manually associate a key ID with a JID.",
"start [contact] : Start PGP encrypted chat, current contact will be used if not specified.",
"end : End PGP encrypted chat with the current recipient.",
"log on|off|redact : PGP message logging, default: redact.",
NULL } } },
{ "/otr",
@ -1620,6 +1621,7 @@ cmd_init(void)
pgp_ac = autocomplete_new();
autocomplete_add(pgp_ac, "keys");
autocomplete_add(pgp_ac, "fps");
autocomplete_add(pgp_ac, "setkey");
autocomplete_add(pgp_ac, "libver");
autocomplete_add(pgp_ac, "start");
autocomplete_add(pgp_ac, "end");
@ -2522,6 +2524,11 @@ _pgp_autocomplete(ProfWin *window, const char * const input)
return found;
}
found = autocomplete_param_with_func(input, "/pgp setkey", roster_barejid_autocomplete);
if (found) {
return found;
}
found = autocomplete_param_with_ac(input, "/pgp", pgp_ac, TRUE);
if (found) {
return found;

View File

@ -688,6 +688,9 @@ cmd_disconnect(ProfWin *window, gchar **args, struct cmd_help_t help)
muc_invites_clear();
chat_sessions_clear();
ui_disconnected();
#ifdef PROF_HAVE_LIBGPGME
p_gpg_on_disconnect();
#endif
free(jid);
} else {
cons_show("You are not currently connected.");
@ -4221,6 +4224,35 @@ cmd_pgp(ProfWin *window, gchar **args, struct cmd_help_t help)
return TRUE;
}
if (g_strcmp0(args[0], "setkey") == 0) {
jabber_conn_status_t conn_status = jabber_get_connection_status();
if (conn_status != JABBER_CONNECTED) {
cons_show("You are not currently connected.");
return TRUE;
}
char *jid = args[1];
if (!args[1]) {
cons_show("Usage: %s", help.usage);
return TRUE;
}
char *keyid = args[2];
if (!args[2]) {
cons_show("Usage: %s", help.usage);
return TRUE;
}
gboolean res = p_gpg_addkey(jid, keyid);
if (!res) {
cons_show("Key ID not found.");
} else {
cons_show("Key %s set for %s.", keyid, jid);
}
return TRUE;
}
if (g_strcmp0(args[0], "fps") == 0) {
jabber_conn_status_t conn_status = jabber_get_connection_status();
if (conn_status != JABBER_CONNECTED) {
@ -4230,11 +4262,11 @@ cmd_pgp(ProfWin *window, gchar **args, struct cmd_help_t help)
GHashTable *fingerprints = p_gpg_fingerprints();
GList *jids = g_hash_table_get_keys(fingerprints);
if (!jids) {
cons_show("No PGP fingerprints received.");
cons_show("No PGP fingerprints available.");
return TRUE;
}
cons_show("Received PGP fingerprints:");
cons_show("Known PGP fingerprints:");
GList *curr = jids;
while (curr) {
char *jid = curr->data;
@ -4343,6 +4375,7 @@ cmd_pgp(ProfWin *window, gchar **args, struct cmd_help_t help)
return TRUE;
}
cons_show("Usage: %s", help.usage);
return TRUE;
#else
cons_show("This version of Profanity has not been built with PGP support enabled");

View File

@ -63,6 +63,10 @@ sv_ev_login_account_success(char *account_name)
otr_on_connect(account);
#endif
#ifdef PROF_HAVE_LIBGPGME
p_gpg_on_connect(account->jid);
#endif
ui_handle_login_account_success(account);
// attempt to rejoin rooms with passwords
@ -97,6 +101,9 @@ sv_ev_lost_connection(void)
muc_invites_clear();
chat_sessions_clear();
ui_disconnected();
#ifdef HAVE_LIBGPGME
p_gpg_on_disconnect();
#endif
}
void
@ -264,9 +271,8 @@ sv_ev_incoming_message(char *barejid, char *resource, char *message, char *enc_m
// OTR unsupported, PGP supported
#ifndef PROF_HAVE_LIBOTR
#ifdef PROF_HAVE_LIBGPGME
prof_enc_t enc_mode = chatwin->enc_mode;
if (enc_message) {
char *decrypted = p_gpg_decrypt(jid->barejid, enc_message);
char *decrypted = p_gpg_decrypt(barejid, enc_message);
if (decrypted) {
ui_incoming_msg(chatwin, resource, decrypted, NULL, new_win);
chat_log_pgp_msg_in(barejid, decrypted);

View File

@ -35,12 +35,16 @@
#include <locale.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <gpgme.h>
#include "pgp/gpg.h"
#include "log.h"
#include "common.h"
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----"
#define PGP_SIGNATURE_FOOTER "-----END PGP SIGNATURE-----"
@ -50,8 +54,12 @@
static const char *libversion;
static GHashTable *fingerprints;
static gchar *fpsloc;
static GKeyFile *fpskeyfile;
static char* _remove_header_footer(char *str, const char * const footer);
static char* _add_header_footer(const char * const str, const char * const header, const char * const footer);
static void _save_fps(void);
void
p_gpg_init(void)
@ -67,6 +75,135 @@ void
p_gpg_close(void)
{
g_hash_table_destroy(fingerprints);
fingerprints = NULL;
g_key_file_free(fpskeyfile);
fpskeyfile = NULL;
free(fpsloc);
fpsloc = NULL;
}
void
p_gpg_on_connect(const char * const barejid)
{
gchar *data_home = xdg_get_data_home();
GString *fpsfile = g_string_new(data_home);
free(data_home);
gchar *account_dir = str_replace(barejid, "@", "_at_");
g_string_append(fpsfile, "/profanity/pgp/");
g_string_append(fpsfile, account_dir);
free(account_dir);
// mkdir if doesn't exist for account
errno = 0;
int res = g_mkdir_with_parents(fpsfile->str, S_IRWXU);
if (res == -1) {
char *errmsg = strerror(errno);
if (errmsg) {
log_error("Error creating directory: %s, %s", fpsfile->str, errmsg);
} else {
log_error("Error creating directory: %s", fpsfile->str);
}
}
// create or read fingerprints keyfile
g_string_append(fpsfile, "/fingerprints");
fpsloc = fpsfile->str;
g_string_free(fpsfile, FALSE);
if (g_file_test(fpsloc, G_FILE_TEST_EXISTS)) {
g_chmod(fpsloc, S_IRUSR | S_IWUSR);
}
fpskeyfile = g_key_file_new();
g_key_file_load_from_file(fpskeyfile, fpsloc, G_KEY_FILE_KEEP_COMMENTS, NULL);
// load each keyid
gsize len = 0;
gchar **jids = g_key_file_get_groups(fpskeyfile, &len);
gpgme_ctx_t ctx;
gpgme_error_t error = gpgme_new(&ctx);
if (error) {
log_error("GPG: Failed to create gpgme context. %s %s", gpgme_strsource(error), gpgme_strerror(error));
g_strfreev(jids);
return;
}
int i = 0;
for (i = 0; i < len; i++) {
GError *gerr = NULL;
gchar *jid = jids[i];
gchar *keyid = g_key_file_get_string(fpskeyfile, jid, "keyid", &gerr);
if (gerr) {
log_error("Error loading PGP key id for %s", jid);
g_error_free(gerr);
} else {
gpgme_key_t key = NULL;
error = gpgme_get_key(ctx, keyid, &key, 1);
if (error || key == NULL) {
log_error("GPG: Failed to get key. %s %s", gpgme_strsource(error), gpgme_strerror(error));
continue;
}
g_hash_table_replace(fingerprints, strdup(jid), strdup(key->subkeys->fpr));
gpgme_key_release(key);
}
}
gpgme_release(ctx);
g_strfreev(jids);
_save_fps();
}
void
p_gpg_on_disconnect(void)
{
if (fingerprints) {
g_hash_table_destroy(fingerprints);
fingerprints = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
}
if (fpskeyfile) {
g_key_file_free(fpskeyfile);
fpskeyfile = NULL;
}
if (fpsloc) {
free(fpsloc);
fpsloc = NULL;
}
}
gboolean
p_gpg_addkey(const char * const jid, const char * const keyid)
{
gpgme_ctx_t ctx;
gpgme_error_t error = gpgme_new(&ctx);
if (error) {
log_error("GPG: Failed to create gpgme context. %s %s", gpgme_strsource(error), gpgme_strerror(error));
return FALSE;
}
gpgme_key_t key = NULL;
error = gpgme_get_key(ctx, keyid, &key, 1);
if (error || key == NULL) {
log_error("GPG: Failed to get key. %s %s", gpgme_strsource(error), gpgme_strerror(error));
return FALSE;
}
// save to ID keyfile
g_key_file_set_string(fpskeyfile, jid, "keyid", keyid);
_save_fps();
// update in memory fingerprint list
g_hash_table_replace(fingerprints, strdup(jid), strdup(key->subkeys->fpr));
gpgme_key_release(key);
return TRUE;
}
GSList *
@ -378,3 +515,13 @@ _add_header_footer(const char * const str, const char * const header, const char
return result;
}
static void
_save_fps(void)
{
gsize g_data_size;
gchar *g_fps_data = g_key_file_to_data(fpskeyfile, &g_data_size, NULL);
g_file_set_contents(fpsloc, g_fps_data, g_data_size, NULL);
g_chmod(fpsloc, S_IRUSR | S_IWUSR);
g_free(g_fps_data);
}

View File

@ -43,7 +43,10 @@ typedef struct pgp_key_t {
void p_gpg_init(void);
void p_gpg_close(void);
void p_gpg_on_connect(const char * const barejid);
void p_gpg_on_disconnect(void);
GSList* p_gpg_list_keys(void);
gboolean p_gpg_addkey(const char * const jid, const char * const keyid);
GHashTable* p_gpg_fingerprints(void);
gboolean p_gpg_available(const char * const barejid);
const char* p_gpg_libver(void);

View File

@ -254,7 +254,7 @@ ui_resize(void)
resizeterm(w.ws_row, w.ws_col);
refresh();
log_info("Resizing UI");
log_debug("Resizing UI");
title_bar_resize();
wins_resize_all();
status_bar_resize();

View File

@ -38,3 +38,12 @@ char * p_gpg_decrypt(const char * const barejid, const char * const cipher)
{
return NULL;
}
void p_gpg_on_connect(const char * const barejid) {}
void p_gpg_on_disconnect(void) {}
gboolean p_gpg_addkey(const char * const jid, const char * const keyid)
{
return TRUE;
}