diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/command/command.c | 81 | ||||
-rw-r--r-- | src/command/commands.c | 26 | ||||
-rw-r--r-- | src/config/account.c | 10 | ||||
-rw-r--r-- | src/config/account.h | 4 | ||||
-rw-r--r-- | src/config/accounts.c | 28 | ||||
-rw-r--r-- | src/config/accounts.h | 3 | ||||
-rw-r--r-- | src/event/client_events.c | 4 | ||||
-rw-r--r-- | src/event/client_events.h | 2 | ||||
-rw-r--r-- | src/ui/console.c | 3 | ||||
-rw-r--r-- | src/xmpp/connection.c | 32 | ||||
-rw-r--r-- | src/xmpp/xmpp.h | 2 |
11 files changed, 171 insertions, 24 deletions
diff --git a/src/command/command.c b/src/command/command.c index 1b8def1a..ec8696fe 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -168,12 +168,12 @@ static struct cmd_t command_defs[] = }, { "/connect", - cmd_connect, parse_args, 0, 5, NULL, + cmd_connect, parse_args, 0, 7, NULL, CMD_TAGS( CMD_TAG_CONNECTION) CMD_SYN( "/connect [<account>]", - "/connect <account> [server <server>] [port <port>]") + "/connect <account> [server <server>] [port <port>] [tls force|allow|disable]") CMD_DESC( "Login to a chat service. " "If no account is specified, the default is used if one is configured. " @@ -181,12 +181,16 @@ static struct cmd_t command_defs[] = CMD_ARGS( { "<account>", "The local account you wish to connect with, or a JID if connecting for the first time." }, { "server <server>", "Supply a server if it is different to the domain part of your JID." }, - { "port <port>", "The port to use if different to the default (5222, or 5223 for SSL)." }) + { "port <port>", "The port to use if different to the default (5222, or 5223 for SSL)." }, + { "tls force", "Force TLS connection, and fail if one cannot be established, this is default behaviour." }, + { "tls allow", "Use TLS for the connection if it is available." }, + { "tls disable", "Disable TLS for the connection." }) CMD_EXAMPLES( "/connect", "/connect myuser@gmail.com", "/connect myuser@mycompany.com server talk.google.com", "/connect bob@someplace port 5678", + "/connect me@localhost.test.org server 127.0.0.1 tls disable", "/connect me@chatty server chatty.com port 5443") }, @@ -1491,6 +1495,7 @@ static struct cmd_t command_defs[] = "/account set <account> otr <policy>", "/account set <account> pgpkeyid <pgpkeyid>", "/account set <account> startscript <script>", + "/account set <account> tls force|allow|disable", "/account clear <account> password", "/account clear <account> eval_password", "/account clear <account> server", @@ -1525,6 +1530,9 @@ static struct cmd_t command_defs[] = { "set <account> otr <policy>", "Override global OTR policy for this account, see /otr." }, { "set <account> pgpkeyid <pgpkeyid>", "Set the ID of the PGP key for this account, see /pgp." }, { "set <account> startscript <script>", "Set the script to execute after connecting." }, + { "set <account> tls force", "Force TLS connection, and fail if one cannot be established, this is default behaviour." }, + { "set <account> tls allow", "Use TLS for the connection if it is available." }, + { "set <account> tls disable", "Disable TLS for the connection." }, { "clear <account> server", "Remove the server setting for this account." }, { "clear <account> port", "Remove the port setting for this account." }, { "clear <account> password", "Remove the password setting for this account." }, @@ -1753,6 +1761,7 @@ static Autocomplete otr_ac; static Autocomplete otr_log_ac; static Autocomplete otr_policy_ac; static Autocomplete connect_property_ac; +static Autocomplete tls_property_ac; static Autocomplete statuses_ac; static Autocomplete statuses_setting_ac; static Autocomplete alias_ac; @@ -1944,6 +1953,7 @@ cmd_init(void) autocomplete_add(account_set_ac, "otr"); autocomplete_add(account_set_ac, "pgpkeyid"); autocomplete_add(account_set_ac, "startscript"); + autocomplete_add(account_set_ac, "tls"); account_clear_ac = autocomplete_new(); autocomplete_add(account_clear_ac, "password"); @@ -2075,6 +2085,12 @@ cmd_init(void) connect_property_ac = autocomplete_new(); autocomplete_add(connect_property_ac, "server"); autocomplete_add(connect_property_ac, "port"); + autocomplete_add(connect_property_ac, "tls"); + + tls_property_ac = autocomplete_new(); + autocomplete_add(tls_property_ac, "force"); + autocomplete_add(tls_property_ac, "allow"); + autocomplete_add(tls_property_ac, "disable"); join_property_ac = autocomplete_new(); autocomplete_add(join_property_ac, "nick"); @@ -2249,6 +2265,7 @@ cmd_uninit(void) autocomplete_free(otr_log_ac); autocomplete_free(otr_policy_ac); autocomplete_free(connect_property_ac); + autocomplete_free(tls_property_ac); autocomplete_free(statuses_ac); autocomplete_free(statuses_setting_ac); autocomplete_free(alias_ac); @@ -2435,6 +2452,7 @@ cmd_reset_autocomplete(ProfWin *window) autocomplete_reset(otr_log_ac); autocomplete_reset(otr_policy_ac); autocomplete_reset(connect_property_ac); + autocomplete_reset(tls_property_ac); autocomplete_reset(statuses_ac); autocomplete_reset(statuses_setting_ac); autocomplete_reset(alias_ac); @@ -3786,7 +3804,7 @@ _connect_autocomplete(ProfWin *window, const char * const input) char *found = NULL; gboolean result = FALSE; - gchar **args = parse_args(input, 2, 4, &result); + gchar **args = parse_args(input, 2, 6, &result); if ((strncmp(input, "/connect", 8) == 0) && (result == TRUE)) { GString *beginning = g_string_new("/connect "); @@ -3796,6 +3814,12 @@ _connect_autocomplete(ProfWin *window, const char * const input) g_string_append(beginning, args[1]); g_string_append(beginning, " "); g_string_append(beginning, args[2]); + if (args[3] && args[4]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[3]); + g_string_append(beginning, " "); + g_string_append(beginning, args[4]); + } } found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE); g_string_free(beginning, TRUE); @@ -3807,6 +3831,46 @@ _connect_autocomplete(ProfWin *window, const char * const input) g_strfreev(args); + result = FALSE; + args = parse_args(input, 2, 7, &result); + + if ((strncmp(input, "/connect", 8) == 0) && (result == TRUE)) { + GString *beginning = g_string_new("/connect "); + g_string_append(beginning, args[0]); + int curr = 0; + if (args[1]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + curr = 1; + if (args[2] && args[3]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + g_string_append(beginning, " "); + g_string_append(beginning, args[3]); + curr = 3; + if (args[4] && args[5]) { + g_string_append(beginning, " "); + g_string_append(beginning, args[4]); + g_string_append(beginning, " "); + g_string_append(beginning, args[5]); + curr = 5; + } + } + } + if (curr != 0 && (g_strcmp0(args[curr], "tls") == 0)) { + found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } + } else { + g_string_free(beginning, TRUE); + } + } + + g_strfreev(args); + found = autocomplete_param_with_func(input, "/connect", accounts_find_enabled); if (found) { return found; @@ -3897,6 +3961,15 @@ _account_autocomplete(ProfWin *window, const char * const input) g_strfreev(args); return found; } + } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "tls")) == 0) { + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE); + g_string_free(beginning, TRUE); + if (found) { + g_strfreev(args); + return found; + } #ifdef HAVE_LIBGPGME } else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "pgpkeyid")) == 0) { g_string_append(beginning, " "); diff --git a/src/command/commands.c b/src/command/commands.c index 370c466c..c37af0c7 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -255,7 +255,7 @@ cmd_connect(ProfWin *window, const char * const command, gchar **args) return TRUE; } - gchar *opt_keys[] = { "server", "port", NULL }; + gchar *opt_keys[] = { "server", "port", "tls", NULL }; gboolean parsed; GHashTable *options = parse_options(&args[args[0] ? 1 : 0], opt_keys, &parsed); @@ -267,6 +267,16 @@ cmd_connect(ProfWin *window, const char * const command, gchar **args) char *altdomain = g_hash_table_lookup(options, "server"); + char *tls_policy = g_hash_table_lookup(options, "tls"); + if (tls_policy && + (g_strcmp0(tls_policy, "force") != 0) && + (g_strcmp0(tls_policy, "allow") != 0) && + (g_strcmp0(tls_policy, "disable") != 0)) { + cons_bad_cmd_usage(command); + cons_show(""); + return TRUE; + } + int port = 0; if (g_hash_table_contains(options, "port")) { char *port_str = g_hash_table_lookup(options, "port"); @@ -334,7 +344,7 @@ cmd_connect(ProfWin *window, const char * const command, gchar **args) } else { jid = strdup(lower); char *passwd = ui_ask_password(); - conn_status = cl_ev_connect_jid(jid, passwd, altdomain, port); + conn_status = cl_ev_connect_jid(jid, passwd, altdomain, port, tls_policy); free(passwd); } @@ -386,7 +396,7 @@ cmd_account(ProfWin *window, const char * const command, gchar **args) if (account_name == NULL) { cons_bad_cmd_usage(command); } else { - accounts_add(account_name, NULL, 0); + accounts_add(account_name, NULL, 0, NULL); cons_show("Account created."); cons_show(""); } @@ -590,6 +600,16 @@ cmd_account(ProfWin *window, const char * const command, gchar **args) } else if (strcmp(property, "startscript") == 0) { accounts_set_script_start(account_name, value); cons_show("Updated start script for account %s: %s", account_name, value); + } else if (strcmp(property, "tls") == 0) { + if ((g_strcmp0(value, "force") != 0) + && (g_strcmp0(value, "allow") != 0) + && (g_strcmp0(value, "disable") != 0)) { + cons_show("TLS policy must be one of: force, allow or disable."); + } else { + accounts_set_tls_policy(account_name, value); + cons_show("Updated TLS policy for account %s: %s", account_name, value); + cons_show(""); + } } else if (valid_resource_presence_string(property)) { int intval; char *err_msg = NULL; diff --git a/src/config/account.c b/src/config/account.c index 71b05a96..534d1138 100644 --- a/src/config/account.c +++ b/src/config/account.c @@ -51,7 +51,8 @@ account_new(const gchar * const name, const gchar * const jid, int priority_away, int priority_xa, int priority_dnd, const gchar * const muc_service, const gchar * const muc_nick, const gchar * const otr_policy, GList *otr_manual, GList *otr_opportunistic, - GList *otr_always, const gchar * const pgp_keyid, const char *const startscript) + GList *otr_always, const gchar * const pgp_keyid, const char *const startscript, + gchar *tls_policy) { ProfAccount *new_account = malloc(sizeof(ProfAccount)); @@ -156,6 +157,12 @@ account_new(const gchar * const name, const gchar * const jid, new_account->startscript = NULL; } + if (tls_policy != NULL) { + new_account->tls_policy = strdup(tls_policy); + } else { + new_account->tls_policy = NULL; + } + return new_account; } @@ -224,6 +231,7 @@ account_free(ProfAccount *account) free(account->otr_policy); free(account->pgp_keyid); free(account->startscript); + free(account->tls_policy); g_list_free_full(account->otr_manual, g_free); g_list_free_full(account->otr_opportunistic, g_free); g_list_free_full(account->otr_always, g_free); diff --git a/src/config/account.h b/src/config/account.h index d2b55569..bb5f27ce 100644 --- a/src/config/account.h +++ b/src/config/account.h @@ -61,6 +61,7 @@ typedef struct prof_account_t { GList *otr_always; gchar *pgp_keyid; gchar *startscript; + gchar *tls_policy; } ProfAccount; ProfAccount* account_new(const gchar * const name, const gchar * const jid, @@ -70,7 +71,8 @@ ProfAccount* account_new(const gchar * const name, const gchar * const jid, int priority_away, int priority_xa, int priority_dnd, const gchar * const muc_service, const gchar * const muc_nick, const gchar * const otr_policy, GList *otr_manual, GList *otr_opportunistic, - GList *otr_always, const gchar * const pgp_keyid, const char *const startscript); + GList *otr_always, const gchar * const pgp_keyid, const char *const startscript, + gchar *tls_policy); char* account_create_full_jid(ProfAccount *account); gboolean account_eval_password(ProfAccount *account); void account_free(ProfAccount *account); diff --git a/src/config/accounts.c b/src/config/accounts.c index 7ae34983..43239d76 100644 --- a/src/config/accounts.c +++ b/src/config/accounts.c @@ -120,7 +120,7 @@ accounts_reset_enabled_search(void) } void -accounts_add(const char *account_name, const char *altdomain, const int port) +accounts_add(const char *account_name, const char *altdomain, const int port, const char *const tls_policy) { // set account name and resource const char *barejid = account_name; @@ -144,6 +144,9 @@ accounts_add(const char *account_name, const char *altdomain, const int port) if (port != 0) { g_key_file_set_integer(accounts, account_name, "port", port); } + if (tls_policy) { + g_key_file_set_string(accounts, account_name, "tls.policy", tls_policy); + } Jid *jidp = jid_create(barejid); GString *muc_service = g_string_new("conference."); @@ -269,11 +272,19 @@ accounts_get_account(const char * const name) startscript = g_key_file_get_string(accounts, name, "script.start", NULL); } + gchar *tls_policy = g_key_file_get_string(accounts, name, "tls.policy", NULL); + if (tls_policy && ((g_strcmp0(tls_policy, "force") != 0) && + (g_strcmp0(tls_policy, "allow") != 0) && + (g_strcmp0(tls_policy, "disable") != 0))) { + g_free(tls_policy); + tls_policy = NULL; + } + ProfAccount *new_account = account_new(name, jid, password, eval_password, enabled, server, port, resource, last_presence, login_presence, priority_online, priority_chat, priority_away, priority_xa, priority_dnd, muc_service, muc_nick, otr_policy, otr_manual, - otr_opportunistic, otr_always, pgp_keyid, startscript); + otr_opportunistic, otr_always, pgp_keyid, startscript, tls_policy); g_free(jid); g_free(password); @@ -287,6 +298,7 @@ accounts_get_account(const char * const name) g_free(otr_policy); g_free(pgp_keyid); g_free(startscript); + g_free(tls_policy); return new_account; } @@ -354,7 +366,8 @@ accounts_rename(const char * const account_name, const char * const new_name) "otr.always", "pgp.keyid", "last.activity", - "script.start" + "script.start", + "tls.policy" }; int i; @@ -679,6 +692,15 @@ accounts_set_otr_policy(const char * const account_name, const char * const valu } void +accounts_set_tls_policy(const char * const account_name, const char * const value) +{ + if (accounts_account_exists(account_name)) { + g_key_file_set_string(accounts, account_name, "tls.policy", value); + _save_accounts(); + } +} + +void accounts_set_priority_online(const char * const account_name, const gint value) { if (accounts_account_exists(account_name)) { diff --git a/src/config/accounts.h b/src/config/accounts.h index 610ed6a3..bd9d9307 100644 --- a/src/config/accounts.h +++ b/src/config/accounts.h @@ -47,7 +47,7 @@ char * accounts_find_all(const char * const prefix); char * accounts_find_enabled(const char * const prefix); void accounts_reset_all_search(void); void accounts_reset_enabled_search(void); -void accounts_add(const char *jid, const char *altdomain, const int port); +void accounts_add(const char *jid, const char *altdomain, const int port, const char *const tls_policy); int accounts_remove(const char *jid); gchar** accounts_get_list(void); ProfAccount* accounts_get_account(const char * const name); @@ -65,6 +65,7 @@ void accounts_set_eval_password(const char * const account_name, const char * co void accounts_set_muc_service(const char * const account_name, const char * const value); void accounts_set_muc_nick(const char * const account_name, const char * const value); void accounts_set_otr_policy(const char * const account_name, const char * const value); +void accounts_set_tls_policy(const char * const account_name, const char * const value); void accounts_set_last_presence(const char * const account_name, const char * const value); void accounts_set_last_status(const char * const account_name, const char * const value); void accounts_set_last_activity(const char * const account_name); diff --git a/src/event/client_events.c b/src/event/client_events.c index c3e5070d..8f744c7e 100644 --- a/src/event/client_events.c +++ b/src/event/client_events.c @@ -48,10 +48,10 @@ #endif jabber_conn_status_t -cl_ev_connect_jid(const char * const jid, const char * const passwd, const char * const altdomain, const int port) +cl_ev_connect_jid(const char * const jid, const char * const passwd, const char * const altdomain, const int port, const char *const tls_policy) { cons_show("Connecting as %s", jid); - return jabber_connect_with_details(jid, passwd, altdomain, port); + return jabber_connect_with_details(jid, passwd, altdomain, port, tls_policy); } jabber_conn_status_t diff --git a/src/event/client_events.h b/src/event/client_events.h index ea1bdef7..dbd053f3 100644 --- a/src/event/client_events.h +++ b/src/event/client_events.h @@ -35,7 +35,7 @@ #ifndef CLIENT_EVENTS_H #define CLIENT_EVENTS_H -jabber_conn_status_t cl_ev_connect_jid(const char * const jid, const char * const passwd, const char * const altdomain, const int port); +jabber_conn_status_t cl_ev_connect_jid(const char * const jid, const char * const passwd, const char * const altdomain, const int port, const char *const tls_policy); jabber_conn_status_t cl_ev_connect_account(ProfAccount *account); void cl_ev_presence_send(const resource_presence_t presence_type, const char * const msg, const int idle_secs); diff --git a/src/ui/console.c b/src/ui/console.c index 37316d83..bda808c7 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -707,6 +707,9 @@ cons_show_account(ProfAccount *account) if (account->muc_nick) { cons_show ("muc nick : %s", account->muc_nick); } + if (account->tls_policy) { + cons_show ("TLS policy : %s", account->tls_policy); + } if (account->last_presence) { cons_show ("Last presence : %s", account->last_presence); } diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index fa29a70e..4b3ef803 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -87,6 +87,7 @@ static struct { char *passwd; char *altdomain; int port; + char *tls_policy; } saved_details; static GTimer *reconnect_timer; @@ -101,7 +102,7 @@ static void _xmpp_file_logger(void * const userdata, static xmpp_log_t * _xmpp_get_file_logger(); static jabber_conn_status_t _jabber_connect(const char * const fulljid, - const char * const passwd, const char * const altdomain, int port); + const char * const passwd, const char * const altdomain, int port, const char *const tls_policy); static void _jabber_reconnect(void); @@ -149,7 +150,7 @@ jabber_connect_with_account(const ProfAccount * const account) // connect with fulljid Jid *jidp = jid_create_from_bare_and_resource(account->jid, account->resource); jabber_conn_status_t result = - _jabber_connect(jidp->fulljid, account->password, account->server, account->port); + _jabber_connect(jidp->fulljid, account->password, account->server, account->port, account->tls_policy); jid_destroy(jidp); return result; @@ -157,7 +158,7 @@ jabber_connect_with_account(const ProfAccount * const account) jabber_conn_status_t jabber_connect_with_details(const char * const jid, - const char * const passwd, const char * const altdomain, const int port) + const char * const passwd, const char * const altdomain, const int port, const char *const tls_policy) { assert(jid != NULL); assert(passwd != NULL); @@ -175,6 +176,11 @@ jabber_connect_with_details(const char * const jid, } else { saved_details.port = 0; } + if (tls_policy) { + saved_details.tls_policy = strdup(tls_policy); + } else { + saved_details.tls_policy = NULL; + } // use 'profanity' when no resourcepart in provided jid Jid *jidp = jid_create(jid); @@ -189,7 +195,12 @@ jabber_connect_with_details(const char * const jid, // connect with fulljid log_info("Connecting without account, JID: %s", saved_details.jid); - return _jabber_connect(saved_details.jid, passwd, saved_details.altdomain, saved_details.port); + return _jabber_connect( + saved_details.jid, + passwd, + saved_details.altdomain, + saved_details.port, + saved_details.tls_policy); } void @@ -363,6 +374,7 @@ _connection_free_saved_details(void) FREE_SET_NULL(saved_details.jid); FREE_SET_NULL(saved_details.passwd); FREE_SET_NULL(saved_details.altdomain); + FREE_SET_NULL(saved_details.tls_policy); } void @@ -384,7 +396,7 @@ _connection_certfail_cb(const char * const certname, const char * const certfp, static jabber_conn_status_t _jabber_connect(const char * const fulljid, const char * const passwd, - const char * const altdomain, int port) + const char * const altdomain, int port, const char *const tls_policy) { assert(fulljid != NULL); assert(passwd != NULL); @@ -429,6 +441,12 @@ _jabber_connect(const char * const fulljid, const char * const passwd, xmpp_conn_set_jid(jabber_conn.conn, fulljid); xmpp_conn_set_pass(jabber_conn.conn, passwd); + if (!tls_policy || (g_strcmp0(tls_policy, "force") == 0)) { + xmpp_conn_set_flags(jabber_conn.conn, XMPP_CONN_FLAG_MANDATORY_TLS); + } else if (g_strcmp0(tls_policy, "disable") == 0) { + xmpp_conn_set_flags(jabber_conn.conn, XMPP_CONN_FLAG_DISABLE_TLS); + } + #ifdef HAVE_LIBMESODE char *cert_path = prefs_get_string(PREF_TLS_CERTPATH); if (cert_path) { @@ -463,7 +481,7 @@ _jabber_reconnect(void) } else { char *fulljid = create_fulljid(account->jid, account->resource); log_debug("Attempting reconnect with account %s", account->name); - _jabber_connect(fulljid, saved_account.passwd, account->server, account->port); + _jabber_connect(fulljid, saved_account.passwd, account->server, account->port, account->tls_policy); free(fulljid); g_timer_start(reconnect_timer); } @@ -489,7 +507,7 @@ _connection_handler(xmpp_conn_t * const conn, // logged in without account, use details to create new account } else { log_debug("Connection handler: logged in with jid: %s", saved_details.name); - accounts_add(saved_details.name, saved_details.altdomain, saved_details.port); + accounts_add(saved_details.name, saved_details.altdomain, saved_details.port, saved_details.tls_policy); accounts_set_jid(saved_details.name, saved_details.jid); sv_ev_login_account_success(saved_details.name, secured); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index ddf83c64..43106fa6 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -139,7 +139,7 @@ typedef struct data_form_t { // connection functions void jabber_init(void); jabber_conn_status_t jabber_connect_with_details(const char * const jid, - const char * const passwd, const char * const altdomain, const int port); + const char * const passwd, const char * const altdomain, const int port, const char *const tls_policy); jabber_conn_status_t jabber_connect_with_account(const ProfAccount * const account); void jabber_disconnect(void); void jabber_shutdown(void); |