mirror of
https://github.com/irssi/irssi.git
synced 2025-01-03 14:56:47 -05:00
Merge pull request #1170 from ailin-nemui/starttls
use starttls / enable tls_verify
This commit is contained in:
commit
4432b0bf0d
@ -1,10 +1,10 @@
|
||||
servers = (
|
||||
{ address = "irc.dal.net"; chatnet = "DALnet"; port = "6667"; },
|
||||
{ address = "ssl.efnet.org"; chatnet = "EFNet"; port = "9999"; use_tls = "yes"; },
|
||||
{ address = "ssl.efnet.org"; chatnet = "EFNet"; port = "9999"; use_tls = "yes"; tls_verify = "no"; },
|
||||
{ address = "irc.esper.net"; chatnet = "EsperNet"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; },
|
||||
{ address = "chat.freenode.net"; chatnet = "Freenode"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; },
|
||||
{ address = "irc.gamesurge.net"; chatnet = "GameSurge"; port = "6667"; },
|
||||
{ address = "eu.irc6.net"; chatnet = "IRCnet"; port = "6667"; use_tls = "yes"; },
|
||||
{ address = "ssl.ircnet.ovh"; chatnet = "IRCnet"; port = "6697"; use_tls = "yes"; tls_verify = "yes"; },
|
||||
{ address = "open.ircnet.net"; chatnet = "IRCnet"; port = "6667"; },
|
||||
{ address = "irc.ircsource.net"; chatnet = "IRCSource"; port = "6667"; },
|
||||
{ address = "irc.netfuze.net"; chatnet = "NetFuze"; port = "6667"; },
|
||||
|
@ -6,7 +6,7 @@
|
||||
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
|
||||
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
|
||||
|
||||
#define IRSSI_ABI_VERSION 35
|
||||
#define IRSSI_ABI_VERSION 36
|
||||
|
||||
#define DEFAULT_SERVER_ADD_PORT 6667
|
||||
#define DEFAULT_SERVER_ADD_TLS_PORT 6697
|
||||
|
@ -40,7 +40,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
|
||||
CHAT_PROTOCOL_REC *proto;
|
||||
SERVER_CONNECT_REC *conn;
|
||||
GHashTable *optlist;
|
||||
char *addr, *portstr, *password, *nick, *chatnet, *host, *tmp;
|
||||
char *addr, *portstr, *password, *nick, *chatnet, *host;
|
||||
void *free_arg;
|
||||
|
||||
g_return_val_if_fail(data != NULL, NULL);
|
||||
@ -71,8 +71,8 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
|
||||
if (chatnet == NULL)
|
||||
chatnet = g_hash_table_lookup(optlist, "network");
|
||||
|
||||
conn = server_create_conn(proto != NULL ? proto->id : -1, addr,
|
||||
atoi(portstr), chatnet, password, nick);
|
||||
conn = server_create_conn_opt(proto != NULL ? proto->id : -1, addr, atoi(portstr), chatnet,
|
||||
password, nick, optlist);
|
||||
if (conn == NULL) {
|
||||
signal_emit("error command", 1,
|
||||
GINT_TO_POINTER(CMDERR_NO_SERVER_DEFINED));
|
||||
@ -94,46 +94,7 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
|
||||
if (strchr(addr, '/') != NULL)
|
||||
conn->unix_socket = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "6") != NULL)
|
||||
conn->family = AF_INET6;
|
||||
else if (g_hash_table_lookup(optlist, "4") != NULL)
|
||||
conn->family = AF_INET;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "tls") != NULL || g_hash_table_lookup(optlist, "ssl") != NULL)
|
||||
conn->use_tls = TRUE;
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_cert")) != NULL || (tmp = g_hash_table_lookup(optlist, "ssl_cert")) != NULL)
|
||||
conn->tls_cert = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_pkey")) != NULL || (tmp = g_hash_table_lookup(optlist, "ssl_pkey")) != NULL)
|
||||
conn->tls_pkey = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_pass")) != NULL || (tmp = g_hash_table_lookup(optlist, "ssl_pass")) != NULL)
|
||||
conn->tls_pass = g_strdup(tmp);
|
||||
if (g_hash_table_lookup(optlist, "tls_verify") != NULL || g_hash_table_lookup(optlist, "ssl_verify") != NULL)
|
||||
conn->tls_verify = TRUE;
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_cafile")) != NULL || (tmp = g_hash_table_lookup(optlist, "ssl_cafile")) != NULL)
|
||||
conn->tls_cafile = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_capath")) != NULL || (tmp = g_hash_table_lookup(optlist, "ssl_capath")) != NULL)
|
||||
conn->tls_capath = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_ciphers")) != NULL || (tmp = g_hash_table_lookup(optlist, "ssl_ciphers")) != NULL)
|
||||
conn->tls_ciphers = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_pinned_cert")) != NULL || (tmp = g_hash_table_lookup(optlist, "ssl_pinned_cert")) != NULL)
|
||||
conn->tls_pinned_cert = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_pinned_pubkey")) != NULL || (tmp = g_hash_table_lookup(optlist, "ssl_pinned_pubkey")) != NULL)
|
||||
conn->tls_pinned_pubkey = g_strdup(tmp);
|
||||
if ((conn->tls_capath != NULL && conn->tls_capath[0] != '\0')
|
||||
|| (conn->tls_cafile != NULL && conn->tls_cafile[0] != '\0'))
|
||||
conn->tls_verify = TRUE;
|
||||
if ((conn->tls_cert != NULL && conn->tls_cert[0] != '\0') || conn->tls_verify)
|
||||
conn->use_tls = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "!") != NULL)
|
||||
conn->no_autojoin_channels = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "noautosendcmd") != NULL)
|
||||
conn->no_autosendcmd = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "noproxy") != NULL)
|
||||
g_free_and_null(conn->proxy);
|
||||
|
||||
/* TLS options are handled in server_create_conn_opt ... -> server_setup_fill_optlist */
|
||||
|
||||
*rawlog_file = g_strdup(g_hash_table_lookup(optlist, "rawlog"));
|
||||
|
||||
@ -149,13 +110,13 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr,
|
||||
return conn;
|
||||
}
|
||||
|
||||
/* SYNTAX: CONNECT [-4 | -6] [-tls] [-tls_cert <cert>] [-tls_pkey <pkey>] [-tls_pass <password>]
|
||||
/* SYNTAX: CONNECT [-4 | -6] [-tls_cert <cert>] [-tls_pkey <pkey>] [-tls_pass <password>]
|
||||
[-tls_verify] [-tls_cafile <cafile>] [-tls_capath <capath>]
|
||||
[-tls_ciphers <list>] [-tls_pinned_cert <fingerprint>] [-tls_pinned_pubkey <fingerprint>]
|
||||
[-!] [-noautosendcmd]
|
||||
[-noproxy] [-network <network>] [-host <hostname>]
|
||||
[-rawlog <file>]
|
||||
<address>|<chatnet> [<port> [<password> [<nick>]]] */
|
||||
[-tls_ciphers <list>] [-tls_pinned_cert <fingerprint>]
|
||||
[-tls_pinned_pubkey <fingerprint>] [-!] [-noautosendcmd] [-tls | -notls]
|
||||
[-starttls | -disallow_starttls] [-noproxy] [-network <network>]
|
||||
[-host <hostname>] [-rawlog <file>]
|
||||
<address>|<chatnet> [<port> [<password> [<nick>]]] */
|
||||
/* NOTE: -network replaces the old -ircnet flag. */
|
||||
static void cmd_connect(const char *data)
|
||||
{
|
||||
@ -520,9 +481,9 @@ void chat_commands_init(void)
|
||||
command_set_options(
|
||||
"connect",
|
||||
"4 6 !! -network ~ssl ~+ssl_cert ~+ssl_pkey ~+ssl_pass ~ssl_verify ~+ssl_cafile "
|
||||
"~+ssl_capath ~+ssl_ciphers ~+ssl_pinned_cert ~+ssl_pinned_pubkey tls +tls_cert "
|
||||
"+tls_pkey +tls_pass tls_verify +tls_cafile +tls_capath +tls_ciphers +tls_pinned_cert "
|
||||
"+tls_pinned_pubkey +host noproxy -rawlog noautosendcmd");
|
||||
"~+ssl_capath ~+ssl_ciphers ~+ssl_pinned_cert ~+ssl_pinned_pubkey tls notls +tls_cert "
|
||||
"+tls_pkey +tls_pass tls_verify notls_verify +tls_cafile +tls_capath +tls_ciphers "
|
||||
"+tls_pinned_cert +tls_pinned_pubkey +host noproxy -rawlog noautosendcmd");
|
||||
command_set_options("msg", "channel nick");
|
||||
}
|
||||
|
||||
|
@ -239,8 +239,11 @@ static void sig_reconnect(SERVER_REC *server)
|
||||
if (reconnect_time == -1 || !server_should_reconnect(server))
|
||||
return;
|
||||
|
||||
conn = server_connect_copy_skeleton(server->connrec, FALSE);
|
||||
g_return_if_fail(conn != NULL);
|
||||
sserver = server_setup_find(server->connrec->address, server->connrec->port,
|
||||
server->connrec->chatnet);
|
||||
|
||||
conn = server_connect_copy_skeleton(server->connrec, sserver == NULL);
|
||||
g_return_if_fail(conn != NULL);
|
||||
|
||||
/* save the server status */
|
||||
if (server->connected) {
|
||||
@ -249,10 +252,6 @@ static void sig_reconnect(SERVER_REC *server)
|
||||
reconnect_save_status(conn, server);
|
||||
}
|
||||
|
||||
sserver = server_setup_find(server->connrec->address,
|
||||
server->connrec->port,
|
||||
server->connrec->chatnet);
|
||||
|
||||
if (sserver != NULL) {
|
||||
/* save the last connection time/status */
|
||||
sserver->last_connect = server->connect_time == 0 ?
|
||||
|
@ -140,8 +140,8 @@ void server_setup_fill_reconn(SERVER_CONNECT_REC *conn,
|
||||
signal_emit("server setup fill reconn", 2, conn, sserver);
|
||||
}
|
||||
|
||||
static void server_setup_fill(SERVER_CONNECT_REC *conn,
|
||||
const char *address, int port)
|
||||
static void server_setup_fill(SERVER_CONNECT_REC *conn, const char *address, int port,
|
||||
GHashTable *optlist)
|
||||
{
|
||||
g_return_if_fail(conn != NULL);
|
||||
g_return_if_fail(address != NULL);
|
||||
@ -177,7 +177,69 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn,
|
||||
memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR));
|
||||
}
|
||||
|
||||
signal_emit("server setup fill connect", 1, conn);
|
||||
signal_emit("server setup fill connect", 2, conn, optlist);
|
||||
}
|
||||
|
||||
static void server_setup_fill_optlist(SERVER_CONNECT_REC *conn, GHashTable *optlist)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "6") != NULL)
|
||||
conn->family = AF_INET6;
|
||||
else if (g_hash_table_lookup(optlist, "4") != NULL)
|
||||
conn->family = AF_INET;
|
||||
|
||||
/* ad-hoc TLS settings from command optlist */
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_cert")) != NULL ||
|
||||
(tmp = g_hash_table_lookup(optlist, "ssl_cert")) != NULL)
|
||||
conn->tls_cert = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_pkey")) != NULL ||
|
||||
(tmp = g_hash_table_lookup(optlist, "ssl_pkey")) != NULL)
|
||||
conn->tls_pkey = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_pass")) != NULL ||
|
||||
(tmp = g_hash_table_lookup(optlist, "ssl_pass")) != NULL)
|
||||
conn->tls_pass = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_cafile")) != NULL ||
|
||||
(tmp = g_hash_table_lookup(optlist, "ssl_cafile")) != NULL)
|
||||
conn->tls_cafile = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_capath")) != NULL ||
|
||||
(tmp = g_hash_table_lookup(optlist, "ssl_capath")) != NULL)
|
||||
conn->tls_capath = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_ciphers")) != NULL ||
|
||||
(tmp = g_hash_table_lookup(optlist, "ssl_ciphers")) != NULL)
|
||||
conn->tls_ciphers = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_pinned_cert")) != NULL ||
|
||||
(tmp = g_hash_table_lookup(optlist, "ssl_pinned_cert")) != NULL)
|
||||
conn->tls_pinned_cert = g_strdup(tmp);
|
||||
if ((tmp = g_hash_table_lookup(optlist, "tls_pinned_pubkey")) != NULL ||
|
||||
(tmp = g_hash_table_lookup(optlist, "ssl_pinned_pubkey")) != NULL)
|
||||
conn->tls_pinned_pubkey = g_strdup(tmp);
|
||||
if ((conn->tls_capath != NULL && conn->tls_capath[0] != '\0') ||
|
||||
(conn->tls_cafile != NULL && conn->tls_cafile[0] != '\0'))
|
||||
conn->tls_verify = TRUE;
|
||||
if (g_hash_table_lookup(optlist, "notls_verify") != NULL)
|
||||
conn->tls_verify = FALSE;
|
||||
if (g_hash_table_lookup(optlist, "tls_verify") != NULL ||
|
||||
g_hash_table_lookup(optlist, "ssl_verify") != NULL)
|
||||
conn->tls_verify = TRUE;
|
||||
if ((conn->tls_cert != NULL && conn->tls_cert[0] != '\0') || conn->tls_verify)
|
||||
conn->use_tls = TRUE;
|
||||
if (g_hash_table_lookup(optlist, "notls") != NULL)
|
||||
conn->use_tls = FALSE;
|
||||
if (g_hash_table_lookup(optlist, "tls") != NULL ||
|
||||
g_hash_table_lookup(optlist, "ssl") != NULL)
|
||||
conn->use_tls = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "!") != NULL)
|
||||
conn->no_autojoin_channels = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "noautosendcmd") != NULL)
|
||||
conn->no_autosendcmd = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "noproxy") != NULL)
|
||||
g_free_and_null(conn->proxy);
|
||||
|
||||
signal_emit("server setup fill optlist", 2, conn, optlist);
|
||||
}
|
||||
|
||||
static void server_setup_fill_server(SERVER_CONNECT_REC *conn,
|
||||
@ -219,10 +281,9 @@ static void server_setup_fill_chatnet(SERVER_CONNECT_REC *conn,
|
||||
signal_emit("server setup fill chatnet", 2, conn, chatnet);
|
||||
}
|
||||
|
||||
static SERVER_CONNECT_REC *
|
||||
create_addr_conn(int chat_type, const char *address, int port,
|
||||
const char *chatnet, const char *password,
|
||||
const char *nick)
|
||||
static SERVER_CONNECT_REC *create_addr_conn(int chat_type, const char *address, int port,
|
||||
const char *chatnet, const char *password,
|
||||
const char *nick, GHashTable *optlist)
|
||||
{
|
||||
CHAT_PROTOCOL_REC *proto;
|
||||
SERVER_CONNECT_REC *conn;
|
||||
@ -250,7 +311,7 @@ create_addr_conn(int chat_type, const char *address, int port,
|
||||
conn->chatnet = g_strdup(chatnet);
|
||||
|
||||
/* fill in the defaults */
|
||||
server_setup_fill(conn, address, port);
|
||||
server_setup_fill(conn, address, port, optlist);
|
||||
|
||||
/* fill the rest from chat network settings */
|
||||
chatnetrec = chatnet != NULL ? chatnet_find(chatnet) :
|
||||
@ -263,6 +324,10 @@ create_addr_conn(int chat_type, const char *address, int port,
|
||||
if (sserver != NULL)
|
||||
server_setup_fill_server(conn, sserver);
|
||||
|
||||
/* fill the optlist overrides */
|
||||
if (g_hash_table_size(optlist))
|
||||
server_setup_fill_optlist(conn, optlist);
|
||||
|
||||
/* nick / password given in command line overrides all settings */
|
||||
if (password && *password) {
|
||||
g_free_not_null(conn->password);
|
||||
@ -279,9 +344,8 @@ create_addr_conn(int chat_type, const char *address, int port,
|
||||
/* Connect to server where last connect succeeded (or we haven't tried to
|
||||
connect yet). If there's no such server, connect to server where we
|
||||
haven't connected for the longest time */
|
||||
static SERVER_CONNECT_REC *
|
||||
create_chatnet_conn(const char *dest, int port,
|
||||
const char *password, const char *nick)
|
||||
static SERVER_CONNECT_REC *create_chatnet_conn(const char *dest, int port, const char *password,
|
||||
const char *nick, GHashTable *optlist)
|
||||
{
|
||||
SERVER_SETUP_REC *bestrec;
|
||||
GSList *tmp;
|
||||
@ -308,16 +372,15 @@ create_chatnet_conn(const char *dest, int port,
|
||||
}
|
||||
|
||||
return bestrec == NULL ? NULL :
|
||||
create_addr_conn(bestrec->chat_type, bestrec->address, 0,
|
||||
dest, NULL, nick);
|
||||
create_addr_conn(bestrec->chat_type, bestrec->address, 0, dest,
|
||||
NULL, nick, optlist);
|
||||
}
|
||||
|
||||
/* Create server connection record. `dest' is required, rest can be NULL.
|
||||
`dest' is either a server address or chat network */
|
||||
SERVER_CONNECT_REC *
|
||||
server_create_conn(int chat_type, const char *dest, int port,
|
||||
const char *chatnet, const char *password,
|
||||
const char *nick)
|
||||
SERVER_CONNECT_REC *server_create_conn_opt(int chat_type, const char *dest, int port,
|
||||
const char *chatnet, const char *password,
|
||||
const char *nick, GHashTable *optlist)
|
||||
{
|
||||
SERVER_CONNECT_REC *rec;
|
||||
CHATNET_REC *chatrec;
|
||||
@ -326,7 +389,7 @@ server_create_conn(int chat_type, const char *dest, int port,
|
||||
|
||||
chatrec = chatnet_find(dest);
|
||||
if (chatrec != NULL) {
|
||||
rec = create_chatnet_conn(chatrec->name, port, password, nick);
|
||||
rec = create_chatnet_conn(chatrec->name, port, password, nick, optlist);
|
||||
/* If rec is NULL the chatnet has no url to connect to */
|
||||
return rec;
|
||||
}
|
||||
@ -335,8 +398,20 @@ server_create_conn(int chat_type, const char *dest, int port,
|
||||
if (chatrec != NULL)
|
||||
chatnet = chatrec->name;
|
||||
|
||||
return create_addr_conn(chat_type, dest, port,
|
||||
chatnet, password, nick);
|
||||
return create_addr_conn(chat_type, dest, port, chatnet, password, nick, optlist);
|
||||
}
|
||||
|
||||
SERVER_CONNECT_REC *server_create_conn(int chat_type, const char *dest, int port,
|
||||
const char *chatnet, const char *password, const char *nick)
|
||||
{
|
||||
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,
|
||||
@ -409,7 +484,8 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
|
||||
rec->password = g_strdup(config_node_get_str(node, "password", NULL));
|
||||
|
||||
rec->use_tls = config_node_get_bool(node, "use_tls", FALSE) || config_node_get_bool(node, "use_ssl", FALSE);
|
||||
rec->tls_verify = config_node_get_bool(node, "tls_verify", FALSE) || config_node_get_bool(node, "ssl_verify", FALSE);
|
||||
rec->tls_verify = config_node_get_bool(node, "tls_verify", TRUE) ||
|
||||
config_node_get_bool(node, "ssl_verify", FALSE);
|
||||
|
||||
value = config_node_get_str(node, "tls_cert", NULL);
|
||||
if (value == NULL)
|
||||
@ -451,11 +527,6 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
|
||||
value = config_node_get_str(node, "ssl_pinned_pubkey", NULL);
|
||||
rec->tls_pinned_pubkey = g_strdup(value);
|
||||
|
||||
if (rec->tls_cafile || rec->tls_capath)
|
||||
rec->tls_verify = TRUE;
|
||||
if (rec->tls_cert != NULL || rec->tls_verify)
|
||||
rec->use_tls = TRUE;
|
||||
|
||||
rec->port = port;
|
||||
rec->autoconnect = config_node_get_bool(node, "autoconnect", FALSE);
|
||||
rec->no_proxy = config_node_get_bool(node, "no_proxy", FALSE);
|
||||
|
@ -31,6 +31,10 @@ server_create_conn(int chat_type, const char *dest, int port,
|
||||
const char *chatnet, const char *password,
|
||||
const char *nick);
|
||||
|
||||
SERVER_CONNECT_REC *server_create_conn_opt(int chat_type, const char *dest, int port,
|
||||
const char *chatnet, const char *password,
|
||||
const char *nick, GHashTable *optlist);
|
||||
|
||||
/* Find matching server from setup. Try to find record with a same port,
|
||||
but fallback to any server with the same address. */
|
||||
SERVER_SETUP_REC *server_setup_find(const char *address, int port,
|
||||
|
@ -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)
|
||||
|
@ -101,6 +101,7 @@ static SERVER_SETUP_REC *create_server_setup(GHashTable *optlist)
|
||||
|
||||
server = rec->create_server_setup();
|
||||
server->chat_type = rec->id;
|
||||
server->tls_verify = TRUE;
|
||||
return server;
|
||||
}
|
||||
|
||||
@ -110,6 +111,7 @@ static void cmd_server_add_modify(const char *data, gboolean add)
|
||||
SERVER_SETUP_REC *rec;
|
||||
char *addr, *portstr, *password, *value, *chatnet;
|
||||
void *free_arg;
|
||||
gboolean newrec;
|
||||
int port;
|
||||
|
||||
if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS,
|
||||
@ -135,6 +137,7 @@ static void cmd_server_add_modify(const char *data, gboolean add)
|
||||
rec = server_setup_find(addr, port, chatnet);
|
||||
|
||||
if (rec == NULL) {
|
||||
newrec = TRUE;
|
||||
if (add == FALSE) {
|
||||
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
TXT_SETUPSERVER_NOT_FOUND, addr, port);
|
||||
@ -150,6 +153,7 @@ static void cmd_server_add_modify(const char *data, gboolean add)
|
||||
rec->address = g_strdup(addr);
|
||||
rec->port = port;
|
||||
} else {
|
||||
newrec = FALSE;
|
||||
if (*portstr != '\0' || g_hash_table_lookup(optlist, "port"))
|
||||
rec->port = port;
|
||||
|
||||
@ -165,20 +169,17 @@ 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")) {
|
||||
rec->use_tls = TRUE;
|
||||
}
|
||||
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)
|
||||
value = g_hash_table_lookup(optlist, "ssl_cert");
|
||||
if (value != NULL && *value != '\0')
|
||||
if (value != NULL && *value != '\0') {
|
||||
rec->tls_cert = g_strdup(value);
|
||||
if (newrec) {
|
||||
/* convenience and backward compatibility, turn on tls if tls_cert is given
|
||||
*/
|
||||
rec->use_tls = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
value = g_hash_table_lookup(optlist, "tls_pkey");
|
||||
if (value == NULL)
|
||||
@ -192,11 +193,6 @@ static void cmd_server_add_modify(const char *data, gboolean add)
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->tls_pass = g_strdup(value);
|
||||
|
||||
if (g_hash_table_lookup(optlist, "tls_verify") || g_hash_table_lookup(optlist, "ssl_verify"))
|
||||
rec->tls_verify = TRUE;
|
||||
else if (g_hash_table_lookup(optlist, "notls_verify") || g_hash_table_lookup(optlist, "nossl_verify"))
|
||||
rec->tls_verify = FALSE;
|
||||
|
||||
value = g_hash_table_lookup(optlist, "tls_cafile");
|
||||
if (value == NULL)
|
||||
value = g_hash_table_lookup(optlist, "ssl_cafile");
|
||||
@ -231,8 +227,23 @@ static void cmd_server_add_modify(const char *data, gboolean add)
|
||||
|| (rec->tls_capath != NULL && rec->tls_capath[0] != '\0'))
|
||||
rec->tls_verify = TRUE;
|
||||
|
||||
if ((rec->tls_cert != NULL && rec->tls_cert[0] != '\0') || rec->tls_verify == TRUE)
|
||||
if (g_hash_table_lookup(optlist, "tls_verify") ||
|
||||
g_hash_table_lookup(optlist, "ssl_verify")) {
|
||||
rec->tls_verify = TRUE;
|
||||
if (newrec) {
|
||||
/* convenience and backward compatibility, turn on tls if tls_verify is
|
||||
* given */
|
||||
rec->use_tls = TRUE;
|
||||
}
|
||||
} else if (g_hash_table_lookup(optlist, "notls_verify") ||
|
||||
g_hash_table_lookup(optlist, "nossl_verify")) {
|
||||
rec->tls_verify = FALSE;
|
||||
}
|
||||
|
||||
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"))
|
||||
rec->use_tls = FALSE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "auto")) rec->autoconnect = TRUE;
|
||||
if (g_hash_table_lookup(optlist, "noauto")) rec->autoconnect = FALSE;
|
||||
@ -246,7 +257,7 @@ static void cmd_server_add_modify(const char *data, gboolean add)
|
||||
rec->own_ip4 = rec->own_ip6 = NULL;
|
||||
}
|
||||
|
||||
signal_emit("server add fill", 2, rec, optlist);
|
||||
signal_emit("server add fill", 3, rec, optlist, GINT_TO_POINTER(add));
|
||||
|
||||
server_setup_add(rec);
|
||||
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
|
@ -51,12 +51,13 @@ const char *get_visible_target(IRC_SERVER_REC *server, const char *target)
|
||||
return target;
|
||||
}
|
||||
|
||||
/* SYNTAX: SERVER ADD|MODIFY [-4 | -6] [-tls] [-tls_cert <cert>] [-tls_pkey <pkey>] [-tls_pass <password>]
|
||||
[-tls_verify] [-tls_cafile <cafile>] [-tls_capath <capath>]
|
||||
[-tls_ciphers <list>]
|
||||
/* SYNTAX: SERVER ADD|MODIFY [-4 | -6] [-tls_cert <cert>] [-tls_pkey <pkey>]
|
||||
[-tls_pass <password>] [-tls_verify] [-tls_cafile <cafile>]
|
||||
[-tls_capath <capath>] [-tls_ciphers <list>] [-tls | -notls]
|
||||
[-starttls | -nostarttls | -disallow_starttls | -nodisallow_starttls]
|
||||
[-auto | -noauto] [-network <network>] [-host <hostname>]
|
||||
[-cmdspeed <ms>] [-cmdmax <count>] [-port <port>]
|
||||
<address> [<port> [<password>]] */
|
||||
[-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)
|
||||
@ -85,6 +86,28 @@ static void sig_server_add_fill(IRC_SERVER_SETUP_REC *rec,
|
||||
if (value != NULL && *value != '\0') rec->max_cmds_at_once = atoi(value);
|
||||
value = g_hash_table_lookup(optlist, "querychans");
|
||||
if (value != NULL && *value != '\0') rec->max_query_chans = atoi(value);
|
||||
if (g_hash_table_lookup(optlist, "nodisallow_starttls") ||
|
||||
g_hash_table_lookup(optlist, "nostarttls"))
|
||||
rec->starttls = STARTTLS_NOTSET;
|
||||
if (g_hash_table_lookup(optlist, "disallow_starttls"))
|
||||
rec->starttls = STARTTLS_DISALLOW;
|
||||
if (g_hash_table_lookup(optlist, "starttls")) {
|
||||
rec->starttls = STARTTLS_ENABLED;
|
||||
rec->use_tls = 0;
|
||||
}
|
||||
if (g_hash_table_lookup(optlist, "nocap"))
|
||||
rec->no_cap = 1;
|
||||
if (g_hash_table_lookup(optlist, "cap"))
|
||||
rec->no_cap = 0;
|
||||
}
|
||||
|
||||
static void sig_server_waiting_info(IRC_SERVER_REC *server, const char *version)
|
||||
{
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_SERVER_WAITING_CAP_LS, server,
|
||||
version);
|
||||
}
|
||||
|
||||
/* SYNTAX: SERVER LIST */
|
||||
@ -108,29 +131,35 @@ 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_tls) {
|
||||
if (rec->no_cap)
|
||||
g_string_append(str, "nocap, ");
|
||||
if (rec->starttls == STARTTLS_DISALLOW)
|
||||
g_string_append(str, "disallow_starttls, ");
|
||||
if (rec->starttls == STARTTLS_ENABLED)
|
||||
g_string_append(str, "starttls, ");
|
||||
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->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->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->tls_verify)
|
||||
g_string_append(str, "notls_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)
|
||||
g_string_append_printf(str, "cmdmax: %d, ", rec->max_cmds_at_once);
|
||||
if (rec->cmd_queue_speed > 0)
|
||||
@ -153,13 +182,20 @@ static void cmd_server_list(const char *data)
|
||||
void fe_irc_server_init(void)
|
||||
{
|
||||
signal_add("server add fill", (SIGNAL_FUNC) sig_server_add_fill);
|
||||
signal_add("server waiting cap ls", (SIGNAL_FUNC) sig_server_waiting_info);
|
||||
command_bind("server list", NULL, (SIGNAL_FUNC) cmd_server_list);
|
||||
|
||||
command_set_options("server add", "-ircnet -network -cmdspeed -cmdmax -querychans");
|
||||
command_set_options("server add",
|
||||
"-ircnet -network -cmdspeed -cmdmax -querychans starttls "
|
||||
"nostarttls disallow_starttls nodisallow_starttls cap nocap");
|
||||
command_set_options("server modify",
|
||||
"-ircnet -network -cmdspeed -cmdmax -querychans starttls nostarttls "
|
||||
"disallow_starttls nodisallow_starttls cap nocap");
|
||||
}
|
||||
|
||||
void fe_irc_server_deinit(void)
|
||||
{
|
||||
signal_remove("server add fill", (SIGNAL_FUNC) sig_server_add_fill);
|
||||
signal_remove("server waiting cap ls", (SIGNAL_FUNC) sig_server_waiting_info);
|
||||
command_unbind("server list", (SIGNAL_FUNC) cmd_server_list);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ FORMAT_REC fecommon_irc_formats[] = {
|
||||
{ "setupserver_header", "%#Server Port Network Settings", 0 },
|
||||
{ "setupserver_line", "%#%|$[!20]0 $[5]1 $[10]2 $3", 4, { 0, 1, 0, 0 } },
|
||||
{ "setupserver_footer", "", 0 },
|
||||
{ "server_waiting_cap_ls", "Waiting for CAP LS response...", 2, { 0, 0 } },
|
||||
{ "sasl_success", "SASL authentication succeeded", 0 },
|
||||
{ "sasl_error", "Cannot authenticate via SASL ($0)", 1, { 0 } },
|
||||
{ "cap_req", "Capabilities requested: $0", 1, { 0 } },
|
||||
|
@ -23,6 +23,7 @@ enum {
|
||||
IRCTXT_SETUPSERVER_HEADER,
|
||||
IRCTXT_SETUPSERVER_LINE,
|
||||
IRCTXT_SETUPSERVER_FOOTER,
|
||||
IRCTXT_SERVER_WAITING_CAP_LS,
|
||||
IRCTXT_SASL_SUCCESS,
|
||||
IRCTXT_SASL_ERROR,
|
||||
IRCTXT_CAP_REQ,
|
||||
|
@ -177,12 +177,23 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
for (; *lines != NULL; lines++) {
|
||||
gchar *prefixedLine;
|
||||
int disconnected;
|
||||
if (prefixedChoice) {
|
||||
prefixedLine = g_strdup_printf(":user %s\n", *lines);
|
||||
} else {
|
||||
prefixedLine = g_strdup_printf("%s\n", *lines);
|
||||
}
|
||||
server_ref(server);
|
||||
signal_emit("server incoming", 2, server, prefixedLine);
|
||||
disconnected = server->disconnected;
|
||||
if (disconnected) {
|
||||
server_connect_unref(server->connrec);
|
||||
}
|
||||
server_unref(server);
|
||||
if (disconnected) {
|
||||
/* reconnect */
|
||||
test_server();
|
||||
}
|
||||
g_free(prefixedLine);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -104,12 +104,54 @@ static gboolean parse_cap_name(char *name, char **key, char **val)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void cap_process_request_queue(IRC_SERVER_REC *server)
|
||||
{
|
||||
/* No CAP has been requested */
|
||||
if (server->cap_queue == NULL) {
|
||||
irc_cap_finish_negotiation(server);
|
||||
} else {
|
||||
GSList *tmp;
|
||||
GString *cmd;
|
||||
int avail_caps = 0;
|
||||
|
||||
cmd = g_string_new("CAP REQ :");
|
||||
|
||||
/* To process the queue in order, we need to reverse the stack once */
|
||||
server->cap_queue = g_slist_reverse(server->cap_queue);
|
||||
|
||||
/* Check whether the cap is supported by the server */
|
||||
for (tmp = server->cap_queue; tmp != NULL; tmp = tmp->next) {
|
||||
if (g_hash_table_lookup_extended(server->cap_supported, tmp->data, NULL,
|
||||
NULL)) {
|
||||
if (avail_caps > 0)
|
||||
g_string_append_c(cmd, ' ');
|
||||
g_string_append(cmd, tmp->data);
|
||||
|
||||
avail_caps++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the queue here */
|
||||
i_slist_free_full(server->cap_queue, (GDestroyNotify) g_free);
|
||||
server->cap_queue = NULL;
|
||||
|
||||
/* If the server doesn't support any cap we requested close the negotiation here */
|
||||
if (avail_caps > 0) {
|
||||
signal_emit("server cap req", 2, server,
|
||||
cmd->str + sizeof("CAP REQ :") - 1);
|
||||
irc_send_cmd_now(server, cmd->str);
|
||||
} else {
|
||||
irc_cap_finish_negotiation(server);
|
||||
}
|
||||
|
||||
g_string_free(cmd, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void event_cap (IRC_SERVER_REC *server, char *args, char *nick, char *address)
|
||||
{
|
||||
GSList *tmp;
|
||||
GString *cmd;
|
||||
char *params, *evt, *list, *star, **caps;
|
||||
int i, caps_length, disable, avail_caps, multiline;
|
||||
int i, caps_length, disable, multiline;
|
||||
|
||||
params = event_get_params(args, 4, NULL, &evt, &star, &list);
|
||||
if (params == NULL)
|
||||
@ -174,42 +216,20 @@ static void event_cap (IRC_SERVER_REC *server, char *args, char *nick, char *add
|
||||
/* A multiline response is always terminated by a normal one,
|
||||
* wait until we receive that one to require any CAP */
|
||||
if (multiline == FALSE) {
|
||||
/* No CAP has been requested */
|
||||
if (server->cap_queue == NULL) {
|
||||
irc_cap_finish_negotiation(server);
|
||||
}
|
||||
else {
|
||||
cmd = g_string_new("CAP REQ :");
|
||||
|
||||
avail_caps = 0;
|
||||
|
||||
/* To process the queue in order, we need to reverse the stack once */
|
||||
server->cap_queue = g_slist_reverse(server->cap_queue);
|
||||
|
||||
/* Check whether the cap is supported by the server */
|
||||
for (tmp = server->cap_queue; tmp != NULL; tmp = tmp->next) {
|
||||
if (g_hash_table_lookup_extended(server->cap_supported, tmp->data, NULL, NULL)) {
|
||||
if (avail_caps > 0)
|
||||
g_string_append_c(cmd, ' ');
|
||||
g_string_append(cmd, tmp->data);
|
||||
|
||||
avail_caps++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the queue here */
|
||||
i_slist_free_full(server->cap_queue, (GDestroyNotify) g_free);
|
||||
server->cap_queue = NULL;
|
||||
|
||||
/* If the server doesn't support any cap we requested close the negotiation here */
|
||||
if (avail_caps > 0) {
|
||||
signal_emit("server cap req", 2, server, cmd->str + sizeof("CAP REQ :") - 1);
|
||||
irc_send_cmd_now(server, cmd->str);
|
||||
} else {
|
||||
irc_cap_finish_negotiation(server);
|
||||
}
|
||||
|
||||
g_string_free(cmd, TRUE);
|
||||
gboolean want_starttls =
|
||||
i_slist_find_string(server->cap_queue, CAP_STARTTLS) != NULL;
|
||||
server->cap_queue =
|
||||
i_slist_delete_string(server->cap_queue, CAP_STARTTLS, g_free);
|
||||
if (server->connrec->starttls) {
|
||||
/* the connection has requested starttls,
|
||||
no more data must be sent now */
|
||||
} else if (want_starttls &&
|
||||
g_hash_table_lookup_extended(server->cap_supported, CAP_STARTTLS,
|
||||
NULL, NULL)) {
|
||||
irc_server_send_starttls(server);
|
||||
/* no more data must be sent now */
|
||||
} else {
|
||||
cap_process_request_queue(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -301,12 +321,14 @@ static void event_invalid_cap (IRC_SERVER_REC *server, const char *data, const c
|
||||
|
||||
void irc_cap_init (void)
|
||||
{
|
||||
signal_add_last("server cap continue", (SIGNAL_FUNC) cap_process_request_queue);
|
||||
signal_add_first("event cap", (SIGNAL_FUNC) event_cap);
|
||||
signal_add_first("event 410", (SIGNAL_FUNC) event_invalid_cap);
|
||||
}
|
||||
|
||||
void irc_cap_deinit (void)
|
||||
{
|
||||
signal_remove("server cap continue", (SIGNAL_FUNC) cap_process_request_queue);
|
||||
signal_remove("event cap", (SIGNAL_FUNC) event_cap);
|
||||
signal_remove("event 410", (SIGNAL_FUNC) event_invalid_cap);
|
||||
}
|
||||
|
@ -1053,7 +1053,7 @@ void irc_commands_init(void)
|
||||
signal_add("whois end", (SIGNAL_FUNC) event_end_of_whois);
|
||||
signal_add("whowas event", (SIGNAL_FUNC) event_whowas);
|
||||
|
||||
command_set_options("connect", "+ircnet");
|
||||
command_set_options("connect", "+ircnet starttls disallow_starttls nocap");
|
||||
command_set_options("topic", "delete");
|
||||
command_set_options("list", "yes");
|
||||
command_set_options("away", "one all");
|
||||
|
@ -51,6 +51,9 @@ static void sig_server_connect_copy(SERVER_CONNECT_REC **dest,
|
||||
rec->sasl_mechanism = src->sasl_mechanism;
|
||||
rec->sasl_username = g_strdup(src->sasl_username);
|
||||
rec->sasl_password = g_strdup(src->sasl_password);
|
||||
rec->disallow_starttls = src->disallow_starttls;
|
||||
rec->starttls = src->starttls;
|
||||
rec->no_cap = src->no_cap;
|
||||
*dest = (SERVER_CONNECT_REC *) rec;
|
||||
}
|
||||
|
||||
@ -62,7 +65,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);
|
||||
|
@ -44,9 +44,15 @@ static void sig_server_setup_fill_reconn(IRC_SERVER_CONNECT_REC *conn,
|
||||
conn->max_cmds_at_once = sserver->max_cmds_at_once;
|
||||
if (sserver->max_query_chans > 0)
|
||||
conn->max_query_chans = sserver->max_query_chans;
|
||||
if (sserver->starttls == STARTTLS_DISALLOW)
|
||||
conn->disallow_starttls = 1;
|
||||
else if (sserver->starttls == STARTTLS_ENABLED)
|
||||
conn->starttls = 1;
|
||||
if (sserver->no_cap)
|
||||
conn->no_cap = 1;
|
||||
}
|
||||
|
||||
static void sig_server_setup_fill_connect(IRC_SERVER_CONNECT_REC *conn)
|
||||
static void sig_server_setup_fill_connect(IRC_SERVER_CONNECT_REC *conn, GHashTable *optlist)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
@ -62,6 +68,23 @@ static void sig_server_setup_fill_connect(IRC_SERVER_CONNECT_REC *conn)
|
||||
g_strdup(value) : NULL;
|
||||
}
|
||||
|
||||
static void sig_server_setup_fill_optlist(IRC_SERVER_CONNECT_REC *conn, GHashTable *optlist)
|
||||
{
|
||||
if (!IS_IRC_SERVER_CONNECT(conn))
|
||||
return;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "starttls") != NULL) {
|
||||
conn->starttls = 1;
|
||||
conn->use_tls = 0;
|
||||
} else if (g_hash_table_lookup(optlist, "disallow_starttls") != NULL) {
|
||||
conn->disallow_starttls = 1;
|
||||
}
|
||||
if (g_hash_table_lookup(optlist, "nocap"))
|
||||
conn->no_cap = 1;
|
||||
if (g_hash_table_lookup(optlist, "cap"))
|
||||
conn->no_cap = 0;
|
||||
}
|
||||
|
||||
static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
|
||||
IRC_CHATNET_REC *ircnet)
|
||||
{
|
||||
@ -174,6 +197,11 @@ static void sig_server_setup_read(IRC_SERVER_SETUP_REC *rec, CONFIG_NODE *node)
|
||||
rec->max_cmds_at_once = config_node_get_int(node, "cmds_max_at_once", 0);
|
||||
rec->cmd_queue_speed = config_node_get_int(node, "cmd_queue_speed", 0);
|
||||
rec->max_query_chans = config_node_get_int(node, "max_query_chans", 0);
|
||||
rec->starttls = config_node_get_bool(node, "starttls", STARTTLS_NOTSET);
|
||||
if (rec->starttls == STARTTLS_ENABLED) {
|
||||
rec->use_tls = 0;
|
||||
}
|
||||
rec->no_cap = config_node_get_bool(node, "no_cap", FALSE);
|
||||
}
|
||||
|
||||
static void sig_server_setup_saved(IRC_SERVER_SETUP_REC *rec,
|
||||
@ -188,6 +216,12 @@ static void sig_server_setup_saved(IRC_SERVER_SETUP_REC *rec,
|
||||
iconfig_node_set_int(node, "cmd_queue_speed", rec->cmd_queue_speed);
|
||||
if (rec->max_query_chans > 0)
|
||||
iconfig_node_set_int(node, "max_query_chans", rec->max_query_chans);
|
||||
if (rec->starttls != STARTTLS_NOTSET)
|
||||
iconfig_node_set_bool(node, "starttls", rec->starttls);
|
||||
else
|
||||
iconfig_node_set_str(node, "starttls", NULL);
|
||||
if (rec->no_cap)
|
||||
iconfig_node_set_bool(node, "no_cap", TRUE);
|
||||
}
|
||||
|
||||
void irc_servers_setup_init(void)
|
||||
@ -199,6 +233,7 @@ void irc_servers_setup_init(void)
|
||||
signal_add("server setup fill reconn", (SIGNAL_FUNC) sig_server_setup_fill_reconn);
|
||||
signal_add("server setup fill connect", (SIGNAL_FUNC) sig_server_setup_fill_connect);
|
||||
signal_add("server setup fill chatnet", (SIGNAL_FUNC) sig_server_setup_fill_chatnet);
|
||||
signal_add("server setup fill optlist", (SIGNAL_FUNC) sig_server_setup_fill_optlist);
|
||||
signal_add("server setup read", (SIGNAL_FUNC) sig_server_setup_read);
|
||||
signal_add("server setup saved", (SIGNAL_FUNC) sig_server_setup_saved);
|
||||
}
|
||||
@ -208,6 +243,7 @@ void irc_servers_setup_deinit(void)
|
||||
signal_remove("server setup fill reconn", (SIGNAL_FUNC) sig_server_setup_fill_reconn);
|
||||
signal_remove("server setup fill connect", (SIGNAL_FUNC) sig_server_setup_fill_connect);
|
||||
signal_remove("server setup fill chatnet", (SIGNAL_FUNC) sig_server_setup_fill_chatnet);
|
||||
signal_remove("server setup fill optlist", (SIGNAL_FUNC) sig_server_setup_fill_optlist);
|
||||
signal_remove("server setup read", (SIGNAL_FUNC) sig_server_setup_read);
|
||||
signal_remove("server setup saved", (SIGNAL_FUNC) sig_server_setup_saved);
|
||||
}
|
||||
|
@ -11,6 +11,12 @@
|
||||
#define IS_IRC_SERVER_SETUP(server) \
|
||||
(IRC_SERVER_SETUP(server) ? TRUE : FALSE)
|
||||
|
||||
enum {
|
||||
STARTTLS_DISALLOW = -1, /* */
|
||||
STARTTLS_NOTSET = 0,
|
||||
STARTTLS_ENABLED = 1
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
#include <irssi/src/core/server-setup-rec.h>
|
||||
|
||||
@ -18,6 +24,8 @@ typedef struct {
|
||||
int max_cmds_at_once;
|
||||
int cmd_queue_speed;
|
||||
int max_query_chans;
|
||||
int starttls;
|
||||
int no_cap : 1;
|
||||
} IRC_SERVER_SETUP_REC;
|
||||
|
||||
void irc_servers_setup_init(void);
|
||||
|
@ -20,10 +20,11 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
#include <irssi/src/core/net-sendbuffer.h>
|
||||
#include <irssi/src/core/signals.h>
|
||||
#include <irssi/src/core/rawlog.h>
|
||||
#include <irssi/src/core/misc.h>
|
||||
#include <irssi/src/core/net-sendbuffer.h>
|
||||
#include <irssi/src/core/network.h>
|
||||
#include <irssi/src/core/rawlog.h>
|
||||
#include <irssi/src/core/signals.h>
|
||||
|
||||
#include <irssi/src/core/channels.h>
|
||||
#include <irssi/src/core/queries.h>
|
||||
@ -207,7 +208,7 @@ static char **split_message(SERVER_REC *server, const char *target,
|
||||
strlen(target));
|
||||
}
|
||||
|
||||
static void server_init(IRC_SERVER_REC *server)
|
||||
static void server_init_2(IRC_SERVER_REC *server)
|
||||
{
|
||||
IRC_SERVER_CONNECT_REC *conn;
|
||||
char *address, *ptr, *username, *cmd;
|
||||
@ -216,8 +217,56 @@ static void server_init(IRC_SERVER_REC *server)
|
||||
|
||||
conn = server->connrec;
|
||||
|
||||
if (conn->proxy != NULL && conn->proxy_password != NULL &&
|
||||
*conn->proxy_password != '\0') {
|
||||
if (conn->password != NULL && *conn->password != '\0') {
|
||||
/* send password */
|
||||
cmd = g_strdup_printf("PASS %s", conn->password);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
|
||||
/* send nick */
|
||||
cmd = g_strdup_printf("NICK %s", conn->nick);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
|
||||
/* send user/realname */
|
||||
address = server->connrec->address;
|
||||
ptr = strrchr(address, ':');
|
||||
if (ptr != NULL) {
|
||||
/* IPv6 address .. doesn't work here, use the string after
|
||||
the last : char */
|
||||
address = ptr + 1;
|
||||
if (*address == '\0')
|
||||
address = "x";
|
||||
}
|
||||
|
||||
username = g_strdup(conn->username);
|
||||
ptr = strchr(username, ' ');
|
||||
if (ptr != NULL)
|
||||
*ptr = '\0';
|
||||
|
||||
cmd = g_strdup_printf("USER %s %s %s :%s", username, username, address, conn->realname);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
g_free(username);
|
||||
|
||||
if (conn->proxy != NULL && conn->proxy_string_after != NULL) {
|
||||
cmd = g_strdup_printf(conn->proxy_string_after, conn->address, conn->port);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void server_init_1(IRC_SERVER_REC *server)
|
||||
{
|
||||
IRC_SERVER_CONNECT_REC *conn;
|
||||
char *cmd;
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
conn = server->connrec;
|
||||
|
||||
if (conn->proxy != NULL && conn->proxy_password != NULL && *conn->proxy_password != '\0') {
|
||||
cmd = g_strdup_printf("PASS %s", conn->proxy_password);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
@ -243,45 +292,8 @@ static void server_init(IRC_SERVER_REC *server)
|
||||
irc_cap_toggle(server, CAP_ACCOUNT_NOTIFY, TRUE);
|
||||
irc_cap_toggle(server, CAP_SELF_MESSAGE, TRUE);
|
||||
irc_cap_toggle(server, CAP_SERVER_TIME, TRUE);
|
||||
|
||||
irc_send_cmd_now(server, "CAP LS " CAP_LS_VERSION);
|
||||
|
||||
if (conn->password != NULL && *conn->password != '\0') {
|
||||
/* send password */
|
||||
cmd = g_strdup_printf("PASS %s", conn->password);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
|
||||
/* send nick */
|
||||
cmd = g_strdup_printf("NICK %s", conn->nick);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
|
||||
/* send user/realname */
|
||||
address = server->connrec->address;
|
||||
ptr = strrchr(address, ':');
|
||||
if (ptr != NULL) {
|
||||
/* IPv6 address .. doesn't work here, use the string after
|
||||
the last : char */
|
||||
address = ptr+1;
|
||||
if (*address == '\0')
|
||||
address = "x";
|
||||
}
|
||||
|
||||
username = g_strdup(conn->username);
|
||||
ptr = strchr(username, ' ');
|
||||
if (ptr != NULL) *ptr = '\0';
|
||||
|
||||
cmd = g_strdup_printf("USER %s %s %s :%s", username, username, address, conn->realname);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
g_free(username);
|
||||
|
||||
if (conn->proxy != NULL && conn->proxy_string_after != NULL) {
|
||||
cmd = g_strdup_printf(conn->proxy_string_after, conn->address, conn->port);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
if (!conn->use_tls && (conn->starttls || !conn->disallow_starttls)) {
|
||||
irc_cap_toggle(server, CAP_STARTTLS, TRUE);
|
||||
}
|
||||
|
||||
server->isupport = g_hash_table_new((GHashFunc) i_istr_hash, (GCompareFunc) i_istr_equal);
|
||||
@ -296,6 +308,119 @@ static void server_init(IRC_SERVER_REC *server)
|
||||
/* this will reset to 1 sec after we get the 001 event */
|
||||
server->wait_cmd = g_get_real_time();
|
||||
server->wait_cmd += 120 * G_USEC_PER_SEC;
|
||||
|
||||
if (!conn->no_cap) {
|
||||
signal_emit("server waiting cap ls", 2, server, CAP_LS_VERSION);
|
||||
irc_send_cmd_now(server, "CAP LS " CAP_LS_VERSION);
|
||||
/* to detect non-CAP servers, send this bogus join */
|
||||
irc_send_cmd_now(server, "JOIN ");
|
||||
}
|
||||
if (conn->starttls)
|
||||
irc_server_send_starttls(server);
|
||||
else if (conn->no_cap)
|
||||
server_init_2(server);
|
||||
}
|
||||
|
||||
static void init_ssl_loop(IRC_SERVER_REC *server, GIOChannel *handle)
|
||||
{
|
||||
int error;
|
||||
server->connrec->starttls = 1;
|
||||
|
||||
if (server->starttls_tag) {
|
||||
g_source_remove(server->starttls_tag);
|
||||
server->starttls_tag = 0;
|
||||
}
|
||||
|
||||
error = irssi_ssl_handshake(handle);
|
||||
if (error == -1) {
|
||||
server->connection_lost = TRUE;
|
||||
server_disconnect((SERVER_REC *) server);
|
||||
return;
|
||||
}
|
||||
if (error & 1) { /* wait */
|
||||
server->starttls_tag =
|
||||
i_input_add(handle, error == 1 ? I_INPUT_READ : I_INPUT_WRITE,
|
||||
(GInputFunction) init_ssl_loop, server);
|
||||
return;
|
||||
}
|
||||
/* continue */
|
||||
rawlog_redirect(server->rawlog, "Now talking encrypted");
|
||||
signal_emit("server connection switched", 1, server);
|
||||
if (!server->cap_supported) {
|
||||
server_init_2(server);
|
||||
} else {
|
||||
signal_emit("server cap continue", 1, server);
|
||||
}
|
||||
|
||||
if (settings_get_bool("starttls_sts")) {
|
||||
IRC_SERVER_SETUP_REC *ssetup = IRC_SERVER_SETUP(server_setup_find(
|
||||
server->connrec->address, server->connrec->port, server->connrec->chatnet));
|
||||
if (ssetup != NULL) {
|
||||
ssetup->starttls = STARTTLS_ENABLED;
|
||||
server_setup_add((SERVER_SETUP_REC *) ssetup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <irssi/src/core/line-split.h>
|
||||
void irc_server_send_starttls(IRC_SERVER_REC *server)
|
||||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
g_warning("[%s] Now attempting STARTTLS", server->tag);
|
||||
irc_send_cmd_now(server, "STARTTLS");
|
||||
}
|
||||
|
||||
static void event_starttls(IRC_SERVER_REC *server, const char *data)
|
||||
{
|
||||
GIOChannel *ssl_handle;
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
if (server->handle->readbuffer != NULL &&
|
||||
!line_split_is_empty(server->handle->readbuffer)) {
|
||||
char *str;
|
||||
line_split("", -1, &str, &server->handle->readbuffer);
|
||||
}
|
||||
ssl_handle = net_start_ssl((SERVER_REC *) server);
|
||||
if (ssl_handle != NULL) {
|
||||
g_source_remove(server->readtag);
|
||||
server->readtag = -1;
|
||||
server->handle->handle = ssl_handle;
|
||||
init_ssl_loop(server, server->handle->handle);
|
||||
} else {
|
||||
g_warning("net_start_ssl failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void event_registerfirst(IRC_SERVER_REC *server, const char *data)
|
||||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
if (server->connected)
|
||||
return;
|
||||
|
||||
if (!server->cap_supported && !server->connrec->starttls)
|
||||
server_init_2(server);
|
||||
}
|
||||
|
||||
static void event_capend(IRC_SERVER_REC *server)
|
||||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
if (server->connected)
|
||||
return;
|
||||
|
||||
server_init_2(server);
|
||||
}
|
||||
|
||||
SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn)
|
||||
@ -348,6 +473,27 @@ void irc_server_connect(SERVER_REC *server)
|
||||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
if (server->connrec->connect_handle != NULL) {
|
||||
/* an existing handle from upgrade */
|
||||
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);
|
||||
@ -420,7 +566,7 @@ static void sig_connected(IRC_SERVER_REC *server)
|
||||
server->splits = g_hash_table_new((GHashFunc) i_istr_hash, (GCompareFunc) i_istr_equal);
|
||||
|
||||
if (!server->session_reconnect)
|
||||
server_init(server);
|
||||
server_init_1(server);
|
||||
}
|
||||
|
||||
static void isupport_destroy_hash(void *key, void *value)
|
||||
@ -429,6 +575,17 @@ static void isupport_destroy_hash(void *key, void *value)
|
||||
g_free(value);
|
||||
}
|
||||
|
||||
static void sig_disconnected(IRC_SERVER_REC *server)
|
||||
{
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
if (server->starttls_tag) {
|
||||
g_source_remove(server->starttls_tag);
|
||||
server->starttls_tag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void sig_destroyed(IRC_SERVER_REC *server)
|
||||
{
|
||||
GSList *tmp;
|
||||
@ -650,20 +807,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);
|
||||
@ -674,7 +828,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)
|
||||
@ -687,7 +843,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);
|
||||
@ -1048,6 +1206,7 @@ void irc_server_init_isupport(IRC_SERVER_REC *server)
|
||||
|
||||
void irc_servers_init(void)
|
||||
{
|
||||
settings_add_bool("servers", "starttls_sts", TRUE);
|
||||
settings_add_choice("servers", "rejoin_channels_on_reconnect", 1, "off;on;auto");
|
||||
settings_add_str("misc", "usermode", DEFAULT_USER_MODE);
|
||||
settings_add_str("misc", "split_line_start", "");
|
||||
@ -1059,9 +1218,13 @@ void irc_servers_init(void)
|
||||
cmd_tag = -1;
|
||||
|
||||
signal_add_first("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
signal_add_first("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
signal_add_last("server destroyed", (SIGNAL_FUNC) sig_destroyed);
|
||||
signal_add_last("server quit", (SIGNAL_FUNC) sig_server_quit);
|
||||
signal_add("server cap ack " CAP_MAXLINE, (SIGNAL_FUNC) cap_maxline);
|
||||
signal_add("event 670", (SIGNAL_FUNC) event_starttls);
|
||||
signal_add("event 451", (SIGNAL_FUNC) event_registerfirst);
|
||||
signal_add("server cap end", (SIGNAL_FUNC) event_capend);
|
||||
signal_add("event 001", (SIGNAL_FUNC) event_connected);
|
||||
signal_add("event 004", (SIGNAL_FUNC) event_server_info);
|
||||
signal_add("event 005", (SIGNAL_FUNC) event_isupport);
|
||||
@ -1087,9 +1250,13 @@ void irc_servers_deinit(void)
|
||||
g_source_remove(cmd_tag);
|
||||
|
||||
signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
signal_remove("server destroyed", (SIGNAL_FUNC) sig_destroyed);
|
||||
signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
|
||||
signal_remove("server cap ack " CAP_MAXLINE, (SIGNAL_FUNC) cap_maxline);
|
||||
signal_remove("event 670", (SIGNAL_FUNC) event_starttls);
|
||||
signal_remove("event 451", (SIGNAL_FUNC) event_registerfirst);
|
||||
signal_remove("server cap end", (SIGNAL_FUNC) event_capend);
|
||||
signal_remove("event 001", (SIGNAL_FUNC) event_connected);
|
||||
signal_remove("event 004", (SIGNAL_FUNC) event_server_info);
|
||||
signal_remove("event 005", (SIGNAL_FUNC) event_isupport);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#define CAP_ACCOUNT_NOTIFY "account-notify"
|
||||
#define CAP_SELF_MESSAGE "znc.in/self-message"
|
||||
#define CAP_SERVER_TIME "server-time"
|
||||
#define CAP_STARTTLS "tls"
|
||||
|
||||
/* returns IRC_SERVER_REC if it's IRC server, NULL if it isn't */
|
||||
#define IRC_SERVER(server) \
|
||||
@ -42,6 +43,7 @@
|
||||
#define IS_IRC_SERVER_CONNECT(conn) \
|
||||
(IRC_SERVER_CONNECT(conn) ? TRUE : FALSE)
|
||||
|
||||
/* clang-format off */
|
||||
/* all strings should be either NULL or dynamically allocated */
|
||||
/* address and nick are mandatory, rest are optional */
|
||||
struct _IRC_SERVER_CONNECT_REC {
|
||||
@ -59,7 +61,11 @@ struct _IRC_SERVER_CONNECT_REC {
|
||||
int max_query_chans;
|
||||
|
||||
int max_kicks, max_msgs, max_modes, max_whois;
|
||||
int disallow_starttls:1;
|
||||
int starttls:1;
|
||||
int no_cap:1;
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
#define STRUCT_SERVER_CONNECT_REC IRC_SERVER_CONNECT_REC
|
||||
struct _IRC_SERVER_REC {
|
||||
@ -136,6 +142,7 @@ struct _IRC_SERVER_REC {
|
||||
GSList *rejoin_channels; /* try to join to these channels after a while -
|
||||
channels go here if they're "temporarily unavailable"
|
||||
because of netsplits */
|
||||
guint starttls_tag; /* Holds the source id of the running timeout */
|
||||
struct _SERVER_QUERY_REC *chanqueries;
|
||||
|
||||
GHashTable *isupport;
|
||||
@ -151,10 +158,17 @@ 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: */
|
||||
void irc_server_send_action(IRC_SERVER_REC *server, const char *target,
|
||||
const char *data);
|
||||
|
@ -23,8 +23,10 @@
|
||||
#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-servers-setup.h>
|
||||
#include <irssi/src/irc/core/irc-channels.h>
|
||||
#include <irssi/src/irc/core/irc-nicklist.h>
|
||||
|
||||
@ -43,6 +45,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 +61,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 +82,27 @@ 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 ? STARTTLS_DISALLOW :
|
||||
server->connrec->starttls ? STARTTLS_ENABLED :
|
||||
STARTTLS_NOTSET);
|
||||
|
||||
config_node_set_bool(config, node, "no_cap", server->connrec->no_cap);
|
||||
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;
|
||||
@ -96,6 +116,7 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
|
||||
server->emode_known = config_node_get_bool(node, "emode_known", FALSE);
|
||||
server->isupport_sent = config_node_get_bool(node, "isupport_sent", FALSE);
|
||||
|
||||
server->connrec->no_cap = config_node_get_bool(node, "no_cap", FALSE);
|
||||
server->connrec->sasl_mechanism = config_node_get_int(node, "sasl_mechanism", SASL_MECHANISM_NONE);
|
||||
/* The fields below might have been filled when loading the chatnet
|
||||
* description from the config and we favor the content that's been saved
|
||||
@ -105,6 +126,16 @@ 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", STARTTLS_NOTSET);
|
||||
if (starttls_mode == STARTTLS_DISALLOW)
|
||||
server->connrec->disallow_starttls = 1;
|
||||
if (starttls_mode == STARTTLS_ENABLED) {
|
||||
server->connrec->starttls = 1;
|
||||
server->connrec->use_tls = 0;
|
||||
}
|
||||
|
||||
if (server->isupport == NULL) {
|
||||
server->isupport =
|
||||
g_hash_table_new((GHashFunc) i_istr_hash, (GCompareFunc) i_istr_equal);
|
||||
@ -123,6 +154,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,
|
||||
|
@ -579,6 +579,7 @@ void irc_irc_init(void)
|
||||
signal_add("server event", (SIGNAL_FUNC) irc_server_event);
|
||||
signal_add("server event tags", (SIGNAL_FUNC) irc_server_event_tags);
|
||||
signal_add("server connected", (SIGNAL_FUNC) irc_init_server);
|
||||
signal_add("server connection switched", (SIGNAL_FUNC) irc_init_server);
|
||||
signal_add("server incoming", (SIGNAL_FUNC) irc_parse_incoming_line);
|
||||
|
||||
current_server_event = NULL;
|
||||
@ -593,5 +594,6 @@ void irc_irc_deinit(void)
|
||||
signal_remove("server event", (SIGNAL_FUNC) irc_server_event);
|
||||
signal_remove("server event tags", (SIGNAL_FUNC) irc_server_event_tags);
|
||||
signal_remove("server connected", (SIGNAL_FUNC) irc_init_server);
|
||||
signal_remove("server connection switched", (SIGNAL_FUNC) irc_init_server);
|
||||
signal_remove("server incoming", (SIGNAL_FUNC) irc_parse_incoming_line);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user