diff options
Diffstat (limited to 'src/fe-common/irc')
-rw-r--r-- | src/fe-common/irc/fe-irc-queries.c | 7 | ||||
-rw-r--r-- | src/fe-common/irc/fe-irc-server.c | 47 | ||||
-rw-r--r-- | src/fe-common/irc/fe-ircnet.c | 40 | ||||
-rw-r--r-- | src/fe-common/irc/fe-netjoin.c | 45 | ||||
-rw-r--r-- | src/fe-common/irc/fe-netsplit.c | 32 | ||||
-rw-r--r-- | src/fe-common/irc/fe-sasl.c | 29 |
6 files changed, 142 insertions, 58 deletions
diff --git a/src/fe-common/irc/fe-irc-queries.c b/src/fe-common/irc/fe-irc-queries.c index b2faefbc..c928a94a 100644 --- a/src/fe-common/irc/fe-irc-queries.c +++ b/src/fe-common/irc/fe-irc-queries.c @@ -78,6 +78,13 @@ static void event_privmsg(SERVER_REC *server, const char *data, if (!server_has_nick(server, query->name)) query_change_nick(query, nick); } + } else { + /* process the changes to the query structure now, before the + * privmsg is dispatched. */ + if (g_strcmp0(query->name, nick) != 0) + query_change_nick(query, nick); + if (address != NULL && g_strcmp0(query->address, address) != 0) + query_change_address(query, address); } } diff --git a/src/fe-common/irc/fe-irc-server.c b/src/fe-common/irc/fe-irc-server.c index 2cb99a2f..c4435d8f 100644 --- a/src/fe-common/irc/fe-irc-server.c +++ b/src/fe-common/irc/fe-irc-server.c @@ -50,12 +50,13 @@ const char *get_visible_target(IRC_SERVER_REC *server, const char *target) return target; } -/* SYNTAX: SERVER ADD [-4 | -6] [-ssl] [-ssl_cert <cert>] [-ssl_pkey <pkey>] [-ssl_pass <password>] - [-ssl_verify] [-ssl_cafile <cafile>] [-ssl_capath <capath>] - [-ssl_ciphers <list>] - [-auto | -noauto] [-network <network>] [-host <hostname>] - [-cmdspeed <ms>] [-cmdmax <count>] [-port <port>] - <address> [<port> [<password>]] */ + +/* SYNTAX: SERVER ADD|MODIFY [-4 | -6] [-ssl] [-ssl_cert <cert>] [-ssl_pkey <pkey>] [-ssl_pass <password>] + [-ssl_verify] [-ssl_cafile <cafile>] [-ssl_capath <capath>] + [-ssl_ciphers <list>] + [-auto | -noauto] [-network <network>] [-host <hostname>] + [-cmdspeed <ms>] [-cmdmax <count>] [-port <port>] + <address> [<port> [<password>]] */ /* NOTE: -network replaces the old -ircnet flag. */ static void sig_server_add_fill(IRC_SERVER_SETUP_REC *rec, GHashTable *optlist) @@ -107,23 +108,27 @@ static void cmd_server_list(const char *data) g_string_append(str, "autoconnect, "); if (rec->no_proxy) g_string_append(str, "noproxy, "); - if (rec->use_ssl) { - g_string_append(str, "ssl, "); - if (rec->ssl_cert) { - g_string_append_printf(str, "ssl_cert: %s, ", rec->ssl_cert); - if (rec->ssl_pkey) - g_string_append_printf(str, "ssl_pkey: %s, ", rec->ssl_pkey); - if (rec->ssl_pass) + if (rec->use_tls) { + g_string_append(str, "tls, "); + if (rec->tls_cert) { + g_string_append_printf(str, "tls_cert: %s, ", rec->tls_cert); + if (rec->tls_pkey) + g_string_append_printf(str, "tls_pkey: %s, ", rec->tls_pkey); + if (rec->tls_pass) g_string_append_printf(str, "(pass), "); } - if (rec->ssl_verify) - g_string_append(str, "ssl_verify, "); - if (rec->ssl_cafile) - g_string_append_printf(str, "ssl_cafile: %s, ", rec->ssl_cafile); - if (rec->ssl_capath) - g_string_append_printf(str, "ssl_capath: %s, ", rec->ssl_capath); - if (rec->ssl_ciphers) - g_string_append_printf(str, "ssl_ciphers: %s, ", rec->ssl_ciphers); + if (rec->tls_verify) + g_string_append(str, "tls_verify, "); + if (rec->tls_cafile) + g_string_append_printf(str, "tls_cafile: %s, ", rec->tls_cafile); + if (rec->tls_capath) + g_string_append_printf(str, "tls_capath: %s, ", rec->tls_capath); + if (rec->tls_ciphers) + g_string_append_printf(str, "tls_ciphers: %s, ", rec->tls_ciphers); + if (rec->tls_pinned_cert) + g_string_append_printf(str, "tls_pinned_cert: %s, ", rec->tls_pinned_cert); + if (rec->tls_pinned_pubkey) + g_string_append_printf(str, "tls_pinned_pubkey: %s, ", rec->tls_pinned_pubkey); } if (rec->max_cmds_at_once > 0) diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index 4d7037d5..b70a9ea7 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -88,14 +88,7 @@ static void cmd_network_list(void) printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_NETWORK_FOOTER); } -/* SYNTAX: NETWORK ADD [-nick <nick>] [-user <user>] [-realname <name>] - [-host <host>] [-usermode <mode>] [-autosendcmd <cmd>] - [-querychans <count>] [-whois <count>] [-msgs <count>] - [-kicks <count>] [-modes <count>] [-cmdspeed <ms>] - [-cmdmax <count>] [-sasl_mechanism <mechanism>] - [-sasl_username <username>] [-sasl_password <password>] - <name> */ -static void cmd_network_add(const char *data) +static void cmd_network_add_modify(const char *data, gboolean add) { GHashTable *optlist; char *name, *value; @@ -103,12 +96,20 @@ static void cmd_network_add(const char *data) IRC_CHATNET_REC *rec; if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, - "network add", &optlist, &name)) + "network add", &optlist, &name)) return; + if (*name == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); rec = ircnet_find(name); if (rec == NULL) { + if (add == FALSE) { + cmd_params_free(free_arg); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + IRCTXT_NETWORK_NOT_FOUND, name); + return; + } + rec = g_new0(IRC_CHATNET_REC, 1); rec->name = g_strdup(name); } else { @@ -174,6 +175,23 @@ static void cmd_network_add(const char *data) cmd_params_free(free_arg); } +/* SYNTAX: NETWORK ADD|MODIFY [-nick <nick>] [-user <user>] [-realname <name>] + [-host <host>] [-usermode <mode>] [-autosendcmd <cmd>] + [-querychans <count>] [-whois <count>] [-msgs <count>] + [-kicks <count>] [-modes <count>] [-cmdspeed <ms>] + [-cmdmax <count>] [-sasl_mechanism <mechanism>] + [-sasl_username <username>] [-sasl_password <password>] + <name> */ +static void cmd_network_add(const char *data) +{ + cmd_network_add_modify(data, TRUE); +} + +static void cmd_network_modify(const char *data) +{ + cmd_network_add_modify(data, FALSE); +} + /* SYNTAX: NETWORK REMOVE <network> */ static void cmd_network_remove(const char *data) { @@ -206,10 +224,13 @@ void fe_ircnet_init(void) command_bind("network", NULL, (SIGNAL_FUNC) cmd_network); command_bind("network list", NULL, (SIGNAL_FUNC) cmd_network_list); command_bind("network add", NULL, (SIGNAL_FUNC) cmd_network_add); + command_bind("network modify", NULL, (SIGNAL_FUNC) cmd_network_modify); command_bind("network remove", NULL, (SIGNAL_FUNC) cmd_network_remove); command_set_options("network add", "-kicks -msgs -modes -whois -cmdspeed " "-cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode -sasl_mechanism -sasl_username -sasl_password"); + command_set_options("network modify", "-kicks -msgs -modes -whois -cmdspeed " + "-cmdmax -nick -user -realname -host -autosendcmd -querychans -usermode -sasl_mechanism -sasl_username -sasl_password"); } void fe_ircnet_deinit(void) @@ -218,5 +239,6 @@ void fe_ircnet_deinit(void) command_unbind("network", (SIGNAL_FUNC) cmd_network); command_unbind("network list", (SIGNAL_FUNC) cmd_network_list); command_unbind("network add", (SIGNAL_FUNC) cmd_network_add); + command_unbind("network modify", (SIGNAL_FUNC) cmd_network_modify); command_unbind("network remove", (SIGNAL_FUNC) cmd_network_remove); } diff --git a/src/fe-common/irc/fe-netjoin.c b/src/fe-common/irc/fe-netjoin.c index f5cb081e..4eb388c0 100644 --- a/src/fe-common/irc/fe-netjoin.c +++ b/src/fe-common/irc/fe-netjoin.c @@ -164,11 +164,11 @@ static void print_channel_netjoins(char *channel, TEMP_PRINT_REC *rec, g_free(channel); } -static void print_netjoins(NETJOIN_SERVER_REC *server) +static void print_netjoins(NETJOIN_SERVER_REC *server, const char *filter_channel) { TEMP_PRINT_REC *temp; GHashTable *channels; - GSList *tmp, *next, *old; + GSList *tmp, *tmp2, *next, *next2, *old; g_return_if_fail(server != NULL); @@ -181,11 +181,19 @@ static void print_netjoins(NETJOIN_SERVER_REC *server) for (tmp = server->netjoins; tmp != NULL; tmp = next) { NETJOIN_REC *rec = tmp->data; - next = tmp->next; - while (rec->now_channels != NULL) { - char *channel = rec->now_channels->data; + next = g_slist_next(tmp); + + for (tmp2 = rec->now_channels; tmp2 != NULL; tmp2 = next2) { + char *channel = tmp2->data; char *realchannel = channel + 1; + next2 = g_slist_next(tmp2); + + /* Filter the results by channel if asked to do so */ + if (filter_channel != NULL && + strcasecmp(realchannel, filter_channel) != 0) + continue; + temp = g_hash_table_lookup(channels, realchannel); if (temp == NULL) { temp = g_new0(TEMP_PRINT_REC, 1); @@ -214,8 +222,8 @@ static void print_netjoins(NETJOIN_SERVER_REC *server) g_free(data); } - rec->now_channels = - g_slist_remove(rec->now_channels, channel); + /* drop tmp2 from the list */ + rec->now_channels = g_slist_delete_link(rec->now_channels, tmp2); g_free(channel); } @@ -235,20 +243,25 @@ static void print_netjoins(NETJOIN_SERVER_REC *server) /* something is going to be printed to screen, print our current netsplit message before it. */ -static void sig_print_starting(void) +static void sig_print_starting(TEXT_DEST_REC *dest) { - GSList *tmp, *next; + NETJOIN_SERVER_REC *rec; if (printing_joins) return; - for (tmp = joinservers; tmp != NULL; tmp = next) { - NETJOIN_SERVER_REC *server = tmp->data; + if (!IS_IRC_SERVER(dest->server)) + return; - next = tmp->next; - if (server->netjoins != NULL) - print_netjoins(server); - } + if (!(dest->level & MSGLEVEL_PUBLIC)) + return; + + if (!server_ischannel(dest->server, dest->target)) + return; + + rec = netjoin_find_server(IRC_SERVER(dest->server)); + if (rec != NULL && rec->netjoins != NULL) + print_netjoins(rec, dest->target); } static int sig_check_netjoins(void) @@ -272,7 +285,7 @@ static int sig_check_netjoins(void) } if (server->netjoins != NULL) - print_netjoins(server); + print_netjoins(server, NULL); } /* now remove all netjoins which haven't had any new joins diff --git a/src/fe-common/irc/fe-netsplit.c b/src/fe-common/irc/fe-netsplit.c index 3eb30796..17fb1994 100644 --- a/src/fe-common/irc/fe-netsplit.c +++ b/src/fe-common/irc/fe-netsplit.c @@ -142,7 +142,7 @@ static void get_server_splits(void *key, NETSPLIT_REC *split, } } -static void print_server_splits(IRC_SERVER_REC *server, TEMP_SPLIT_REC *rec) +static void print_server_splits(IRC_SERVER_REC *server, TEMP_SPLIT_REC *rec, const char *filter_channel) { GString *destservers; char *sourceserver; @@ -168,6 +168,10 @@ static void print_server_splits(IRC_SERVER_REC *server, TEMP_SPLIT_REC *rec) for (tmp = rec->channels; tmp != NULL; tmp = tmp->next) { TEMP_SPLIT_CHAN_REC *chan = tmp->data; + if (filter_channel != NULL && + strcasecmp(chan->name, filter_channel) != 0) + continue; + g_string_truncate(chan->nicks, chan->nicks->len-2); if (netsplit_max_nicks > 0 && @@ -193,7 +197,7 @@ static void temp_split_chan_free(TEMP_SPLIT_CHAN_REC *rec) g_free(rec); } -static void print_splits(IRC_SERVER_REC *server) +static void print_splits(IRC_SERVER_REC *server, const char *channel) { TEMP_SPLIT_REC temp; GSList *servers; @@ -212,7 +216,7 @@ static void print_splits(IRC_SERVER_REC *server) g_hash_table_foreach(server->splits, (GHFunc) get_server_splits, &temp); - print_server_splits(server, &temp); + print_server_splits(server, &temp, channel); g_slist_foreach(temp.channels, (GFunc) temp_split_chan_free, NULL); @@ -233,25 +237,31 @@ static int check_server_splits(IRC_SERVER_REC *server) if (time(NULL)-last < SPLIT_WAIT_TIME) return FALSE; - print_splits(server); + print_splits(server, NULL); return TRUE; } /* something is going to be printed to screen, print our current netsplit message before it. */ -static void sig_print_starting(void) +static void sig_print_starting(TEXT_DEST_REC *dest) { - GSList *tmp; + IRC_SERVER_REC *rec; if (printing_splits) return; - for (tmp = servers; tmp != NULL; tmp = tmp->next) { - IRC_SERVER_REC *rec = tmp->data; + if (!IS_IRC_SERVER(dest->server)) + return; - if (IS_IRC_SERVER(rec) && rec->split_servers != NULL) - print_splits(rec); - } + if (!(dest->level & MSGLEVEL_PUBLIC)) + return; + + if (!server_ischannel(dest->server, dest->target)) + return; + + rec = IRC_SERVER(dest->server); + if (rec->split_servers != NULL) + print_splits(rec, dest->target); } static int sig_check_splits(void) diff --git a/src/fe-common/irc/fe-sasl.c b/src/fe-common/irc/fe-sasl.c index 331b38b0..fc8105fc 100644 --- a/src/fe-common/irc/fe-sasl.c +++ b/src/fe-common/irc/fe-sasl.c @@ -1,7 +1,7 @@ /* fe-sasl.c : irssi - Copyright (C) 2015 The Lemon Man + Copyright (C) 2015-2017 The Lemon Man This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,11 @@ #include "module-formats.h" #include "signals.h" #include "levels.h" +#include "misc.h" +#include "sasl.h" + +#include "irc-servers.h" +#include "settings.h" #include "printtext.h" @@ -35,14 +40,36 @@ static void sig_sasl_failure(IRC_SERVER_REC *server, const char *reason) printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_SASL_ERROR, reason); } +static void sig_cap_end(IRC_SERVER_REC *server) +{ + /* The negotiation has now been terminated, if we didn't manage to + * authenticate successfully with the server just disconnect. */ + if (!server->sasl_success && + server->connrec->sasl_mechanism != SASL_MECHANISM_NONE && + settings_get_bool("sasl_disconnect_on_failure")) { + /* We can't use server_disconnect() here because we'd end up + * freeing the 'server' object and be guilty of a slew of UaF. */ + server->connection_lost = TRUE; + /* By setting connection_lost we make sure the communication is + * halted and when the control goes back to irc_parse_incoming + * the server object is safely destroyed. */ + signal_stop(); + } + +} + void fe_sasl_init(void) { + settings_add_bool("server", "sasl_disconnect_on_failure", TRUE); + signal_add("server sasl success", (SIGNAL_FUNC) sig_sasl_success); signal_add("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure); + signal_add_first("server cap end", (SIGNAL_FUNC) sig_cap_end); } void fe_sasl_deinit(void) { signal_remove("server sasl success", (SIGNAL_FUNC) sig_sasl_success); signal_remove("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure); + signal_remove("server cap end", (SIGNAL_FUNC) sig_cap_end); } |