mirror of
https://git.jabber.space/devs/cproof.git
synced 2026-07-19 00:46:21 +00:00
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
This commit is contained in:
committed by
Michael Vetter
parent
3afd854dc8
commit
2c94ee5a88
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user