mirror of
https://github.com/profanity-im/profanity.git
synced 2024-12-04 14:46:46 -05:00
Added /pgp setkey command
This commit is contained in:
parent
2d3537515d
commit
358e9d6af0
@ -869,18 +869,19 @@ static struct cmd_t command_defs[] =
|
|||||||
NULL } } },
|
NULL } } },
|
||||||
|
|
||||||
{ "/pgp",
|
{ "/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.",
|
||||||
{ "/pgp command [args..]",
|
{ "/pgp command [args..]",
|
||||||
"---------------------",
|
"---------------------",
|
||||||
"Open PGP commands.",
|
"Open PGP commands.",
|
||||||
"",
|
"",
|
||||||
"keys : List private keys.",
|
"keys : List all keys.",
|
||||||
"libver : Show which version of the libgpgme library is being used.",
|
"libver : Show which version of the libgpgme library is being used.",
|
||||||
"fps : Show received fingerprints.",
|
"fps : Show known fingerprints.",
|
||||||
"start [contact] : Start PGP encrypted chat, current contact will be used if not specified.",
|
"setkey contact keyid : Manually associate a key ID with a JID.",
|
||||||
"end : End PGP encrypted chat with the current recipient.",
|
"start [contact] : Start PGP encrypted chat, current contact will be used if not specified.",
|
||||||
"log on|off|redact : PGP message logging, default: redact.",
|
"end : End PGP encrypted chat with the current recipient.",
|
||||||
|
"log on|off|redact : PGP message logging, default: redact.",
|
||||||
NULL } } },
|
NULL } } },
|
||||||
|
|
||||||
{ "/otr",
|
{ "/otr",
|
||||||
@ -1611,6 +1612,7 @@ cmd_init(void)
|
|||||||
pgp_ac = autocomplete_new();
|
pgp_ac = autocomplete_new();
|
||||||
autocomplete_add(pgp_ac, "keys");
|
autocomplete_add(pgp_ac, "keys");
|
||||||
autocomplete_add(pgp_ac, "fps");
|
autocomplete_add(pgp_ac, "fps");
|
||||||
|
autocomplete_add(pgp_ac, "setkey");
|
||||||
autocomplete_add(pgp_ac, "libver");
|
autocomplete_add(pgp_ac, "libver");
|
||||||
autocomplete_add(pgp_ac, "start");
|
autocomplete_add(pgp_ac, "start");
|
||||||
autocomplete_add(pgp_ac, "end");
|
autocomplete_add(pgp_ac, "end");
|
||||||
@ -2503,6 +2505,11 @@ _pgp_autocomplete(ProfWin *window, const char * const input)
|
|||||||
return found;
|
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);
|
found = autocomplete_param_with_ac(input, "/pgp", pgp_ac, TRUE);
|
||||||
if (found) {
|
if (found) {
|
||||||
return found;
|
return found;
|
||||||
|
@ -680,6 +680,9 @@ cmd_disconnect(ProfWin *window, gchar **args, struct cmd_help_t help)
|
|||||||
muc_invites_clear();
|
muc_invites_clear();
|
||||||
chat_sessions_clear();
|
chat_sessions_clear();
|
||||||
ui_disconnected();
|
ui_disconnected();
|
||||||
|
#ifdef HAVE_LIBGPGME
|
||||||
|
p_gpg_on_disconnect();
|
||||||
|
#endif
|
||||||
free(jid);
|
free(jid);
|
||||||
} else {
|
} else {
|
||||||
cons_show("You are not currently connected.");
|
cons_show("You are not currently connected.");
|
||||||
@ -4192,6 +4195,35 @@ cmd_pgp(ProfWin *window, gchar **args, struct cmd_help_t help)
|
|||||||
return TRUE;
|
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) {
|
if (g_strcmp0(args[0], "fps") == 0) {
|
||||||
jabber_conn_status_t conn_status = jabber_get_connection_status();
|
jabber_conn_status_t conn_status = jabber_get_connection_status();
|
||||||
if (conn_status != JABBER_CONNECTED) {
|
if (conn_status != JABBER_CONNECTED) {
|
||||||
@ -4201,11 +4233,11 @@ cmd_pgp(ProfWin *window, gchar **args, struct cmd_help_t help)
|
|||||||
GHashTable *fingerprints = p_gpg_fingerprints();
|
GHashTable *fingerprints = p_gpg_fingerprints();
|
||||||
GList *jids = g_hash_table_get_keys(fingerprints);
|
GList *jids = g_hash_table_get_keys(fingerprints);
|
||||||
if (!jids) {
|
if (!jids) {
|
||||||
cons_show("No PGP fingerprints received.");
|
cons_show("No PGP fingerprints available.");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cons_show("Received PGP fingerprints:");
|
cons_show("Known PGP fingerprints:");
|
||||||
GList *curr = jids;
|
GList *curr = jids;
|
||||||
while (curr) {
|
while (curr) {
|
||||||
char *jid = curr->data;
|
char *jid = curr->data;
|
||||||
@ -4314,6 +4346,7 @@ cmd_pgp(ProfWin *window, gchar **args, struct cmd_help_t help)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cons_show("Usage: %s", help.usage);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
#else
|
#else
|
||||||
cons_show("This version of Profanity has not been built with PGP support enabled");
|
cons_show("This version of Profanity has not been built with PGP support enabled");
|
||||||
|
@ -63,6 +63,10 @@ sv_ev_login_account_success(char *account_name)
|
|||||||
otr_on_connect(account);
|
otr_on_connect(account);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBGPGME
|
||||||
|
p_gpg_on_connect(account->jid);
|
||||||
|
#endif
|
||||||
|
|
||||||
ui_handle_login_account_success(account);
|
ui_handle_login_account_success(account);
|
||||||
|
|
||||||
// attempt to rejoin rooms with passwords
|
// attempt to rejoin rooms with passwords
|
||||||
@ -97,6 +101,9 @@ sv_ev_lost_connection(void)
|
|||||||
muc_invites_clear();
|
muc_invites_clear();
|
||||||
chat_sessions_clear();
|
chat_sessions_clear();
|
||||||
ui_disconnected();
|
ui_disconnected();
|
||||||
|
#ifdef HAVE_LIBGPGME
|
||||||
|
p_gpg_on_disconnect();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
147
src/pgp/gpg.c
147
src/pgp/gpg.c
@ -35,12 +35,16 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
#include <gpgme.h>
|
#include <gpgme.h>
|
||||||
|
|
||||||
#include "pgp/gpg.h"
|
#include "pgp/gpg.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----"
|
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----"
|
||||||
#define PGP_SIGNATURE_FOOTER "-----END PGP SIGNATURE-----"
|
#define PGP_SIGNATURE_FOOTER "-----END PGP SIGNATURE-----"
|
||||||
@ -50,8 +54,12 @@
|
|||||||
static const char *libversion;
|
static const char *libversion;
|
||||||
static GHashTable *fingerprints;
|
static GHashTable *fingerprints;
|
||||||
|
|
||||||
|
static gchar *fpsloc;
|
||||||
|
static GKeyFile *fpskeyfile;
|
||||||
|
|
||||||
static char* _remove_header_footer(char *str, const char * const footer);
|
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 char* _add_header_footer(const char * const str, const char * const header, const char * const footer);
|
||||||
|
static void _save_fps(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
p_gpg_init(void)
|
p_gpg_init(void)
|
||||||
@ -67,6 +75,135 @@ void
|
|||||||
p_gpg_close(void)
|
p_gpg_close(void)
|
||||||
{
|
{
|
||||||
g_hash_table_destroy(fingerprints);
|
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 *
|
GSList *
|
||||||
@ -378,3 +515,13 @@ _add_header_footer(const char * const str, const char * const header, const char
|
|||||||
|
|
||||||
return result;
|
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);
|
||||||
|
}
|
||||||
|
@ -43,7 +43,10 @@ typedef struct pgp_key_t {
|
|||||||
|
|
||||||
void p_gpg_init(void);
|
void p_gpg_init(void);
|
||||||
void p_gpg_close(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);
|
GSList* p_gpg_list_keys(void);
|
||||||
|
gboolean p_gpg_addkey(const char * const jid, const char * const keyid);
|
||||||
GHashTable* p_gpg_fingerprints(void);
|
GHashTable* p_gpg_fingerprints(void);
|
||||||
gboolean p_gpg_available(const char * const barejid);
|
gboolean p_gpg_available(const char * const barejid);
|
||||||
const char* p_gpg_libver(void);
|
const char* p_gpg_libver(void);
|
||||||
|
@ -38,3 +38,12 @@ char * p_gpg_decrypt(const char * const barejid, const char * const cipher)
|
|||||||
{
|
{
|
||||||
return NULL;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user