diff options
author | DebXWoody <stefan@debxwoody.de> | 2020-06-21 09:43:42 +0200 |
---|---|---|
committer | Michael Vetter <jubalh@iodoru.org> | 2020-06-29 19:05:41 +0200 |
commit | 2c94ee5a88f64332a3f41f41a4d314fc52200e31 (patch) | |
tree | 6209fd4796609a7706f950b18a9bb652c6c137fb /src/command | |
parent | 3afd854dc862696c4842b2ed93efcad44d617910 (diff) | |
download | profani-tty-2c94ee5a88f64332a3f41f41a4d314fc52200e31.tar.gz |
Feature request - XEP-0373: OpenPGP for XMPP (OX)
Basic implementation of XEP-0373: OpenPGP for XMPP. https://xmpp.org/extensions/xep-0373.html Command /ox Issue: #1331
Diffstat (limited to 'src/command')
-rw-r--r-- | src/command/cmd_ac.c | 97 | ||||
-rw-r--r-- | src/command/cmd_defs.c | 42 | ||||
-rw-r--r-- | src/command/cmd_funcs.c | 163 | ||||
-rw-r--r-- | src/command/cmd_funcs.h | 3 |
4 files changed, 305 insertions, 0 deletions
diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 09de573c..eefca0cc 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -78,6 +78,7 @@ static char* _otr_autocomplete(ProfWin *window, const char *const input, gboolea #endif #ifdef HAVE_LIBGPGME static char* _pgp_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _ox_autocomplete(ProfWin *window, const char *const input, gboolean previous); #endif #ifdef HAVE_OMEMO static char* _omemo_autocomplete(ProfWin *window, const char *const input, gboolean previous); @@ -224,6 +225,9 @@ static Autocomplete receipts_ac; static Autocomplete pgp_ac; static Autocomplete pgp_log_ac; static Autocomplete pgp_sendfile_ac; +static Autocomplete ox_ac; +static Autocomplete ox_log_ac; +static Autocomplete ox_sendfile_ac; #endif static Autocomplete tls_ac; static Autocomplete titlebar_ac; @@ -261,6 +265,13 @@ static Autocomplete correction_ac; static Autocomplete avatar_ac; static Autocomplete executable_ac; +/*! + * \brief Initialization of auto completion for commands. + * + * This function implements the auto completion for profanity's commands. + * + */ + void cmd_ac_init(void) { @@ -842,6 +853,29 @@ cmd_ac_init(void) pgp_sendfile_ac = autocomplete_new(); autocomplete_add(pgp_sendfile_ac, "on"); autocomplete_add(pgp_sendfile_ac, "off"); + + // XEP-0373: OX + ox_ac = autocomplete_new(); + autocomplete_add(ox_ac, "keys"); + autocomplete_add(ox_ac, "contacts"); + autocomplete_add(ox_ac, "start"); + autocomplete_add(ox_ac, "end"); + autocomplete_add(ox_ac, "log"); + autocomplete_add(ox_ac, "char"); + autocomplete_add(ox_ac, "sendfile"); + autocomplete_add(ox_ac, "announce"); + autocomplete_add(ox_ac, "discover"); + autocomplete_add(ox_ac, "request"); + + pgp_log_ac = autocomplete_new(); + autocomplete_add(ox_log_ac, "on"); + autocomplete_add(ox_log_ac, "off"); + autocomplete_add(ox_log_ac, "redact"); + + pgp_sendfile_ac = autocomplete_new(); + autocomplete_add(ox_sendfile_ac, "on"); + autocomplete_add(ox_sendfile_ac, "off"); + #endif tls_ac = autocomplete_new(); @@ -1707,6 +1741,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previ #endif #ifdef HAVE_LIBGPGME g_hash_table_insert(ac_funcs, "/pgp", _pgp_autocomplete); + g_hash_table_insert(ac_funcs, "/ox", _ox_autocomplete); #endif #ifdef HAVE_OMEMO g_hash_table_insert(ac_funcs, "/omemo", _omemo_autocomplete); @@ -2420,6 +2455,68 @@ _pgp_autocomplete(ProfWin *window, const char *const input, gboolean previous) return NULL; } + +/*! + * \brief Auto completion for XEP-0373: OpenPGP for XMPP command. + * + * + */ +static char* +_ox_autocomplete(ProfWin *window, const char *const input, gboolean previous) +{ + char *found = NULL; + + jabber_conn_status_t conn_status = connection_get_status(); + + if (conn_status == JABBER_CONNECTED) { + found = autocomplete_param_with_func(input, "/ox start", roster_contact_autocomplete, previous, NULL); + if (found) { + return found; + } + } + + found = autocomplete_param_with_ac(input, "/ox log", ox_log_ac, TRUE, previous); + if (found) { + return found; + } + + found = autocomplete_param_with_ac(input, "/ox sendfile", ox_sendfile_ac, TRUE, previous); + if (found) { + return found; + } + + gboolean result; + gchar **args = parse_args(input, 2, 3, &result); + if ((strncmp(input, "/ox", 4) == 0) && (result == TRUE)) { + GString *beginning = g_string_new("/ox "); + g_string_append(beginning, args[0]); + if (args[1]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + } + found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key, previous, NULL); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } + g_strfreev(args); + + if (conn_status == JABBER_CONNECTED) { + found = autocomplete_param_with_func(input, "/ox setkey", roster_barejid_autocomplete, previous, NULL); + if (found) { + return found; + } + } + + found = autocomplete_param_with_ac(input, "/ox", ox_ac, TRUE, previous); + if (found) { + return found; + } + + return NULL; +} #endif #ifdef HAVE_OMEMO diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 85140430..815fe9d8 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -1691,6 +1691,48 @@ static struct cmd_t command_defs[] = "/pgp char P") }, +// XEP-0373: OpenPGP for XMPP +#ifdef HAVE_LIBGPGME + { "/ox", + parse_args, 1, 3, NULL, + CMD_NOSUBFUNCS + CMD_MAINFUNC(cmd_ox) + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_UI) + CMD_SYN( + "/ox keys", + "/ox contacts", + "/ox start [<contact>]", + "/ox end", + "/ox log on|off|redact", + "/ox char <char>", + "/ox sendfile on|off", + "/ox announce <file>", + "/ox discover", + "/ox request <jid>") + CMD_DESC( + "OpenPGP (OX) commands to manage keys, and perform PGP encryption during chat sessions. ") + CMD_ARGS( + { "keys", "List all keys known to the system." }, + { "contacts", "Show contacts with assigned public keys." }, + { "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", "Enable or disable plaintext logging of PGP encrypted messages." }, + { "log redact", "Log PGP encrypted messages, but replace the contents with [redacted]. This is the default." }, + { "char <char>", "Set the character to be displayed next to PGP encrypted messages." }, + { "announce <file>", "Announce a public key by pushing it on the XMPP Server"}, + { "discover <jid>", "Discover public keys of a jid "}, + { "request <jid>", "Request public keys"}, + { "sendfile on|off", "Allow /sendfile to send unencrypted files while otherwise using PGP."}) + CMD_EXAMPLES( + "/ox log off", + "/ox start odin@valhalla.edda", + "/ox end", + "/ox char X") + }, +#endif // HAVE_LIBGPGME + { "/otr", parse_args, 1, 3, NULL, CMD_SUBFUNCS( diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 735e197b..7d779e87 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -7418,6 +7418,169 @@ cmd_pgp(ProfWin *window, const char *const command, gchar **args) #endif } +#ifdef HAVE_LIBGPGME + +/*! + * \brief Command for XEP-0373: OpenPGP for XMPP + * + */ + +gboolean +cmd_ox(ProfWin *window, const char *const command, gchar **args) +{ + if (args[0] == NULL) { + cons_bad_cmd_usage(command); + return TRUE; + } + + // The '/ox keys' command - same like in pgp + // Should we move this to a common command + // e.g. '/openpgp keys'?. + else if (g_strcmp0(args[0], "keys") == 0) { + GHashTable *keys = p_gpg_list_keys(); + if (!keys || g_hash_table_size(keys) == 0) { + cons_show("No keys found"); + return TRUE; + } + + cons_show("OpenPGP keys:"); + GList *keylist = g_hash_table_get_keys(keys); + GList *curr = keylist; + while (curr) { + ProfPGPKey *key = g_hash_table_lookup(keys, curr->data); + cons_show(" %s", key->name); + cons_show(" ID : %s", key->id); + char *format_fp = p_gpg_format_fp_str(key->fp); + cons_show(" Fingerprint : %s", format_fp); + free(format_fp); + if (key->secret) { + cons_show(" Type : PUBLIC, PRIVATE"); + } else { + cons_show(" Type : PUBLIC"); + } + curr = g_list_next(curr); + } + g_list_free(keylist); + p_gpg_free_keys(keys); + return TRUE; + } + + else if (g_strcmp0(args[0], "contacts") == 0) { + GHashTable *keys = ox_gpg_public_keys(); + cons_show("OpenPGP keys:"); + GList *keylist = g_hash_table_get_keys(keys); + GList *curr = keylist; + + + GSList *roster_list = NULL; + jabber_conn_status_t conn_status = connection_get_status(); + if (conn_status != JABBER_CONNECTED) { + cons_show("You are not currently connected."); + } else { + roster_list = roster_get_contacts(ROSTER_ORD_NAME); + } + + while (curr) { + ProfPGPKey *key = g_hash_table_lookup(keys, curr->data); + PContact contact = NULL; + if (roster_list) { + GSList *curr_c = roster_list; + while ( !contact && curr_c){ + contact = curr_c->data; + const char *jid = p_contact_barejid(contact); + GString* xmppuri = g_string_new("xmpp:"); + g_string_append(xmppuri, jid); + if( g_strcmp0(key->name, xmppuri->str)) { + contact = NULL; + } + curr_c = g_slist_next(curr_c); + } + } + + if(contact) { + cons_show("%s - %s", key->fp, key->name); + } else { + cons_show("%s - %s (not in roster)", key->fp, key->name); + } + curr = g_list_next(curr); + } + + } else if (g_strcmp0(args[0], "start") == 0) { + jabber_conn_status_t conn_status = connection_get_status(); + if (conn_status != JABBER_CONNECTED) { + cons_show("You must be connected to start OX encrpytion."); + return TRUE; + } + + if (window->type != WIN_CHAT && args[1] == NULL) { + cons_show("You must be in a regular chat window to start OX encrpytion."); + return TRUE; + } + + ProfChatWin *chatwin = NULL; + + if (args[1]) { + char *contact = args[1]; + char *barejid = roster_barejid_from_name(contact); + if (barejid == NULL) { + barejid = contact; + } + + chatwin = wins_get_chat(barejid); + if (!chatwin) { + chatwin = chatwin_new(barejid); + } + ui_focus_win((ProfWin*)chatwin); + } else { + chatwin = (ProfChatWin*)window; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + } + + if (chatwin->is_otr) { + win_println(window, THEME_DEFAULT, "!", "You must end the OTR session to start OX encryption."); + return TRUE; + } + + if (chatwin->pgp_send) { + win_println(window, THEME_DEFAULT, "!", "You must end the PGP session to start OX encryption."); + return TRUE; + } + + if (chatwin->is_ox) { + win_println(window, THEME_DEFAULT, "!", "You have already started OX encryption."); + return TRUE; + } + + ProfAccount *account = accounts_get_account(session_get_account_name()); + + if ( !ox_is_private_key_available(account->jid) ) { + win_println(window, THEME_DEFAULT, "!", "No private OpenPGP found, cannot start OX encryption."); + account_free(account); + return TRUE; + } + account_free(account); + + if (!ox_is_public_key_available(chatwin->barejid)) { + win_println(window, THEME_DEFAULT, "!", "No OX-OpenPGP key found for %s.", chatwin->barejid); + return TRUE; + } + + chatwin->is_ox = TRUE; + win_println(window, THEME_DEFAULT, "!", "OX encryption enabled."); + return TRUE; + } else if (g_strcmp0(args[0], "push") == 0) { + if( args[1] ) { + cons_show("Push file...%s ", args[1] ); + } else { + cons_show("Filename is required"); + } + } else { + cons_show("OX not implemented"); + } + return TRUE; +} +#endif // HAVE_LIBGPGME + gboolean cmd_otr_char(ProfWin *window, const char *const command, gchar **args) { diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index d0d37efa..b75755cb 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -107,6 +107,9 @@ gboolean cmd_msg(ProfWin *window, const char *const command, gchar **args); gboolean cmd_nick(ProfWin *window, const char *const command, gchar **args); gboolean cmd_notify(ProfWin *window, const char *const command, gchar **args); gboolean cmd_pgp(ProfWin *window, const char *const command, gchar **args); +#ifdef HAVE_LIBGPGME +gboolean cmd_ox(ProfWin *window, const char *const command, gchar **args); +#endif // HAVE_LIBGPGME gboolean cmd_outtype(ProfWin *window, const char *const command, gchar **args); gboolean cmd_prefs(ProfWin *window, const char *const command, gchar **args); gboolean cmd_priority(ProfWin *window, const char *const command, gchar **args); |