use starttls

This commit is contained in:
ailin-nemui 2020-04-05 13:18:54 +02:00 committed by Ailin Nemui
commit 51508ff1d3
13 changed files with 324 additions and 116 deletions

View file

@ -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,17 +208,17 @@ 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);
static void server_init_1(IRC_SERVER_REC *server)
{
IRC_SERVER_CONNECT_REC *conn;
char *address, *ptr, *username, *cmd;
char *cmd;
g_return_if_fail(server != NULL);
conn = server->connrec;
if (conn->proxy != NULL && conn->proxy_password != NULL &&
*conn->proxy_password != '\0') {
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 +244,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->no_starttls)) {
irc_cap_toggle(server, CAP_STARTTLS, TRUE);
}
server->isupport = g_hash_table_new((GHashFunc) i_istr_hash, (GCompareFunc) i_istr_equal);
@ -296,6 +260,163 @@ 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;
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);
}
static void init_ssl_loop(IRC_SERVER_REC *server, GIOChannel *handle)
{
int error;
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);
}
server->connrec->starttls = 1;
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 = 1;
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("Now attempting STARTTLS");
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);
}
static void server_init_2(IRC_SERVER_REC *server)
{
IRC_SERVER_CONNECT_REC *conn;
char *address, *ptr, *username, *cmd;
g_return_if_fail(server != NULL);
conn = server->connrec;
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);
}
}
SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn)
@ -420,7 +541,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 +550,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;
@ -1048,6 +1180,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 +1192,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 +1224,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);