mirror of
https://github.com/irssi/irssi.git
synced 2026-08-08 19:30:15 +02:00
Merge pull request #1170 from ailin-nemui/starttls
use starttls / enable tls_verify
This commit is contained in:
commit
4432b0bf0d
25 changed files with 643 additions and 234 deletions
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue