1
0
mirror of https://github.com/irssi/irssi.git synced 2024-07-07 02:54:19 -04:00

actually use the tls settings on upgrade, and disconnect gracefully

This commit is contained in:
Ailin Nemui 2021-04-06 19:31:10 +02:00
parent db2fed0d38
commit f2795abcc5
11 changed files with 116 additions and 29 deletions

View File

@ -338,7 +338,14 @@ SERVER_CONNECT_REC *server_create_conn_opt(int chat_type, const char *dest, int
SERVER_CONNECT_REC *server_create_conn(int chat_type, const char *dest, int port,
const char *chatnet, const char *password, const char *nick)
{
return server_create_conn_opt(chat_type, dest, port, chatnet, password, nick, NULL);
SERVER_CONNECT_REC *ret;
GHashTable *opt;
opt = g_hash_table_new(NULL, NULL);
ret = server_create_conn_opt(chat_type, dest, port, chatnet, password, nick, opt);
g_hash_table_destroy(opt);
return ret;
}
/* Find matching server from setup. Try to find record with a same port,

View File

@ -254,23 +254,35 @@ static void session_restore_server(CONFIG_NODE *node)
proto = chat_protocol_find(chat_type);
if (proto == NULL || proto->not_initialized) {
if (handle < 0) close(handle);
if (handle >= 0)
close(handle);
return;
}
conn = server_create_conn(proto->id, address, port,
chatnet, password, nick);
if (conn != NULL) {
conn->reconnection = TRUE;
conn->connect_handle = i_io_channel_new(handle);
if (conn == NULL)
return;
server = proto->server_init_connect(conn);
server->version = g_strdup(config_node_get_str(node, "version", NULL));
server->session_reconnect = TRUE;
signal_emit("session restore server", 2, server, node);
conn->use_tls = config_node_get_bool(node, "use_tls", FALSE);
conn->tls_cert = g_strdup(config_node_get_str(node, "tls_cert", NULL));
conn->tls_pkey = g_strdup(config_node_get_str(node, "tls_pkey", NULL));
conn->tls_verify = config_node_get_bool(node, "tls_verify", TRUE);
conn->tls_cafile = g_strdup(config_node_get_str(node, "tls_cafile", NULL));
conn->tls_capath = g_strdup(config_node_get_str(node, "tls_capath", NULL));
conn->tls_ciphers = g_strdup(config_node_get_str(node, "tls_ciphers", NULL));
conn->tls_pinned_cert = g_strdup(config_node_get_str(node, "tls_pinned_cert", NULL));
conn->tls_pinned_pubkey = g_strdup(config_node_get_str(node, "tls_pinned_pubkey", NULL));
proto->server_connect(server);
}
conn->reconnection = TRUE;
conn->connect_handle = i_io_channel_new(handle);
server = proto->server_init_connect(conn);
server->version = g_strdup(config_node_get_str(node, "version", NULL));
server->session_reconnect = TRUE;
signal_emit("session restore server", 2, server, node);
proto->server_connect(server);
}
static void sig_session_save(CONFIG_REC *config)

View File

@ -165,14 +165,10 @@ static void cmd_server_add_modify(const char *data, gboolean add)
else if (g_hash_table_lookup(optlist, "4"))
rec->family = AF_INET;
if (g_hash_table_lookup(optlist, "tls") || g_hash_table_lookup(optlist, "ssl")) {
if (g_hash_table_lookup(optlist, "tls") || g_hash_table_lookup(optlist, "ssl"))
rec->use_tls = TRUE;
}
else if (g_hash_table_lookup(optlist, "notls") || g_hash_table_lookup(optlist, "nossl")) {
else if (g_hash_table_lookup(optlist, "notls") || g_hash_table_lookup(optlist, "nossl"))
rec->use_tls = FALSE;
/* tls_verify implies use_tls, disable it explicitly */
rec->tls_verify = FALSE;
}
value = g_hash_table_lookup(optlist, "tls_cert");
if (value == NULL)

View File

@ -90,6 +90,8 @@ static void sig_disconnected(IRC_SERVER_REC *server)
return;
rec = server->chanqueries;
if (rec == NULL)
return;
g_return_if_fail(rec != NULL);
g_hash_table_destroy(rec->accountqueries);

View File

