From c79aae7824b96d24321bbeef881feb53f204fbd9 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 10:57:46 +0100 Subject: [PATCH 01/15] PROXY: implemented native proxy support For the original patch by Enrico Scholz 26 Feb 2008 This patch creates a hook into the net_connect*() methods which call a method to connect to a proxy. Previous solution to send certain strings in the normal IRC dialog was some kind of hack as most proxies require some kind of negotation. E.g. HTTP proxies sent a 'HTTP/1.0 200 Connection established' HTTP header and clients have to wait for it. Else, sent bytes of the following IRC login will be dropped silently. With old method, it is also impossible to tunnel SSL IRC connections through the proxy as proxy speaks plain text or a special protocol while e.g. 'CONNECT ... HTTP/1.0' will be encrypted with key of IRC server. There are further enhancements possible: the whole net_connect stuff should be made asynchronously. Currently, only the hostname is resolved in the background (which makes little sense of local proxies usually). --- src/core/Makefile.am | 3 + src/core/network-openssl.c | 4 +- src/core/network-proxy-priv.h | 128 ++++++++++++++++++++++++++++++++++ src/core/network-proxy.h | 81 +++++++++++++++++++++ src/core/network.c | 13 +++- src/core/network.h | 7 +- src/core/server-connect-rec.h | 5 +- src/core/servers-reconnect.c | 7 +- src/core/servers-setup.c | 15 ++-- src/core/servers.c | 23 +++--- src/irc/core/irc-servers.c | 29 ++++---- 11 files changed, 267 insertions(+), 48 deletions(-) create mode 100644 src/core/network-proxy-priv.h create mode 100644 src/core/network-proxy.h diff --git a/src/core/Makefile.am b/src/core/Makefile.am index fc32e17e..ce4b4bb6 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -31,6 +31,9 @@ libcore_a_SOURCES = \ net-sendbuffer.c \ network.c \ network-openssl.c \ + network-proxy.c \ + network-proxy.h \ + network-proxy-priv.h \ nicklist.c \ nickmatch-cache.c \ pidwait.c \ diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index a18e6fc7..3b0f3c18 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -565,11 +565,11 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ return gchan; } -GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, SERVER_REC *server) +GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify) { GIOChannel *handle, *ssl_handle; - handle = net_connect_ip(ip, port, my_ip); + handle = net_connect_proxy(proxy, host, port, ip, my_ip); if (handle == NULL) return NULL; ssl_handle = irssi_ssl_get_iochannel(handle, port, server); diff --git a/src/core/network-proxy-priv.h b/src/core/network-proxy-priv.h new file mode 100644 index 00000000..e4d5e22b --- /dev/null +++ b/src/core/network-proxy-priv.h @@ -0,0 +1,128 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef H_IRSSI_SRC_CORE_PROXY_PRIV_H +#define H_IRSSI_SRC_CORE_PROXY_PRIV_H + +#include "settings.h" +#include + +/* stolen from linux kernel */ +#define container_of(ptr, type, member) __extension__ ({ \ + const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + + +inline static void +_network_proxy_create(struct network_proxy *dst) +{ + dst->port = settings_get_int("proxy_port"); + dst->host = g_strdup(settings_get_str("proxy_address")); +} + +inline static void +_network_proxy_clone(struct network_proxy *dst, struct network_proxy const *src) +{ + dst->host = g_strdup(src->host); + dst->port = src->port; + + dst->destroy = src->destroy; + dst->connect = src->connect; + dst->clone = src->clone; +} + +inline static void +_network_proxy_destroy(struct network_proxy *proxy) +{ + g_free((void *)proxy->host); +} + + + +inline static bool +_network_proxy_send_all(GIOChannel *ch, void const *buf, ssize_t len) +{ + GError *err = NULL; + gsize written; + GIOStatus status; + + while ((status=g_io_channel_write_chars(ch, buf, len, &written, + &err))==G_IO_STATUS_AGAIN) + continue; + + if (status==G_IO_STATUS_NORMAL) + return true; + + if (err) { + g_warning("failed to send proxy request: %s", err->message); + g_error_free(err); + } + + return false; +} + +inline static bool +_network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t len) +{ + GError *err = NULL; + gchar *buf = buf_v; + + while (len>0) { + GIOStatus status; + gsize l; + + status = g_io_channel_read_chars(ch, buf, len, &l, &err); + if (status==G_IO_STATUS_AGAIN) + continue; + if (status!=G_IO_STATUS_NORMAL) + break; + + buf = l; + len -= l; + } + + if (len==0) + return true; + + if (err) { + g_warning("failed to send proxy request: %s", err->message); + g_error_free(err); + } + + return false; +} + +inline static bool +_network_proxy_flush(GIOChannel *ch) +{ + GError *err = NULL; + GIOStatus status; + + while ((status=g_io_channel_flush(ch, &err))==G_IO_STATUS_AGAIN) + continue; + + if (status==G_IO_STATUS_NORMAL) + return true; + + if (err) { + g_warning("failed to flush proxy channel: %s", err->message); + g_error_free(err); + } + + return false; +} + +#endif /* H_IRSSI_SRC_CORE_PROXY_PRIV_H */ diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h new file mode 100644 index 00000000..15ff33a0 --- /dev/null +++ b/src/core/network-proxy.h @@ -0,0 +1,81 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef H_IRSSI_SRC_CORE_PROXY_H +#define H_IRSSI_SRC_CORE_PROXY_H + +#include +#include + +/* helper structure for the send_string*() functions of the network_proxy + * class */ +struct network_proxy_send_string_info +{ + char const *host; /* hostname of the IRC server */ + uint16_t port; /* portnumber of the IRC server */ + + /* function which is used to send string; usually irc_send_cmd_now() */ + void (*func)(void *obj, char const *); + + /* object for func */ + void *obj; +}; + +struct network_proxy { + /* destroys the network_proxy structure which must not be used anymore + * after; this memberfunction is mandatory */ + void (*destroy)(struct network_proxy *); + + /* connects through the proxy; this memberfunction is mandatory + * + * \arg hint_ip the asynchronously resolved ip of the proxy; when + * NULL, method will resolve it itself + * \arg address the hostname where proxy shall connect to + * \arg port port address where proxy shall connect to + */ + GIOChannel * (*connect)(struct network_proxy const *, IPADDR const *hint_ip, + char const *address, int port); + + /* clones the given network_proxy object; this memberfunction is + * mandatory */ + struct network_proxy * (*clone)(struct network_proxy const *); + + + /* sends a string after connection has been established but before IRC + * authentication begins; this memberfunction is optional + */ + void (*send_string)(struct network_proxy const *, + struct network_proxy_send_string_info const *); + + /* sends a string after connection IRC authentication suceeded; this + * memberfunction is optional + */ + void (*send_string_after)(struct network_proxy const *, + struct network_proxy_send_string_info const *); + + + /* hostname of proxy host */ + char const *host; + + /* portnumber of proxy */ + int port; +}; + +/* factory method to create a proxy object based upon value of 'type' */ +struct network_proxy * network_proxy_create(char const *type); + + +#endif /* H_IRSSI_SRC_CORE_PROXY_H */ diff --git a/src/core/network.c b/src/core/network.c index 3e1b7c70..9f0aee01 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -20,6 +20,7 @@ #include "module.h" #include "network.h" +#include "network-proxy.h" #include @@ -145,7 +146,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) } /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) +GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; @@ -196,6 +197,16 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) return g_io_channel_new(handle); } +/* Connect to socket */ +GIOChannel *net_connect_proxy(struct network_proxy const *proxy, + char const *host, int port, IPADDR *ip, IPADDR *my_ip) +{ + if (proxy) + return proxy->connect(proxy, ip, host, port); + else + return net_connect_ip(ip, port, my_ip); +} + /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path) { diff --git a/src/core/network.h b/src/core/network.h index fb627b4d..c88e9bc0 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -29,6 +29,7 @@ struct _IPADDR { #define IPADDR_IS_V6(ip) ((ip)->family != AF_INET) +struct network_proxy; extern IPADDR ip4_any; GIOChannel *g_io_channel_new(int handle); @@ -39,10 +40,12 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ -GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, SERVER_REC *server); +GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip); +GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify); + int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); +GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip); /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path); /* Disconnect socket */ diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h index 80c5761b..e6345692 100644 --- a/src/core/server-connect-rec.h +++ b/src/core/server-connect-rec.h @@ -5,10 +5,7 @@ int chat_type; /* chat_protocol_lookup(xx) */ int refcount; -/* if we're connecting via proxy, or just NULLs */ -char *proxy; -int proxy_port; -char *proxy_string, *proxy_string_after, *proxy_password; +struct network_proxy *proxy; unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */ char *tag; /* try to keep this tag when connected to server */ diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index f419035b..3190af61 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -29,6 +29,7 @@ #include "servers-reconnect.h" #include "settings.h" +#include "network-proxy.h" GSList *reconnects; static int last_reconnect_tag; @@ -157,11 +158,7 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info) server_connect_ref(dest); dest->type = module_get_uniq_id("SERVER CONNECT", 0); dest->reconnection = src->reconnection; - dest->proxy = g_strdup(src->proxy); - dest->proxy_port = src->proxy_port; - dest->proxy_string = g_strdup(src->proxy_string); - dest->proxy_string_after = g_strdup(src->proxy_string_after); - dest->proxy_password = g_strdup(src->proxy_password); + dest->proxy = src->proxy ? src->proxy->clone(src->proxy) : NULL; dest->tag = g_strdup(src->tag); diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 0cecfece..9bc0e422 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -28,6 +28,7 @@ #include "chatnets.h" #include "servers.h" #include "servers-setup.h" +#include "network-proxy.h" GSList *setupservers; @@ -129,15 +130,6 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn, conn->username = g_strdup(settings_get_str("user_name")); conn->realname = g_strdup(settings_get_str("real_name")); - /* proxy settings */ - if (settings_get_bool("use_proxy")) { - conn->proxy = g_strdup(settings_get_str("proxy_address")); - conn->proxy_port = settings_get_int("proxy_port"); - conn->proxy_string = g_strdup(settings_get_str("proxy_string")); - conn->proxy_string_after = g_strdup(settings_get_str("proxy_string_after")); - conn->proxy_password = g_strdup(settings_get_str("proxy_password")); - } - /* source IP */ if (source_host_ip4 != NULL) { conn->own_ip4 = g_new(IPADDR, 1); @@ -148,6 +140,10 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn, memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR)); } + /* proxy settings */ + if (settings_get_bool("use_proxy")) + conn->proxy = network_proxy_create(settings_get_str("proxy_type")); + signal_emit("server setup fill connect", 1, conn); } @@ -598,6 +594,7 @@ void servers_setup_init(void) settings_add_str("proxy", "proxy_string", "CONNECT %s %d"); settings_add_str("proxy", "proxy_string_after", ""); settings_add_str("proxy", "proxy_password", ""); + settings_add_str("proxy", "proxy_type", "simple"); setupservers = NULL; source_host_ip4 = source_host_ip6 = NULL; diff --git a/src/core/servers.c b/src/core/servers.c index 3342304e..c8183675 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -34,6 +34,7 @@ #include "servers-setup.h" #include "channels.h" #include "queries.h" +#include "network-proxy.h" GSList *servers, *lookup_servers; @@ -219,10 +220,18 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip, if (ip != NULL) { own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4; - port = server->connrec->proxy != NULL ? - server->connrec->proxy_port : server->connrec->port; + port = server->connrec->port; handle = server->connrec->use_ssl ? - net_connect_ip_ssl(ip, port, own_ip, server) : net_connect_ip(ip, port, own_ip); + net_connect_proxy_ssl(server->connrec->proxy, + server->connrec->address, port, + ip, own_ip, + server->connrec->ssl_cert, + server->connrec->ssl_pkey, + server->connrec->ssl_cafile, + server->connrec->ssl_capath, server->connrec->ssl_verify) : + net_connect_proxy(server->connrec->proxy, + server->connrec->address, port, + ip, own_ip); } else { handle = net_connect_unix(unix_socket); } @@ -419,7 +428,7 @@ int server_start_connect(SERVER_REC *server) server->connect_pipe[1] = g_io_channel_new(fd[1]); connect_address = server->connrec->proxy != NULL ? - server->connrec->proxy : server->connrec->address; + server->connrec->proxy->host : server->connrec->address; server->connect_pid = net_gethostbyname_nonblock(connect_address, server->connect_pipe[1], @@ -614,10 +623,8 @@ void server_connect_unref(SERVER_CONNECT_REC *conn) if (conn->connect_handle != NULL) net_disconnect(conn->connect_handle); - g_free_not_null(conn->proxy); - g_free_not_null(conn->proxy_string); - g_free_not_null(conn->proxy_string_after); - g_free_not_null(conn->proxy_password); + if (conn->proxy) + conn->proxy->destroy(conn->proxy); g_free_not_null(conn->tag); g_free_not_null(conn->address); diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 1df95f70..5bac1445 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -41,6 +41,7 @@ #include "servers-reconnect.h" #include "servers-redirect.h" #include "modes.h" +#include "network-proxy.h" #include "settings.h" #include "recode.h" @@ -214,22 +215,19 @@ static void server_init(IRC_SERVER_REC *server) char *address, *ptr, *username, *cmd; GTimeVal now; + struct network_proxy_send_string_info const send_info = { + .host = server->connrec->address, + .port = server->connrec->port, + .func = irc_send_cmd_now_wrapper, + .obj = server + }; + 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); - } - - if (conn->proxy != NULL && conn->proxy_string != NULL) { - cmd = g_strdup_printf(conn->proxy_string, conn->address, conn->port); - irc_send_cmd_now(server, cmd); - g_free(cmd); - } + if (conn->proxy && conn->proxy->send_string) + conn->proxy->send_string(conn->proxy, &send_info); if (conn->sasl_mechanism != SASL_MECHANISM_NONE) cap_toggle(server, "sasl", TRUE); @@ -270,11 +268,8 @@ static void server_init(IRC_SERVER_REC *server) 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->proxy && conn->proxy->send_string_after) + conn->proxy->send_string_after(conn->proxy, &send_info); server->isupport = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); From 3698ae06ffde28c921a373370293a268180bbbd5 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 11:17:48 +0100 Subject: [PATCH 02/15] PROXY/HTTP: added methods for HTTP proxies From original patch by Enrico Scholz 26 Feb 2008 This patch adds code for connecting through HTTP proxies. Open issues are: * support of proxy authentication * a possible DOS due to the usage of g_io_channel_read_line_string() which does not allow to specify a maximum length of line. --- src/core/network-proxy-http.c | 193 ++++++++++++++++++++++++++++++++++ src/core/network-proxy-http.h | 29 +++++ 2 files changed, 222 insertions(+) create mode 100644 src/core/network-proxy-http.c create mode 100644 src/core/network-proxy-http.h diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c new file mode 100644 index 00000000..4e17d5c1 --- /dev/null +++ b/src/core/network-proxy-http.c @@ -0,0 +1,193 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "module.h" +#include "network-proxy-http.h" + +#include +#include +#include +#include + +#include "network.h" +#include "network-proxy-priv.h" + +static void +network_proxy_http_destroy(struct network_proxy *proxy) +{ + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + + g_free((void *)self->password); + _network_proxy_destroy(proxy); + + g_free(self); +} + +static struct network_proxy * +network_proxy_http_clone(struct network_proxy const *proxy) +{ + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct _network_proxy_http *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_clone(&res->proxy, &self->proxy); + res->password = g_strdup(self->password); + return &res->proxy; +} + +static bool +send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, char const *address, uint16_t port) +{ + char port_str[6]; + + (void)proxy; + sprintf(port_str, "%u", port); + + if (!_network_proxy_send_all(ch, "CONNECT ", -1) || + !_network_proxy_send_all(ch, address, -1) || + !_network_proxy_send_all(ch, ":", -1) || + !_network_proxy_send_all(ch, port_str, -1) || + !_network_proxy_send_all(ch, " HTTP/1.0\r\n\r\n", -1) || + !_network_proxy_flush(ch)) + return -1; + + return true; +} + +static int +read_response(struct _network_proxy_http *proxy, GIOChannel *ch) +{ + GIOStatus status; + GString line = { .str = NULL }; + gsize term_pos; + GError *err = NULL; + int state = 0; + int rc = 0; + gchar *resp = NULL; + + (void)proxy; + for (;;) { + /* TODO: a malicious proxy can DOS us by sending much data + * without a line break */ + while ((status=g_io_channel_read_line_string(ch, &line, &term_pos, + &err))==G_IO_STATUS_AGAIN) + { + /* noop */ + } + + if (status!=G_IO_STATUS_NORMAL) { + g_warning("failed to read HTTP response: %s", err->message); + goto err; + } + + if (state==0) { + if (g_str_has_prefix(line.str, "HTTP/1.0 ")) { + resp = g_strndup(line.str+9, line.len-9-2); + rc = g_ascii_strtoull(resp, NULL, 10); + } else { + g_warning("unexpected HTTP response: '%s'", line.str); + goto err; + } + + /* state=1 ... read additional response headers + * (ignored for now) */ + state=1; + } + + if (line.len==2) /* only the \r\n terminators */ + break; + } + + if (rc!=200) + g_warning("unexpected HTTP response code: %s", resp); + + g_free(resp); + g_free(line.str); + return rc; + +err: + g_free(resp); + g_free(line.str); + return -1; +} + +static GIOChannel * +network_proxy_http_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, + char const *address, int port) +{ + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + GIOChannel *ch; + GIOFlags old_flags; + GError *err = NULL; + gchar const *line_term; + gint line_term_sz; + + if (hint_ip) + ch = net_connect_ip(hint_ip, self->proxy.port, NULL); + else + ch = net_connect(self->proxy.host, self->proxy.port, NULL); + + if (!ch) + return NULL; + + /* set \r\n line delims */ + line_term = g_io_channel_get_line_term(ch, &line_term_sz); + g_io_channel_set_line_term(ch, "\r\n", 2); + + /* set to non-blocking */ + old_flags = g_io_channel_get_flags(ch); + if (g_io_channel_set_flags(ch, old_flags & ~G_IO_FLAG_NONBLOCK, &err)!=G_IO_STATUS_NORMAL) + goto err; + + if (!send_connect(self, ch, address, port) || + read_response(self, ch)!=200) + goto err; + + if (g_io_channel_set_flags(ch, old_flags, &err)!=G_IO_STATUS_NORMAL) + goto err; + + g_io_channel_set_line_term(ch, line_term, line_term_sz); + return ch; +err: + if (err) { + g_warning("something went wrong while preparing HTTP proxy request: %s", + err->message); + g_error_free(err); + } + + net_disconnect(ch); + return NULL; + +} + + +struct network_proxy * +_network_proxy_http_create(void) +{ + struct _network_proxy_http *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_create(&res->proxy); + res->password = g_strdup(settings_get_str("proxy_password")); + + res->proxy.destroy = network_proxy_http_destroy; + res->proxy.connect = network_proxy_http_connect; + res->proxy.clone = network_proxy_http_clone; + + return &res->proxy; +} diff --git a/src/core/network-proxy-http.h b/src/core/network-proxy-http.h new file mode 100644 index 00000000..67eb208d --- /dev/null +++ b/src/core/network-proxy-http.h @@ -0,0 +1,29 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef H_IRSSI_SRC_CORE_PROXY_HTTP_H +#define H_IRSSI_SRC_CORE_PROXY_HTTP_H + +#include "network-proxy.h" + +struct _network_proxy_http { + struct network_proxy proxy; + char const *password; +}; + +struct network_proxy * _network_proxy_http_create(void); + +#endif /* H_IRSSI_SRC_CORE_PROXY_HTTP_H */ From 7ef54cc29f23cc7723f62b36735093e4e3f2a2a7 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 11:21:25 +0100 Subject: [PATCH 03/15] PROXY/SOCKS5: added methods for SOCKS5 proxies From original patch by Enrico Scholz 26 Feb 2008 This patch adds code for connecting through SOCKS5 proxies. It was primarily written for use with TOR, so there are some open issues: * it only allows to make proxy requests with full hostnames; ipv4/ipv6 is not supported * GSSAPI authentication (which is mentioned as mandatory in RFC 1928) is not implemented * plaintext authentication is untested To use it * set 'proxy_type' to 'socks5' --- src/core/network-proxy-socks5.c | 338 ++++++++++++++++++++++++++++++++ src/core/network-proxy-socks5.h | 31 +++ 2 files changed, 369 insertions(+) create mode 100644 src/core/network-proxy-socks5.c create mode 100644 src/core/network-proxy-socks5.h diff --git a/src/core/network-proxy-socks5.c b/src/core/network-proxy-socks5.c new file mode 100644 index 00000000..64a8f510 --- /dev/null +++ b/src/core/network-proxy-socks5.c @@ -0,0 +1,338 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "module.h" +#include "network-proxy-socks5.h" + +#include +#include + +#include "network.h" +#include "network-proxy-priv.h" + +/* RFC 1928 */ +struct client_greeting +{ + uint8_t ver; + uint8_t nmethods; + uint8_t methods[]; +} __attribute__((__packed__)); + +struct server_greeting +{ + uint8_t ver; + uint8_t method; +} __attribute__((__packed__)); + +struct server_response_plain +{ + uint8_t ver; + uint8_t status; +} __attribute__((__packed__)); + +struct client_request +{ + uint8_t ver; + uint8_t cmd; + uint8_t rsv; + uint8_t atyp; + uint8_t dst[]; +} __attribute__((__packed__)); + +struct server_response +{ + uint8_t ver; + uint8_t rep; + uint8_t res; + uint8_t atyp; + uint8_t bnd[]; +} __attribute__((__packed__)); + +static void +network_proxy_socks5_destroy(struct network_proxy *proxy) +{ + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + + g_free((void *)self->password); + g_free((void *)self->username); + _network_proxy_destroy(proxy); + g_free(self); +} + +static struct network_proxy * +network_proxy_socks5_clone(struct network_proxy const *proxy) +{ + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct _network_proxy_socks5 *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_clone(&res->proxy, &self->proxy); + res->username = g_strdup(self->username); + res->password = g_strdup(self->password); + return &res->proxy; +} + +static bool +socks5_connect_unauthorized(GIOChannel *ch) +{ + /* nothing to do here */ + (void)ch; + return true; +} + +/* TODO: test this method! */ +static bool +socks5_connect_plain(struct _network_proxy_socks5 const *proxy, GIOChannel *ch) +{ + uint8_t ver = 0x01; + uint8_t ulen = strlen(proxy->username); + uint8_t plen = proxy->password ? strlen(proxy->password) : 0; + struct server_response_plain resp; + + if (ulen==0 || + !_network_proxy_send_all(ch, &ver, sizeof ver) || + !_network_proxy_send_all(ch, &ulen, sizeof ulen) || + !_network_proxy_send_all(ch, proxy->username, ulen) || + !_network_proxy_send_all(ch, &plen, sizeof plen) || + (plen>0 && !_network_proxy_send_all(ch, proxy->password, plen)) || + !_network_proxy_flush(ch) || + !_network_proxy_recv_all(ch, &resp, sizeof resp)) + return false; + + if (resp.ver!=0x01) { + g_warning("unexpected plaintext response version %#04x", resp.ver); + return false; + } + + if (resp.status!=0x00) { + g_warning("socks5 authentication error (%#04x)", resp.status); + return false; + } + + return true; +} + +static bool +socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, + char const *address, uint16_t port) +{ + bool rc; + + struct server_greeting s_greeting; + struct server_response s_response; + + + /* Phase 1: exchange greeting */ + { + struct client_greeting c_greeting = { + .ver = 0x05, + .nmethods = proxy->username && proxy->username[0] ? 2 : 1 + }; + /* HACK: order is important because it depends upon + * c_greeting.nmethods */ + char const methods[] = { + 0x00, /* no authentication */ + 0x02 /* username/password */ + }; + if (!_network_proxy_send_all(ch, &c_greeting, sizeof c_greeting) || + !_network_proxy_send_all(ch, methods, c_greeting.nmethods) || + !_network_proxy_flush(ch) || + !_network_proxy_recv_all(ch, &s_greeting, sizeof s_greeting)) + goto err; + + if (s_greeting.ver!=5) { + g_warning("version mismatch during initial socks5 greeting; got version %#04x", + s_greeting.ver); + goto err; + } + } + + /* Phase 2: authentication */ + { + switch (s_greeting.method) { + case 0x00: rc = socks5_connect_unauthorized(ch); break; + case 0x02: rc = socks5_connect_plain(proxy, ch); break; + default: + g_warning("unsupported authentication method %#04x", s_greeting.method); + rc = false; + } + + if (!rc) + goto err; + } + + /* Phase 3: connection request */ + { + struct client_request c_request = { + .ver = 0x05, + .cmd = 0x01, /* CONNECT */ + .atyp = 0x03, /* domain name */ + }; + uint8_t address_len = strlen(address); + uint16_t dst_port = htons(port); + uint16_t bnd_port; + char bnd_address[257]; + + if (!_network_proxy_send_all(ch, &c_request, sizeof c_request) || + !_network_proxy_send_all(ch, &address_len, sizeof address_len) || + !_network_proxy_send_all(ch, address, address_len) || + !_network_proxy_send_all(ch, &dst_port, sizeof dst_port) || + !_network_proxy_flush(ch) || + !_network_proxy_recv_all(ch, &s_response, sizeof s_response)) + goto err; + + if (s_response.ver != 0x05) { + g_warning("version mismatch in socks5 response; got version %#04x", + s_response.ver); + goto err; + } + + rc = false; + switch (s_response.rep) { + case 0x00: rc = true; break; /* succeeded */ + case 0x01: g_warning("SOCKS5: general SOCKS server failure"); break; + case 0x02: g_warning("SOCKS5: connection not allowed by ruleset"); break; + case 0x03: g_warning("SOCKS5: Network unreachable"); break; + case 0x04: g_warning("SOCKS5: Host unreachable"); break; + case 0x05: g_warning("SOCKS5: Connection refused"); break; + case 0x06: g_warning("SOCKS5: TTL expired"); break; + case 0x07: g_warning("SOCKS5: Command not supported"); break; + case 0x08: g_warning("SOCKS5: Address type not supported"); break; + default: g_warning("SOCKS5: unknown error %#04x", s_response.rep); break; + } + + if (!rc) + goto err; + + switch(s_response.atyp) { + case 0x01: { + struct in_addr ip; + if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || + !inet_ntop(AF_INET, &ip, bnd_address, sizeof bnd_address)) + rc = false; + break; + } + + case 0x04: { + struct in6_addr ip; + if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || + !inet_ntop(AF_INET6, &ip, bnd_address, sizeof bnd_address)) + rc = false; + break; + } + + case 0x03: { + uint8_t tmp; + if (!_network_proxy_recv_all(ch, &tmp, sizeof tmp) || + tmp==0 || + !_network_proxy_recv_all(ch, &bnd_address, tmp)) + rc = false; + else + bnd_address[tmp] = '\0'; + } + + default: + g_warning("SOCKS5: unsupported address family in response: %#04x", + s_response.atyp); + rc = false; + } + + if (!rc || + !_network_proxy_recv_all(ch, &bnd_port, sizeof bnd_port)) + goto err; + + bnd_port = ntohs(bnd_port); + g_debug("SOCKS5: bound to %s:%u", bnd_address, bnd_port); + } + + return true; + +err: + g_warning("connecting through socks5 proxy failed"); + return false; +} + + +static GIOChannel * +network_proxy_socks5_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, + char const *address, int port) +{ + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + GIOChannel *ch; + + GIOFlags old_flags; + gchar const *old_enc; + gboolean old_buf; + GError *err = NULL; + + if (hint_ip) + ch = net_connect_ip(hint_ip, self->proxy.port, NULL); + else + ch = net_connect(self->proxy.host, self->proxy.port, NULL); + + if (!ch) + return NULL; + + old_enc = g_io_channel_get_encoding(ch); + old_flags = g_io_channel_get_flags(ch); + old_buf = g_io_channel_get_buffered(ch); + + if (g_io_channel_set_encoding(ch, NULL, &err)!=G_IO_STATUS_NORMAL || + g_io_channel_set_flags(ch, old_flags & ~G_IO_FLAG_NONBLOCK, &err)!=G_IO_STATUS_NORMAL) + goto err; + + g_io_channel_set_buffered(ch, false); + + if (!socks5_connect(self, ch, address, port)) + goto err; + + g_io_channel_set_buffered(ch, old_buf); + + if (g_io_channel_set_flags(ch, old_flags, &err) !=G_IO_STATUS_NORMAL || + g_io_channel_set_encoding(ch, old_enc, &err)!=G_IO_STATUS_NORMAL) + goto err; + + return ch; + +err: + if (err) { + g_warning("something went wrong while preparing SOCKS5 proxy request: %s", + err->message); + g_error_free(err); + } + + net_disconnect(ch); + return NULL; +} + +struct network_proxy * +_network_proxy_socks5_create(void) +{ + struct _network_proxy_socks5 *res; + + res = g_malloc0(sizeof *res); + + _network_proxy_create(&res->proxy); + res->username = g_strdup(settings_get_str("proxy_username")); + res->password = g_strdup(settings_get_str("proxy_password")); + + res->proxy.destroy = network_proxy_socks5_destroy; + res->proxy.connect = network_proxy_socks5_connect; + res->proxy.clone = network_proxy_socks5_clone; + + return &res->proxy; +} diff --git a/src/core/network-proxy-socks5.h b/src/core/network-proxy-socks5.h new file mode 100644 index 00000000..963bad3d --- /dev/null +++ b/src/core/network-proxy-socks5.h @@ -0,0 +1,31 @@ +/* --*- c -*-- + * Copyright (C) 2008 Enrico Scholz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 and/or 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef H_IRSSI_SRC_CORE_PROXY_SOCKS5_H +#define H_IRSSI_SRC_CORE_PROXY_SOCKS5_H + +#include "network-proxy.h" + +struct _network_proxy_socks5 { + struct network_proxy proxy; + + char const *username; + char const *password; +}; + +struct network_proxy * _network_proxy_socks5_create(void); + +#endif /* H_IRSSI_SRC_CORE_PROXY_SOCKS5_H */ From 3bc24696a437d305be03e7771b5e1b6e8f9c50b3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 11:35:53 +0100 Subject: [PATCH 04/15] PROXY: merge proxy methods into buildsystem From the original patch by Enrico Scholz 26 Feb 2008 This patch adds the code and rules to build the various proxy methods. --- src/core/Makefile.am | 6 ++++++ src/core/network-proxy.c | 43 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/core/network-proxy.c diff --git a/src/core/Makefile.am b/src/core/Makefile.am index ce4b4bb6..c664739b 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -33,6 +33,12 @@ libcore_a_SOURCES = \ network-openssl.c \ network-proxy.c \ network-proxy.h \ + network-proxy-simple.c \ + network-proxy-simple.h \ + network-proxy-http.c \ + network-proxy-http.h \ + network-proxy-socks5.c \ + network-proxy-socks5.h \ network-proxy-priv.h \ nicklist.c \ nickmatch-cache.c \ diff --git a/src/core/network-proxy.c b/src/core/network-proxy.c new file mode 100644 index 00000000..f056da6b --- /dev/null +++ b/src/core/network-proxy.c @@ -0,0 +1,43 @@ +/* + network-proxy.c : irssi + + Copyright (C) 2008 Enrico Scholz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 and/or 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "module.h" + +#include "network-proxy.h" +#include +#include "network-proxy-simple.h" +#include "network-proxy-http.h" +#include "network-proxy-socks5.h" + +struct network_proxy *network_proxy_create(const char *type) +{ + if (type==NULL) + return NULL; + + if (strcmp(type, "simple")==0 || type[0]=='\0') + return network_proxy_simple_create(); + + if (strcmp(type, "http")==0) + return network_proxy_http_create(); + + if (strcmp(type, "socks5")==0) + return network_proxy_socks5_create(); + + g_error("unsupported proxy type '%s'", type); + return NULL; +} From bade9e3d9e7d95b51da578eb8ed88f0789baff06 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 11:41:05 +0100 Subject: [PATCH 05/15] http-proxy: fixed bad return value From the original patch by Enrico Scholz 7 Apr 2010 --- src/core/network-proxy-http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c index 4e17d5c1..07966b3f 100644 --- a/src/core/network-proxy-http.c +++ b/src/core/network-proxy-http.c @@ -63,7 +63,7 @@ send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, char const *addr !_network_proxy_send_all(ch, port_str, -1) || !_network_proxy_send_all(ch, " HTTP/1.0\r\n\r\n", -1) || !_network_proxy_flush(ch)) - return -1; + return false; return true; } From 646d17d9d47ea681b439ebce425e2fb067cba606 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 11:47:57 +0100 Subject: [PATCH 06/15] Porting some stuff to modern git version From the original patch by hawken93 3 Oct 2014 --- src/core/network-openssl.c | 3 ++- src/core/network.h | 2 +- src/core/servers.c | 5 +---- src/irc/core/irc-servers.c | 5 +++++ src/irc/core/irc-servers.h | 2 ++ 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 3b0f3c18..fc729dde 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -565,7 +565,8 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ return gchan; } -GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify) +GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, + IPADDR *ip, IPADDR *my_ip, SERVER_REC *server) { GIOChannel *handle, *ssl_handle; diff --git a/src/core/network.h b/src/core/network.h index c88e9bc0..a7804b1a 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -41,7 +41,7 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip); -GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify); +GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ diff --git a/src/core/servers.c b/src/core/servers.c index c8183675..dbc8ae49 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -225,10 +225,7 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip, net_connect_proxy_ssl(server->connrec->proxy, server->connrec->address, port, ip, own_ip, - server->connrec->ssl_cert, - server->connrec->ssl_pkey, - server->connrec->ssl_cafile, - server->connrec->ssl_capath, server->connrec->ssl_verify) : + server->connrec) : net_connect_proxy(server->connrec->proxy, server->connrec->address, port, ip, own_ip); diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 5bac1445..284f2b6e 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -341,6 +341,11 @@ void irc_server_connect(SERVER_REC *server) } } +void irc_send_cmd_now_wrapper(void *server, const char *cmd) +{ + return irc_send_cmd_now((IRC_SERVER_REC *)server, cmd); +} + /* Returns TRUE if `command' is sent to `target' */ static int command_has_target(const char *cmd, const char *target) { diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h index 41c4b9c2..7da1ab39 100644 --- a/src/irc/core/irc-servers.h +++ b/src/irc/core/irc-servers.h @@ -136,6 +136,8 @@ void irc_server_send_away(IRC_SERVER_REC *server, const char *reason); void irc_server_send_data(IRC_SERVER_REC *server, const char *data, int len); void irc_server_init_isupport(IRC_SERVER_REC *server); +void irc_send_cmd_now_wrapper(void *server, const char *cmd); + void irc_servers_start_cmd_timeout(void); void irc_servers_init(void); From 4b0610e317ee95fce8642d3cb8d7e94415cc05b7 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 11:51:28 +0100 Subject: [PATCH 07/15] no patching unrelated stuff From original patch by hawken93 3 Oct 2014 --- src/core/network.c | 2 +- src/core/network.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/network.c b/src/core/network.c index 9f0aee01..cb1a966e 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -146,7 +146,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) } /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip) +GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; diff --git a/src/core/network.h b/src/core/network.h index a7804b1a..513a367f 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -40,11 +40,11 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ -GIOChannel *net_connect_ip(IPADDR const *ip, int port, IPADDR *my_ip); GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ +GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip); /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path); From 4a8a6cfcbfa896aa91d0539c9b9cdf8097891de3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 12:21:37 +0100 Subject: [PATCH 08/15] Change coding style Based on original patch by hawken93 3 Oct 2014 --- TODO | 5 ++ src/core/network-openssl.c | 2 +- src/core/network-proxy-http.c | 66 +++++++-------- src/core/network-proxy-http.h | 6 +- src/core/network-proxy-priv.h | 46 +++++------ src/core/network-proxy-simple.c | 128 +++++++++++++++++++++++++++++ src/core/network-proxy-simple.h | 14 ++++ src/core/network-proxy-socks5.c | 141 +++++++++++++++----------------- src/core/network-proxy-socks5.h | 8 +- src/core/network-proxy.h | 28 +++---- src/core/network.c | 4 +- src/core/network.h | 10 ++- src/core/server-connect-rec.h | 2 +- src/irc/core/irc-servers.c | 10 +-- 14 files changed, 301 insertions(+), 169 deletions(-) create mode 100644 src/core/network-proxy-simple.c create mode 100644 src/core/network-proxy-simple.h diff --git a/TODO b/TODO index 7d28a3f0..832c7e05 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,8 @@ + - New proxy code crashes if an invalid proxy_type setting is used + - Remove old socks code + - Lots of warnings at least when using socks5 + - Clean up coding style + 19:36 [IRCNet] [muzzy] more bugs in irssi, apparently the new version: foo splits out, bar joins, bar changes his nick to foo, foo splits again -> Glib warning "is already in split list (how?)" .. :) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index fc729dde..680feffd 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -565,7 +565,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ return gchan; } -GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, +GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server) { GIOChannel *handle, *ssl_handle; diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c index 07966b3f..fa27c7c1 100644 --- a/src/core/network-proxy-http.c +++ b/src/core/network-proxy-http.c @@ -25,10 +25,9 @@ #include "network.h" #include "network-proxy-priv.h" -static void -network_proxy_http_destroy(struct network_proxy *proxy) +static void network_proxy_http_destroy(struct network_proxy *proxy) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); g_free((void *)self->password); _network_proxy_destroy(proxy); @@ -39,8 +38,8 @@ network_proxy_http_destroy(struct network_proxy *proxy) static struct network_proxy * network_proxy_http_clone(struct network_proxy const *proxy) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); - struct _network_proxy_http *res; + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct _network_proxy_http *res; res = g_malloc0(sizeof *res); @@ -49,18 +48,18 @@ network_proxy_http_clone(struct network_proxy const *proxy) return &res->proxy; } -static bool -send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, char const *address, uint16_t port) +static bool send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, + char const *address, uint16_t port) { - char port_str[6]; + char port_str[6]; (void)proxy; sprintf(port_str, "%u", port); if (!_network_proxy_send_all(ch, "CONNECT ", -1) || - !_network_proxy_send_all(ch, address, -1) || - !_network_proxy_send_all(ch, ":", -1) || - !_network_proxy_send_all(ch, port_str, -1) || + !_network_proxy_send_all(ch, address, -1) || + !_network_proxy_send_all(ch, ":", -1) || + !_network_proxy_send_all(ch, port_str, -1) || !_network_proxy_send_all(ch, " HTTP/1.0\r\n\r\n", -1) || !_network_proxy_flush(ch)) return false; @@ -68,16 +67,15 @@ send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, char const *addr return true; } -static int -read_response(struct _network_proxy_http *proxy, GIOChannel *ch) +static int read_response(struct _network_proxy_http *proxy, GIOChannel *ch) { - GIOStatus status; - GString line = { .str = NULL }; - gsize term_pos; - GError *err = NULL; - int state = 0; - int rc = 0; - gchar *resp = NULL; + GIOStatus status; + GString line = { .str = NULL }; + gsize term_pos; + GError *err = NULL; + int state = 0; + int rc = 0; + gchar *resp = NULL; (void)proxy; for (;;) { @@ -97,7 +95,7 @@ read_response(struct _network_proxy_http *proxy, GIOChannel *ch) if (state==0) { if (g_str_has_prefix(line.str, "HTTP/1.0 ")) { resp = g_strndup(line.str+9, line.len-9-2); - rc = g_ascii_strtoull(resp, NULL, 10); + rc = g_ascii_strtoull(resp, NULL, 10); } else { g_warning("unexpected HTTP response: '%s'", line.str); goto err; @@ -125,16 +123,15 @@ err: return -1; } -static GIOChannel * -network_proxy_http_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, - char const *address, int port) +static GIOChannel *network_proxy_http_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, + char const *address, int port) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); - GIOChannel *ch; - GIOFlags old_flags; - GError *err = NULL; - gchar const *line_term; - gint line_term_sz; + struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + GIOChannel *ch; + GIOFlags old_flags; + GError *err = NULL; + gchar const *line_term; + gint line_term_sz; if (hint_ip) ch = net_connect_ip(hint_ip, self->proxy.port, NULL); @@ -175,19 +172,18 @@ err: } -struct network_proxy * -_network_proxy_http_create(void) +struct network_proxy *_network_proxy_http_create(void) { - struct _network_proxy_http *res; + struct _network_proxy_http *res; res = g_malloc0(sizeof *res); _network_proxy_create(&res->proxy); - res->password = g_strdup(settings_get_str("proxy_password")); + res->password = g_strdup(settings_get_str("proxy_password")); res->proxy.destroy = network_proxy_http_destroy; res->proxy.connect = network_proxy_http_connect; - res->proxy.clone = network_proxy_http_clone; + res->proxy.clone = network_proxy_http_clone; return &res->proxy; } diff --git a/src/core/network-proxy-http.h b/src/core/network-proxy-http.h index 67eb208d..b47bfc5e 100644 --- a/src/core/network-proxy-http.h +++ b/src/core/network-proxy-http.h @@ -20,10 +20,10 @@ #include "network-proxy.h" struct _network_proxy_http { - struct network_proxy proxy; - char const *password; + struct network_proxy proxy; + char const *password; }; -struct network_proxy * _network_proxy_http_create(void); +struct network_proxy *_network_proxy_http_create(void); #endif /* H_IRSSI_SRC_CORE_PROXY_HTTP_H */ diff --git a/src/core/network-proxy-priv.h b/src/core/network-proxy-priv.h index e4d5e22b..8e5fcf95 100644 --- a/src/core/network-proxy-priv.h +++ b/src/core/network-proxy-priv.h @@ -26,38 +26,34 @@ (type *)( (char *)__mptr - offsetof(type,member) );}) -inline static void -_network_proxy_create(struct network_proxy *dst) +inline static void _network_proxy_create(struct network_proxy *dst) { - dst->port = settings_get_int("proxy_port"); - dst->host = g_strdup(settings_get_str("proxy_address")); + dst->port = settings_get_int("proxy_port"); + dst->host = g_strdup(settings_get_str("proxy_address")); } -inline static void -_network_proxy_clone(struct network_proxy *dst, struct network_proxy const *src) +inline static void _network_proxy_clone(struct network_proxy *dst, struct network_proxy const *src) { - dst->host = g_strdup(src->host); - dst->port = src->port; + dst->host = g_strdup(src->host); + dst->port = src->port; dst->destroy = src->destroy; dst->connect = src->connect; - dst->clone = src->clone; + dst->clone = src->clone; } -inline static void -_network_proxy_destroy(struct network_proxy *proxy) +inline static void _network_proxy_destroy(struct network_proxy *proxy) { g_free((void *)proxy->host); } -inline static bool -_network_proxy_send_all(GIOChannel *ch, void const *buf, ssize_t len) +inline static bool _network_proxy_send_all(GIOChannel *ch, void const *buf, ssize_t len) { - GError *err = NULL; - gsize written; - GIOStatus status; + GError *err = NULL; + gsize written; + GIOStatus status; while ((status=g_io_channel_write_chars(ch, buf, len, &written, &err))==G_IO_STATUS_AGAIN) @@ -74,15 +70,14 @@ _network_proxy_send_all(GIOChannel *ch, void const *buf, ssize_t len) return false; } -inline static bool -_network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t len) +inline static bool _network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t len) { - GError *err = NULL; - gchar *buf = buf_v; + GError *err = NULL; + gchar *buf = buf_v; while (len>0) { - GIOStatus status; - gsize l; + GIOStatus status; + gsize l; status = g_io_channel_read_chars(ch, buf, len, &l, &err); if (status==G_IO_STATUS_AGAIN) @@ -105,11 +100,10 @@ _network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t len) return false; } -inline static bool -_network_proxy_flush(GIOChannel *ch) +inline static bool _network_proxy_flush(GIOChannel *ch) { - GError *err = NULL; - GIOStatus status; + GError *err = NULL; + GIOStatus status; while ((status=g_io_channel_flush(ch, &err))==G_IO_STATUS_AGAIN) continue; diff --git a/src/core/network-proxy-simple.c b/src/core/network-proxy-simple.c new file mode 100644 index 00000000..980215b5 --- /dev/null +++ b/src/core/network-proxy-simple.c @@ -0,0 +1,128 @@ +/* + network-proxy-simple.c : irssi + + Copyright (C) 2008 Enrico Scholz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 and/or 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "module.h" +#include "network-proxy-simple.h" + +#include "network-proxy-priv.h" +#include "network.h" + +static void network_proxy_simple_destroy(struct network_proxy *proxy) +{ + struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata; + + g_free(self->password); + g_free(self->string_after); + g_free(self->string); + + g_free(self); + + _network_proxy_destroy(proxy); + + // We are responsible for the whole proxy struct + g_free(proxy); +} + +static struct network_proxy *network_proxy_simple_clone(const struct network_proxy *proxy) +{ + struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata; + struct network_proxy *res; + struct network_proxy_simple *newself; + + // First make and set the parent struct + res = g_malloc0(sizeof(struct network_proxy)); + _network_proxy_clone(res, proxy); + + // Then allocate and set the private data + newself = g_malloc0(sizeof(struct network_proxy_simple)); + res->privdata = (void *)newself; + + newself->string = g_strdup(self->string); + newself->string_after = g_strdup(self->string_after); + newself->password = g_strdup(self->password); + + return res; +} + +static GIOChannel *network_proxy_simple_connect(const struct network_proxy *proxy, + const IPADDR *hint_ip, char const *address, int port) +{ + if (hint_ip) + return net_connect_ip(hint_ip, proxy->port, NULL); + else + return net_connect(proxy->host, proxy->port, NULL); +} + +static void network_proxy_simple_send_string(const struct network_proxy *proxy, + const struct network_proxy_send_string_info *info) +{ + struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata; + char *cmd; + + if (self->password && self->password[0]) { + cmd = g_strdup_printf("PASS %s", self->password); + info->func(info->obj, cmd); + g_free(cmd); + } + + if (self->string && self->string[0]) { + cmd = g_strdup_printf(self->string, info->host, info->port); + info->func(info->obj, cmd); + g_free(cmd); + } +} + +static void network_proxy_simple_send_string_after(const struct network_proxy *proxy, + const struct network_proxy_send_string_info *info) +{ + struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata; + char *cmd; + + if (self->string_after && self->string_after[0]) { + cmd = g_strdup_printf(self->string_after, info->host, info->port); + info->func(info->obj, cmd); + g_free(cmd); + } +} + +struct network_proxy *network_proxy_simple_create(void) +{ + struct network_proxy *proxy; + struct network_proxy_simple *self; + + proxy = g_malloc0(sizeof(struct network_proxy)); + + // assume it could reset every variable to a known state + _network_proxy_create(proxy); + + self = g_malloc0(sizeof(struct network_proxy_simple)); + proxy->privdata = (void *)self; + + self->string = g_strdup(settings_get_str("proxy_string")); + self->string_after = g_strdup(settings_get_str("proxy_string_after")); + self->password = g_strdup(settings_get_str("proxy_password")); + + proxy->destroy = network_proxy_simple_destroy; + proxy->connect = network_proxy_simple_connect; + proxy->clone = network_proxy_simple_clone; + + proxy->send_string = network_proxy_simple_send_string; + proxy->send_string_after = network_proxy_simple_send_string_after; + + return proxy; +} diff --git a/src/core/network-proxy-simple.h b/src/core/network-proxy-simple.h new file mode 100644 index 00000000..010d8e4a --- /dev/null +++ b/src/core/network-proxy-simple.h @@ -0,0 +1,14 @@ +#ifndef H_IRSSI_SRC_CORE_PROXY_SIMPLE_H +#define H_IRSSI_SRC_CORE_PROXY_SIMPLE_H + +#include "network-proxy.h" + +struct network_proxy_simple { + char *string_after; + char *string; + char *password; +}; + +struct network_proxy *network_proxy_simple_create(void); + +#endif diff --git a/src/core/network-proxy-socks5.c b/src/core/network-proxy-socks5.c index 64a8f510..69214b10 100644 --- a/src/core/network-proxy-socks5.c +++ b/src/core/network-proxy-socks5.c @@ -26,45 +26,44 @@ /* RFC 1928 */ struct client_greeting { - uint8_t ver; - uint8_t nmethods; - uint8_t methods[]; + uint8_t ver; + uint8_t nmethods; + uint8_t methods[]; } __attribute__((__packed__)); struct server_greeting { - uint8_t ver; - uint8_t method; + uint8_t ver; + uint8_t method; } __attribute__((__packed__)); struct server_response_plain { - uint8_t ver; - uint8_t status; + uint8_t ver; + uint8_t status; } __attribute__((__packed__)); struct client_request { - uint8_t ver; - uint8_t cmd; - uint8_t rsv; - uint8_t atyp; - uint8_t dst[]; + uint8_t ver; + uint8_t cmd; + uint8_t rsv; + uint8_t atyp; + uint8_t dst[]; } __attribute__((__packed__)); struct server_response { - uint8_t ver; - uint8_t rep; - uint8_t res; - uint8_t atyp; - uint8_t bnd[]; + uint8_t ver; + uint8_t rep; + uint8_t res; + uint8_t atyp; + uint8_t bnd[]; } __attribute__((__packed__)); -static void -network_proxy_socks5_destroy(struct network_proxy *proxy) +static void network_proxy_socks5_destroy(struct network_proxy *proxy) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); g_free((void *)self->password); g_free((void *)self->username); @@ -72,11 +71,10 @@ network_proxy_socks5_destroy(struct network_proxy *proxy) g_free(self); } -static struct network_proxy * -network_proxy_socks5_clone(struct network_proxy const *proxy) +static struct network_proxy *network_proxy_socks5_clone(struct network_proxy const *proxy) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); - struct _network_proxy_socks5 *res; + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct _network_proxy_socks5 *res; res = g_malloc0(sizeof *res); @@ -86,8 +84,7 @@ network_proxy_socks5_clone(struct network_proxy const *proxy) return &res->proxy; } -static bool -socks5_connect_unauthorized(GIOChannel *ch) +static bool socks5_connect_unauthorized(GIOChannel *ch) { /* nothing to do here */ (void)ch; @@ -95,12 +92,11 @@ socks5_connect_unauthorized(GIOChannel *ch) } /* TODO: test this method! */ -static bool -socks5_connect_plain(struct _network_proxy_socks5 const *proxy, GIOChannel *ch) +static bool socks5_connect_plain(struct _network_proxy_socks5 const *proxy, GIOChannel *ch) { - uint8_t ver = 0x01; - uint8_t ulen = strlen(proxy->username); - uint8_t plen = proxy->password ? strlen(proxy->password) : 0; + uint8_t ver = 0x01; + uint8_t ulen = strlen(proxy->username); + uint8_t plen = proxy->password ? strlen(proxy->password) : 0; struct server_response_plain resp; if (ulen==0 || @@ -126,30 +122,29 @@ socks5_connect_plain(struct _network_proxy_socks5 const *proxy, GIOChannel *ch) return true; } -static bool -socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, - char const *address, uint16_t port) +static bool socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, + char const *address, uint16_t port) { - bool rc; + bool rc; - struct server_greeting s_greeting; - struct server_response s_response; + struct server_greeting s_greeting; + struct server_response s_response; /* Phase 1: exchange greeting */ { - struct client_greeting c_greeting = { + struct client_greeting c_greeting = { .ver = 0x05, .nmethods = proxy->username && proxy->username[0] ? 2 : 1 }; /* HACK: order is important because it depends upon * c_greeting.nmethods */ - char const methods[] = { - 0x00, /* no authentication */ - 0x02 /* username/password */ + char const methods[] = { + 0x00, /* no authentication */ + 0x02 /* username/password */ }; if (!_network_proxy_send_all(ch, &c_greeting, sizeof c_greeting) || - !_network_proxy_send_all(ch, methods, c_greeting.nmethods) || + !_network_proxy_send_all(ch, methods, c_greeting.nmethods) || !_network_proxy_flush(ch) || !_network_proxy_recv_all(ch, &s_greeting, sizeof s_greeting)) goto err; @@ -178,21 +173,21 @@ socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, /* Phase 3: connection request */ { struct client_request c_request = { - .ver = 0x05, - .cmd = 0x01, /* CONNECT */ - .atyp = 0x03, /* domain name */ + .ver = 0x05, + .cmd = 0x01, /* CONNECT */ + .atyp = 0x03, /* domain name */ }; - uint8_t address_len = strlen(address); - uint16_t dst_port = htons(port); - uint16_t bnd_port; - char bnd_address[257]; + uint8_t address_len = strlen(address); + uint16_t dst_port = htons(port); + uint16_t bnd_port; + char bnd_address[257]; - if (!_network_proxy_send_all(ch, &c_request, sizeof c_request) || + if (!_network_proxy_send_all(ch, &c_request, sizeof c_request) || !_network_proxy_send_all(ch, &address_len, sizeof address_len) || - !_network_proxy_send_all(ch, address, address_len) || - !_network_proxy_send_all(ch, &dst_port, sizeof dst_port) || + !_network_proxy_send_all(ch, address, address_len) || + !_network_proxy_send_all(ch, &dst_port, sizeof dst_port) || !_network_proxy_flush(ch) || - !_network_proxy_recv_all(ch, &s_response, sizeof s_response)) + !_network_proxy_recv_all(ch, &s_response, sizeof s_response)) goto err; if (s_response.ver != 0x05) { @@ -212,7 +207,7 @@ socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, case 0x06: g_warning("SOCKS5: TTL expired"); break; case 0x07: g_warning("SOCKS5: Command not supported"); break; case 0x08: g_warning("SOCKS5: Address type not supported"); break; - default: g_warning("SOCKS5: unknown error %#04x", s_response.rep); break; + default: g_warning("SOCKS5: unknown error %#04x", s_response.rep); break; } if (!rc) @@ -221,7 +216,7 @@ socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, switch(s_response.atyp) { case 0x01: { struct in_addr ip; - if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || + if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || !inet_ntop(AF_INET, &ip, bnd_address, sizeof bnd_address)) rc = false; break; @@ -229,14 +224,14 @@ socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, case 0x04: { struct in6_addr ip; - if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || + if (!_network_proxy_recv_all(ch, &ip, sizeof ip) || !inet_ntop(AF_INET6, &ip, bnd_address, sizeof bnd_address)) rc = false; break; } case 0x03: { - uint8_t tmp; + uint8_t tmp; if (!_network_proxy_recv_all(ch, &tmp, sizeof tmp) || tmp==0 || !_network_proxy_recv_all(ch, &bnd_address, tmp)) @@ -267,17 +262,16 @@ err: } -static GIOChannel * -network_proxy_socks5_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, - char const *address, int port) +static GIOChannel *network_proxy_socks5_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, + char const *address, int port) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); - GIOChannel *ch; + struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + GIOChannel *ch; - GIOFlags old_flags; - gchar const *old_enc; - gboolean old_buf; - GError *err = NULL; + GIOFlags old_flags; + gchar const *old_enc; + gboolean old_buf; + GError *err = NULL; if (hint_ip) ch = net_connect_ip(hint_ip, self->proxy.port, NULL); @@ -287,9 +281,9 @@ network_proxy_socks5_connect(struct network_proxy const *proxy, IPADDR const *hi if (!ch) return NULL; - old_enc = g_io_channel_get_encoding(ch); + old_enc = g_io_channel_get_encoding(ch); old_flags = g_io_channel_get_flags(ch); - old_buf = g_io_channel_get_buffered(ch); + old_buf = g_io_channel_get_buffered(ch); if (g_io_channel_set_encoding(ch, NULL, &err)!=G_IO_STATUS_NORMAL || g_io_channel_set_flags(ch, old_flags & ~G_IO_FLAG_NONBLOCK, &err)!=G_IO_STATUS_NORMAL) @@ -319,20 +313,19 @@ err: return NULL; } -struct network_proxy * -_network_proxy_socks5_create(void) +struct network_proxy *_network_proxy_socks5_create(void) { - struct _network_proxy_socks5 *res; + struct _network_proxy_socks5 *res; res = g_malloc0(sizeof *res); _network_proxy_create(&res->proxy); - res->username = g_strdup(settings_get_str("proxy_username")); - res->password = g_strdup(settings_get_str("proxy_password")); + res->username = g_strdup(settings_get_str("proxy_username")); + res->password = g_strdup(settings_get_str("proxy_password")); res->proxy.destroy = network_proxy_socks5_destroy; res->proxy.connect = network_proxy_socks5_connect; - res->proxy.clone = network_proxy_socks5_clone; + res->proxy.clone = network_proxy_socks5_clone; return &res->proxy; } diff --git a/src/core/network-proxy-socks5.h b/src/core/network-proxy-socks5.h index 963bad3d..c1e7e22c 100644 --- a/src/core/network-proxy-socks5.h +++ b/src/core/network-proxy-socks5.h @@ -20,12 +20,12 @@ #include "network-proxy.h" struct _network_proxy_socks5 { - struct network_proxy proxy; + struct network_proxy proxy; - char const *username; - char const *password; + char const *username; + char const *password; }; -struct network_proxy * _network_proxy_socks5_create(void); +struct network_proxy *_network_proxy_socks5_create(void); #endif /* H_IRSSI_SRC_CORE_PROXY_SOCKS5_H */ diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h index 15ff33a0..89b195bc 100644 --- a/src/core/network-proxy.h +++ b/src/core/network-proxy.h @@ -24,20 +24,20 @@ * class */ struct network_proxy_send_string_info { - char const *host; /* hostname of the IRC server */ - uint16_t port; /* portnumber of the IRC server */ + char const *host; /* hostname of the IRC server */ + uint16_t port; /* portnumber of the IRC server */ /* function which is used to send string; usually irc_send_cmd_now() */ - void (*func)(void *obj, char const *); + void (*func)(void *obj, char const *); /* object for func */ - void *obj; + void *obj; }; struct network_proxy { /* destroys the network_proxy structure which must not be used anymore * after; this memberfunction is mandatory */ - void (*destroy)(struct network_proxy *); + void (*destroy)(struct network_proxy *); /* connects through the proxy; this memberfunction is mandatory * @@ -46,36 +46,36 @@ struct network_proxy { * \arg address the hostname where proxy shall connect to * \arg port port address where proxy shall connect to */ - GIOChannel * (*connect)(struct network_proxy const *, IPADDR const *hint_ip, + GIOChannel *(*connect)(struct network_proxy const *, IPADDR const *hint_ip, char const *address, int port); /* clones the given network_proxy object; this memberfunction is * mandatory */ - struct network_proxy * (*clone)(struct network_proxy const *); + struct network_proxy * (*clone)(struct network_proxy const *); /* sends a string after connection has been established but before IRC * authentication begins; this memberfunction is optional */ - void (*send_string)(struct network_proxy const *, - struct network_proxy_send_string_info const *); + void (*send_string)(struct network_proxy const *, + struct network_proxy_send_string_info const *); /* sends a string after connection IRC authentication suceeded; this * memberfunction is optional */ - void (*send_string_after)(struct network_proxy const *, - struct network_proxy_send_string_info const *); + void (*send_string_after)(struct network_proxy const *, + struct network_proxy_send_string_info const *); /* hostname of proxy host */ - char const *host; + char const *host; /* portnumber of proxy */ - int port; + int port; }; /* factory method to create a proxy object based upon value of 'type' */ -struct network_proxy * network_proxy_create(char const *type); +struct network_proxy *network_proxy_create(char const *type); #endif /* H_IRSSI_SRC_CORE_PROXY_H */ diff --git a/src/core/network.c b/src/core/network.c index cb1a966e..32601228 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -198,8 +198,8 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) } /* Connect to socket */ -GIOChannel *net_connect_proxy(struct network_proxy const *proxy, - char const *host, int port, IPADDR *ip, IPADDR *my_ip) +GIOChannel *net_connect_proxy(const struct network_proxy *proxy, + const char *host, int port, IPADDR *ip, IPADDR *my_ip) { if (proxy) return proxy->connect(proxy, ip, host, port); diff --git a/src/core/network.h b/src/core/network.h index 513a367f..ab37cd1d 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -20,8 +20,8 @@ #endif struct _IPADDR { - unsigned short family; - struct in6_addr ip; + unsigned short family; + struct in6_addr ip; }; /* maxmimum string length of IP address */ @@ -40,12 +40,14 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ -GIOChannel *net_connect_proxy_ssl(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); +GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char c*host, int port, + IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); -GIOChannel *net_connect_proxy(struct network_proxy const *proxy, char const *host, int port, IPADDR *ip, IPADDR *my_ip); +GIOChannel *net_connect_proxy(const struct network_proxy *proxy, const char *host, int port, + IPADDR *ip, IPADDR *my_ip); /* Connect to named UNIX socket */ GIOChannel *net_connect_unix(const char *path); /* Disconnect socket */ diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h index e6345692..399ddd11 100644 --- a/src/core/server-connect-rec.h +++ b/src/core/server-connect-rec.h @@ -5,7 +5,7 @@ int chat_type; /* chat_protocol_lookup(xx) */ int refcount; -struct network_proxy *proxy; +struct network_proxy *proxy; unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */ char *tag; /* try to keep this tag when connected to server */ diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 284f2b6e..28812e5e 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -215,11 +215,11 @@ static void server_init(IRC_SERVER_REC *server) char *address, *ptr, *username, *cmd; GTimeVal now; - struct network_proxy_send_string_info const send_info = { - .host = server->connrec->address, - .port = server->connrec->port, - .func = irc_send_cmd_now_wrapper, - .obj = server + const struct network_proxy_send_string_info send_info = { + .host = server->connrec->address, + .port = server->connrec->port, + .func = irc_send_cmd_now_wrapper, + .obj = server }; g_return_if_fail(server != NULL); From 5587d78cfd7b9b2645a423ac366c5b43bfe12e4b Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 14:13:50 +0100 Subject: [PATCH 09/15] Fixed stuff broken by the coding style cleanup From the original patch by hawken93 4th Oct 2014 --- src/core/network-proxy.h | 14 +++++++------- src/core/network.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h index 89b195bc..56365639 100644 --- a/src/core/network-proxy.h +++ b/src/core/network-proxy.h @@ -46,25 +46,25 @@ struct network_proxy { * \arg address the hostname where proxy shall connect to * \arg port port address where proxy shall connect to */ - GIOChannel *(*connect)(struct network_proxy const *, IPADDR const *hint_ip, - char const *address, int port); + GIOChannel *(*connect)(const struct network_proxy *, IPADDR const *hint_ip, + const char *address, int port); /* clones the given network_proxy object; this memberfunction is * mandatory */ - struct network_proxy * (*clone)(struct network_proxy const *); + struct network_proxy * (*clone)(const struct network_proxy *); /* sends a string after connection has been established but before IRC * authentication begins; this memberfunction is optional */ - void (*send_string)(struct network_proxy const *, - struct network_proxy_send_string_info const *); + void (*send_string)(const struct network_proxy *, + const struct network_proxy_send_string_info *); /* sends a string after connection IRC authentication suceeded; this * memberfunction is optional */ - void (*send_string_after)(struct network_proxy const *, - struct network_proxy_send_string_info const *); + void (*send_string_after)(const struct network_proxy *, + const struct network_proxy_send_string_info *); /* hostname of proxy host */ diff --git a/src/core/network.h b/src/core/network.h index ab37cd1d..5ca4dce5 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -40,7 +40,7 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip); /* Connect to socket with ip address and SSL*/ -GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char c*host, int port, +GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char *host, int port, IPADDR *ip, IPADDR *my_ip, SERVER_REC *server); int irssi_ssl_handshake(GIOChannel *handle); From 1f43db16d4f3c290ddf467e16418cc5e75595bd2 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 14:16:56 +0100 Subject: [PATCH 10/15] Fix compile warnings From original patch by hawken93 4th Oct 2014 --- src/core/network.c | 2 +- src/core/network.h | 2 +- src/core/servers.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/network.c b/src/core/network.c index 32601228..be6f31b0 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -146,7 +146,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) } /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) +GIOChannel *net_connect_ip(const IPADDR *ip, int port, IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; diff --git a/src/core/network.h b/src/core/network.h index 5ca4dce5..a3a4a50e 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -45,7 +45,7 @@ GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char int irssi_ssl_handshake(GIOChannel *handle); /* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); +GIOChannel *net_connect_ip(const IPADDR *ip, int port, IPADDR *my_ip); GIOChannel *net_connect_proxy(const struct network_proxy *proxy, const char *host, int port, IPADDR *ip, IPADDR *my_ip); /* Connect to named UNIX socket */ diff --git a/src/core/servers.c b/src/core/servers.c index dbc8ae49..81b7f17d 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -225,7 +225,7 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip, net_connect_proxy_ssl(server->connrec->proxy, server->connrec->address, port, ip, own_ip, - server->connrec) : + server) : net_connect_proxy(server->connrec->proxy, server->connrec->address, port, ip, own_ip); From e9211c8ed4290687266175e33451ac11df43ceba Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 14:23:57 +0100 Subject: [PATCH 11/15] Removed casts in g_free(), therefore also removed some const declarations From original patch by hawken93 4th Oct 2014 --- src/core/network-proxy-http.c | 2 +- src/core/network-proxy-http.h | 2 +- src/core/network-proxy-priv.h | 2 +- src/core/network-proxy-socks5.c | 4 ++-- src/core/network-proxy-socks5.h | 4 ++-- src/core/network-proxy.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c index fa27c7c1..10363986 100644 --- a/src/core/network-proxy-http.c +++ b/src/core/network-proxy-http.c @@ -29,7 +29,7 @@ static void network_proxy_http_destroy(struct network_proxy *proxy) { struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); - g_free((void *)self->password); + g_free(self->password); _network_proxy_destroy(proxy); g_free(self); diff --git a/src/core/network-proxy-http.h b/src/core/network-proxy-http.h index b47bfc5e..6994f917 100644 --- a/src/core/network-proxy-http.h +++ b/src/core/network-proxy-http.h @@ -21,7 +21,7 @@ struct _network_proxy_http { struct network_proxy proxy; - char const *password; + char *password; }; struct network_proxy *_network_proxy_http_create(void); diff --git a/src/core/network-proxy-priv.h b/src/core/network-proxy-priv.h index 8e5fcf95..c2a88e10 100644 --- a/src/core/network-proxy-priv.h +++ b/src/core/network-proxy-priv.h @@ -44,7 +44,7 @@ inline static void _network_proxy_clone(struct network_proxy *dst, struct networ inline static void _network_proxy_destroy(struct network_proxy *proxy) { - g_free((void *)proxy->host); + g_free(proxy->host); } diff --git a/src/core/network-proxy-socks5.c b/src/core/network-proxy-socks5.c index 69214b10..b0c08afb 100644 --- a/src/core/network-proxy-socks5.c +++ b/src/core/network-proxy-socks5.c @@ -65,8 +65,8 @@ static void network_proxy_socks5_destroy(struct network_proxy *proxy) { struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); - g_free((void *)self->password); - g_free((void *)self->username); + g_free(self->password); + g_free(self->username); _network_proxy_destroy(proxy); g_free(self); } diff --git a/src/core/network-proxy-socks5.h b/src/core/network-proxy-socks5.h index c1e7e22c..b311265f 100644 --- a/src/core/network-proxy-socks5.h +++ b/src/core/network-proxy-socks5.h @@ -22,8 +22,8 @@ struct _network_proxy_socks5 { struct network_proxy proxy; - char const *username; - char const *password; + char *username; + char *password; }; struct network_proxy *_network_proxy_socks5_create(void); diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h index 56365639..be3e5169 100644 --- a/src/core/network-proxy.h +++ b/src/core/network-proxy.h @@ -24,7 +24,7 @@ * class */ struct network_proxy_send_string_info { - char const *host; /* hostname of the IRC server */ + char *host; /* hostname of the IRC server */ uint16_t port; /* portnumber of the IRC server */ /* function which is used to send string; usually irc_send_cmd_now() */ From be3d3708b6156db2c2344d2089d0c930474f8ea1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 14:25:42 +0100 Subject: [PATCH 12/15] add missing proxy_username setting From original patch by hawken93 5th Oct 2014 --- src/core/servers-setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 9bc0e422..fcaeef61 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -593,6 +593,7 @@ void servers_setup_init(void) settings_add_int("proxy", "proxy_port", 6667); settings_add_str("proxy", "proxy_string", "CONNECT %s %d"); settings_add_str("proxy", "proxy_string_after", ""); + settings_add_str("proxy", "proxy_username", ""); settings_add_str("proxy", "proxy_password", ""); settings_add_str("proxy", "proxy_type", "simple"); From cf48ac6210db247da165ae0227617e40a155b9f8 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 14:49:25 +0100 Subject: [PATCH 13/15] remove container_of, remove some underscores in the process From the original patch by hawken93 5th Oct 2014 --- src/core/network-proxy-http.c | 60 ++++++++++++++++++++------------- src/core/network-proxy-http.h | 5 ++- src/core/network-proxy-priv.h | 8 ++--- src/core/network-proxy-socks5.c | 60 +++++++++++++++++++-------------- src/core/network-proxy-socks5.h | 6 ++-- src/core/network-proxy.h | 3 ++ 6 files changed, 80 insertions(+), 62 deletions(-) diff --git a/src/core/network-proxy-http.c b/src/core/network-proxy-http.c index 10363986..aeff0fdf 100644 --- a/src/core/network-proxy-http.c +++ b/src/core/network-proxy-http.c @@ -27,28 +27,35 @@ static void network_proxy_http_destroy(struct network_proxy *proxy) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct network_proxy_http *self = (struct network_proxy_http *)proxy->privdata; g_free(self->password); - _network_proxy_destroy(proxy); g_free(self); + + _network_proxy_destroy(proxy); + + g_free(proxy); } -static struct network_proxy * -network_proxy_http_clone(struct network_proxy const *proxy) +static struct network_proxy *network_proxy_http_clone(struct network_proxy const *proxy) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); - struct _network_proxy_http *res; + struct network_proxy_http *self = (struct network_proxy_http *)proxy->privdata; + struct network_proxy_http *priv; + struct network_proxy *res; + + res = g_malloc0(sizeof(struct network_proxy)); - res = g_malloc0(sizeof *res); + _network_proxy_clone(res, proxy); - _network_proxy_clone(&res->proxy, &self->proxy); - res->password = g_strdup(self->password); - return &res->proxy; + priv = g_malloc0(sizeof(struct network_proxy_http)); + res->privdata = (void *)priv; + + priv->password = g_strdup(self->password); + return res; } -static bool send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, +static bool send_connect(struct network_proxy_http *proxy, GIOChannel *ch, char const *address, uint16_t port) { char port_str[6]; @@ -67,7 +74,7 @@ static bool send_connect(struct _network_proxy_http *proxy, GIOChannel *ch, return true; } -static int read_response(struct _network_proxy_http *proxy, GIOChannel *ch) +static int read_response(struct network_proxy_http *proxy, GIOChannel *ch) { GIOStatus status; GString line = { .str = NULL }; @@ -126,7 +133,7 @@ err: static GIOChannel *network_proxy_http_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, char const *address, int port) { - struct _network_proxy_http *self = container_of(proxy, struct _network_proxy_http, proxy); + struct network_proxy_http *self = (struct network_proxy_http *)proxy->privdata; GIOChannel *ch; GIOFlags old_flags; GError *err = NULL; @@ -134,9 +141,9 @@ static GIOChannel *network_proxy_http_connect(struct network_proxy const *proxy, gint line_term_sz; if (hint_ip) - ch = net_connect_ip(hint_ip, self->proxy.port, NULL); + ch = net_connect_ip(hint_ip, proxy->port, NULL); else - ch = net_connect(self->proxy.host, self->proxy.port, NULL); + ch = net_connect(proxy->host, proxy->port, NULL); if (!ch) return NULL; @@ -172,18 +179,23 @@ err: } -struct network_proxy *_network_proxy_http_create(void) +struct network_proxy *network_proxy_http_create(void) { - struct _network_proxy_http *res; + struct network_proxy *res; + struct network_proxy_http *priv; - res = g_malloc0(sizeof *res); + res = g_malloc0(sizeof(struct network_proxy)); - _network_proxy_create(&res->proxy); - res->password = g_strdup(settings_get_str("proxy_password")); + _network_proxy_create(res); - res->proxy.destroy = network_proxy_http_destroy; - res->proxy.connect = network_proxy_http_connect; - res->proxy.clone = network_proxy_http_clone; + priv = g_malloc0(sizeof(struct network_proxy_http)); + res->privdata = (void *)priv; - return &res->proxy; + priv->password = g_strdup(settings_get_str("proxy_password")); + + res->destroy = network_proxy_http_destroy; + res->connect = network_proxy_http_connect; + res->clone = network_proxy_http_clone; + + return res; } diff --git a/src/core/network-proxy-http.h b/src/core/network-proxy-http.h index 6994f917..d9d0639e 100644 --- a/src/core/network-proxy-http.h +++ b/src/core/network-proxy-http.h @@ -19,11 +19,10 @@ #include "network-proxy.h" -struct _network_proxy_http { - struct network_proxy proxy; +struct network_proxy_http { char *password; }; -struct network_proxy *_network_proxy_http_create(void); +struct network_proxy *network_proxy_http_create(void); #endif /* H_IRSSI_SRC_CORE_PROXY_HTTP_H */ diff --git a/src/core/network-proxy-priv.h b/src/core/network-proxy-priv.h index c2a88e10..7dfcf5ce 100644 --- a/src/core/network-proxy-priv.h +++ b/src/core/network-proxy-priv.h @@ -19,15 +19,11 @@ #include "settings.h" #include - -/* stolen from linux kernel */ -#define container_of(ptr, type, member) __extension__ ({ \ - const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - inline static void _network_proxy_create(struct network_proxy *dst) { + // TODO: Initialize all fields, to bring the struct to a known state + dst->privdata = NULL; dst->port = settings_get_int("proxy_port"); dst->host = g_strdup(settings_get_str("proxy_address")); } diff --git a/src/core/network-proxy-socks5.c b/src/core/network-proxy-socks5.c index b0c08afb..739583c4 100644 --- a/src/core/network-proxy-socks5.c +++ b/src/core/network-proxy-socks5.c @@ -63,25 +63,30 @@ struct server_response static void network_proxy_socks5_destroy(struct network_proxy *proxy) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct network_proxy_socks5 *self = (struct network_proxy_socks5 *)proxy->privdata; g_free(self->password); g_free(self->username); - _network_proxy_destroy(proxy); g_free(self); + _network_proxy_destroy(proxy); + g_free(proxy); } static struct network_proxy *network_proxy_socks5_clone(struct network_proxy const *proxy) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); - struct _network_proxy_socks5 *res; + struct network_proxy_socks5 *self = (struct network_proxy_socks5 *)proxy->privdata; + struct network_proxy_socks5 *priv; + struct network_proxy *res; - res = g_malloc0(sizeof *res); + res = g_malloc0(sizeof(struct network_proxy)); + _network_proxy_clone(res, proxy); + + priv = g_malloc0(sizeof(struct network_proxy_socks5)); + res->privdata = (void *)priv; - _network_proxy_clone(&res->proxy, &self->proxy); - res->username = g_strdup(self->username); - res->password = g_strdup(self->password); - return &res->proxy; + priv->username = g_strdup(self->username); + priv->password = g_strdup(self->password); + return res; } static bool socks5_connect_unauthorized(GIOChannel *ch) @@ -92,9 +97,9 @@ static bool socks5_connect_unauthorized(GIOChannel *ch) } /* TODO: test this method! */ -static bool socks5_connect_plain(struct _network_proxy_socks5 const *proxy, GIOChannel *ch) +static bool socks5_connect_plain(const struct network_proxy_socks5 *proxy, GIOChannel *ch) { - uint8_t ver = 0x01; + uint8_t ver = 0x01; uint8_t ulen = strlen(proxy->username); uint8_t plen = proxy->password ? strlen(proxy->password) : 0; struct server_response_plain resp; @@ -122,7 +127,7 @@ static bool socks5_connect_plain(struct _network_proxy_socks5 const *proxy, GIOC return true; } -static bool socks5_connect(struct _network_proxy_socks5 const *proxy, GIOChannel *ch, +static bool socks5_connect(const struct network_proxy_socks5 *proxy, GIOChannel *ch, char const *address, uint16_t port) { bool rc; @@ -265,7 +270,7 @@ err: static GIOChannel *network_proxy_socks5_connect(struct network_proxy const *proxy, IPADDR const *hint_ip, char const *address, int port) { - struct _network_proxy_socks5 *self = container_of(proxy, struct _network_proxy_socks5, proxy); + struct network_proxy_socks5 *self = (struct network_proxy_socks5 *)proxy->privdata; GIOChannel *ch; GIOFlags old_flags; @@ -274,9 +279,9 @@ static GIOChannel *network_proxy_socks5_connect(struct network_proxy const *prox GError *err = NULL; if (hint_ip) - ch = net_connect_ip(hint_ip, self->proxy.port, NULL); + ch = net_connect_ip(hint_ip, proxy->port, NULL); else - ch = net_connect(self->proxy.host, self->proxy.port, NULL); + ch = net_connect(proxy->host, proxy->port, NULL); if (!ch) return NULL; @@ -313,19 +318,24 @@ err: return NULL; } -struct network_proxy *_network_proxy_socks5_create(void) +struct network_proxy *network_proxy_socks5_create(void) { - struct _network_proxy_socks5 *res; + struct network_proxy *res; + struct network_proxy_socks5 *priv; - res = g_malloc0(sizeof *res); + res = g_malloc0(sizeof(struct network_proxy)); - _network_proxy_create(&res->proxy); - res->username = g_strdup(settings_get_str("proxy_username")); - res->password = g_strdup(settings_get_str("proxy_password")); + _network_proxy_create(res); - res->proxy.destroy = network_proxy_socks5_destroy; - res->proxy.connect = network_proxy_socks5_connect; - res->proxy.clone = network_proxy_socks5_clone; + priv = g_malloc0(sizeof(struct network_proxy_socks5)); + res->privdata = (void *)priv; - return &res->proxy; + priv->username = g_strdup(settings_get_str("proxy_username")); + priv->password = g_strdup(settings_get_str("proxy_password")); + + res->destroy = network_proxy_socks5_destroy; + res->connect = network_proxy_socks5_connect; + res->clone = network_proxy_socks5_clone; + + return res; } diff --git a/src/core/network-proxy-socks5.h b/src/core/network-proxy-socks5.h index b311265f..70bc3bad 100644 --- a/src/core/network-proxy-socks5.h +++ b/src/core/network-proxy-socks5.h @@ -19,13 +19,11 @@ #include "network-proxy.h" -struct _network_proxy_socks5 { - struct network_proxy proxy; - +struct network_proxy_socks5 { char *username; char *password; }; -struct network_proxy *_network_proxy_socks5_create(void); +struct network_proxy *network_proxy_socks5_create(void); #endif /* H_IRSSI_SRC_CORE_PROXY_SOCKS5_H */ diff --git a/src/core/network-proxy.h b/src/core/network-proxy.h index be3e5169..cbcb863b 100644 --- a/src/core/network-proxy.h +++ b/src/core/network-proxy.h @@ -35,6 +35,9 @@ struct network_proxy_send_string_info }; struct network_proxy { + /* Contains private data for the chosen proxy type */ + void *privdata; + /* destroys the network_proxy structure which must not be used anymore * after; this memberfunction is mandatory */ void (*destroy)(struct network_proxy *); From 20eca8be581492fc78ce8f8b9813e34120d76a43 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 14 Apr 2016 17:16:55 +0100 Subject: [PATCH 14/15] Fix warnings --- src/core/network-proxy-priv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/network-proxy-priv.h b/src/core/network-proxy-priv.h index 7dfcf5ce..22b4eaf0 100644 --- a/src/core/network-proxy-priv.h +++ b/src/core/network-proxy-priv.h @@ -40,7 +40,7 @@ inline static void _network_proxy_clone(struct network_proxy *dst, struct networ inline static void _network_proxy_destroy(struct network_proxy *proxy) { - g_free(proxy->host); + g_free((void*)proxy->host); } @@ -81,7 +81,7 @@ inline static bool _network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t l if (status!=G_IO_STATUS_NORMAL) break; - buf = l; + buf = (gchar *)l; len -= l; } From 9caed63b2159a99853958ace42deac61464fce47 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 15 Apr 2016 10:23:31 +0100 Subject: [PATCH 15/15] socks5 set buffering before encoding --- src/core/network-proxy-socks5.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/network-proxy-socks5.c b/src/core/network-proxy-socks5.c index 739583c4..41b3c9f0 100644 --- a/src/core/network-proxy-socks5.c +++ b/src/core/network-proxy-socks5.c @@ -135,7 +135,6 @@ static bool socks5_connect(const struct network_proxy_socks5 *proxy, GIOChannel struct server_greeting s_greeting; struct server_response s_response; - /* Phase 1: exchange greeting */ { struct client_greeting c_greeting = { @@ -290,12 +289,11 @@ static GIOChannel *network_proxy_socks5_connect(struct network_proxy const *prox old_flags = g_io_channel_get_flags(ch); old_buf = g_io_channel_get_buffered(ch); + g_io_channel_set_buffered(ch, true); if (g_io_channel_set_encoding(ch, NULL, &err)!=G_IO_STATUS_NORMAL || g_io_channel_set_flags(ch, old_flags & ~G_IO_FLAG_NONBLOCK, &err)!=G_IO_STATUS_NORMAL) goto err; - g_io_channel_set_buffered(ch, false); - if (!socks5_connect(self, ch, address, port)) goto err;