@ -64,7 +64,8 @@ static void sig_server_reconnect_save_status(IRC_SERVER_CONNECT_REC *conn,
return;
g_free_not_null(conn->channels);
conn->channels = irc_server_get_channels(server);
conn->channels =
irc_server_get_channels(server, settings_get_choice("rejoin_channels_on_reconnect"));
g_free_not_null(conn->usermode);
conn->usermode = g_strdup(server->wanted_usermode);

View File

@ -469,6 +469,26 @@ void irc_server_connect(SERVER_REC *server)
{
g_return_if_fail(server != NULL);
if (server->connrec->connect_handle != NULL) {
IRC_SERVER_CONNECT_REC *conn;
int tls_disconnect;
conn = ((IRC_SERVER_REC *) server)->connrec;
tls_disconnect = conn->use_tls || conn->starttls;
if (tls_disconnect) {
/* we cannot use it, it is encrypted. force a reconnect */
g_io_channel_unref(conn->connect_handle);
conn->connect_handle = NULL;
server->session_reconnect = FALSE;
server_connect_ref((SERVER_CONNECT_REC *) conn);
server_disconnect(server);
server_connect((SERVER_CONNECT_REC *) conn);
server_connect_unref((SERVER_CONNECT_REC *) conn);
return;
}
}
if (!server_start_connect(server)) {
server_connect_unref(server->connrec);
g_free(server);
@ -782,20 +802,17 @@ void irc_servers_start_cmd_timeout(void)
/* Return a string of all channels (and keys, if any have them) in server,
like "#a,#b,#c,#d x,b_chan_key,x,x" or just "#e,#f,#g" */
char *irc_server_get_channels(IRC_SERVER_REC *server)
char *irc_server_get_channels(IRC_SERVER_REC *server, int rejoin_channels_mode)
{
GSList *tmp;
GString *chans, *keys;
char *ret;
int use_keys;
int rejoin_channels_mode;
g_return_val_if_fail(server != NULL, FALSE);
rejoin_channels_mode = settings_get_choice("rejoin_channels_on_reconnect");
/* do we want to rejoin channels in the first place? */
if(rejoin_channels_mode == 0)
if (rejoin_channels_mode == REJOIN_CHANNELS_MODE_OFF)
return g_strdup("");
chans = g_string_new(NULL);
@ -806,7 +823,9 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *channel = tmp->data;
CHANNEL_SETUP_REC *setup = channel_setup_find(channel->name, channel->server->connrec->chatnet);
if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) {
if ((setup != NULL && setup->autojoin &&
rejoin_channels_mode == REJOIN_CHANNELS_MODE_AUTO) ||
rejoin_channels_mode == REJOIN_CHANNELS_MODE_ON) {
g_string_append_printf(chans, "%s,", channel->name);
g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : channel->key);
if (channel->key != NULL)
@ -819,7 +838,9 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
REJOIN_REC *rec = tmp->data;
CHANNEL_SETUP_REC *setup = channel_setup_find(rec->channel, server->tag);
if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) {
if ((setup != NULL && setup->autojoin &&
rejoin_channels_mode == REJOIN_CHANNELS_MODE_AUTO) ||
rejoin_channels_mode == REJOIN_CHANNELS_MODE_ON) {
g_string_append_printf(chans, "%s,", rec->channel);
g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" :
rec->key);

View File

@ -157,9 +157,15 @@ void irc_server_connect(SERVER_REC *server);
/* Purge server output, either all or for specified target */
void irc_server_purge_output(IRC_SERVER_REC *server, const char *target);
enum {
REJOIN_CHANNELS_MODE_OFF = 0, /* */
REJOIN_CHANNELS_MODE_ON,
REJOIN_CHANNELS_MODE_AUTO
};
/* Return a string of all channels (and keys, if any have them) in server,
like "#a,#b,#c,#d x,b_chan_key,x,x" or just "#e,#f,#g" */
char *irc_server_get_channels(IRC_SERVER_REC *server);
char *irc_server_get_channels(IRC_SERVER_REC *server, int rejoin_channels_mode);
void irc_server_send_starttls(IRC_SERVER_REC *server);
/* INTERNAL: */

View File

@ -23,6 +23,7 @@
#include <irssi/src/core/net-sendbuffer.h>
#include <irssi/src/lib-config/iconfig.h>
#include <irssi/src/core/misc.h>
#include <irssi/src/core/network.h>
#include <irssi/src/irc/core/irc-servers.h>
#include <irssi/src/irc/core/irc-channels.h>
@ -43,6 +44,7 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
GSList *tmp;
CONFIG_NODE *isupport;
struct _isupport_data isupport_data;
int tls_disconnect;
if (!IS_IRC_SERVER(server))
return;
@ -58,7 +60,15 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
break;
}
}
net_sendbuffer_flush(server->handle);
/* we cannot upgrade TLS (yet?) */
tls_disconnect = server->connrec->use_tls || server->connrec->starttls;
if (tls_disconnect) {
config_node_set_str(config, node, "rejoin_channels",
irc_server_get_channels(server, REJOIN_CHANNELS_MODE_ON));
irc_send_cmd_now(server, "QUIT :[TLS] Client upgrade");
}
net_sendbuffer_flush(server->handle);
config_node_set_str(config, node, "real_address", server->real_address);
config_node_set_str(config, node, "userhost", server->userhost);
@ -71,18 +81,26 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
config_node_set_str(config, node, "sasl_username", server->connrec->sasl_username);
config_node_set_str(config, node, "sasl_password", server->connrec->sasl_password);
config_node_set_int(config, node, "starttls",
server->connrec->disallow_starttls ? 0 :
server->connrec->starttls ? 1 :
-1);
config_node_set_bool(config, node, "isupport_sent", server->isupport_sent);
isupport = config_node_section(config, node, "isupport", NODE_TYPE_BLOCK);
isupport_data.config = config;
isupport_data.node = isupport;
g_hash_table_foreach(server->isupport, (GHFunc) session_isupport_foreach, &isupport_data);
/* we have to defer the disconnect to irc_server_connect */
}
static void sig_session_restore_server(IRC_SERVER_REC *server,
CONFIG_NODE *node)
{
GSList *tmp;
int starttls_mode;
if (!IS_IRC_SERVER(server))
return;
@ -105,6 +123,14 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
g_free(server->connrec->sasl_password);
server->connrec->sasl_password = g_strdup(config_node_get_str(node, "sasl_password", NULL));
server->connrec->channels = g_strdup(config_node_get_str(node, "rejoin_channels", NULL));
starttls_mode = config_node_get_int(node, "starttls", -1);
if (starttls_mode == 0)
server->connrec->disallow_starttls = 1;
if (starttls_mode == 1)
server->connrec->starttls = 1;
if (server->isupport == NULL) {
server->isupport =
g_hash_table_new((GHashFunc) i_istr_hash, (GCompareFunc) i_istr_equal);
@ -123,6 +149,7 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
}
irc_server_init_isupport(server);
/* we will reconnect in irc_server_connect if the connection was TLS */
}
static void sig_session_restore_nick(IRC_CHANNEL_REC *channel,

View File

@ -381,6 +381,9 @@ static void sig_disconnected(IRC_SERVER_REC *server)
if (!IS_IRC_SERVER(server))
return;
if (server->splits == NULL)
return;
g_hash_table_foreach(server->splits,
(GHFunc) netsplit_destroy_hash, server);
g_hash_table_destroy(server->splits);

View File

@ -209,6 +209,9 @@ static void notifylist_deinit_server(IRC_SERVER_REC *server)
return;
mserver = MODULE_DATA(server);
if (!mserver)
return;
while (mserver->notify_users != NULL) {
rec = mserver->notify_users->data;

View File

@ -1,5 +1,6 @@
#define PERL_NO_GET_CONTEXT
#include "module.h"
#include <irssi/src/core/misc.h>
static GSList *register_hash2list(HV *hv)
{
@ -47,12 +48,20 @@ MODULE = Irssi::Irc::Server PACKAGE = Irssi::Irc::Server PREFIX = irc_server_
PROTOTYPES: ENABLE
void
irc_server_get_channels(server)
irc_server_get_channels(server, rejoin_channels_mode = "")
Irssi::Irc::Server server
char *rejoin_channels_mode
PREINIT:
char *ret;
int mode;
SETTINGS_REC *setting;
PPCODE:
ret = irc_server_get_channels(server);
setting = settings_get_record("rejoin_channels_on_reconnect");
mode = strarray_find(setting->choices, rejoin_channels_mode);
if (mode < 0)
mode = setting->default_value.v_int;
ret = irc_server_get_channels(server, mode);
XPUSHs(sv_2mortal(new_pv(ret)));
g_free(ret);