From aeb047260fefa187f5b2c5c740280c81b9ccb8f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Wed, 9 Dec 2015 00:53:56 +0100 Subject: [PATCH] Bump liberty, enable TLS SNI Involves some rewrites to fit the new APIs. SNI has been implemented Mostly just because we can, I don't think it's widely in use and kike doesn't support this feature of the protocol either. --- CMakeLists.txt | 15 ++++++++++++--- NEWS | 9 +++++++++ common.c | 28 +++++++++------------------- degesch.c | 48 ++++++++++++++++++------------------------------ kike.c | 1 + liberty | 2 +- zyklonb.c | 4 +++- 7 files changed, 53 insertions(+), 54 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca76dfa..2d25f6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,9 @@ set (project_VERSION "${project_VERSION}.${project_VERSION_MINOR}") set (project_VERSION "${project_VERSION}.${project_VERSION_PATCH}") # Dependencies +set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/liberty/cmake) +include (AddThreads) + find_package (Curses) find_package (PkgConfig REQUIRED) pkg_check_modules (libssl REQUIRED libssl libcrypto) @@ -52,10 +55,9 @@ if (WITH_LUA) link_directories (${lua_LIBRARY_DIRS}) endif (WITH_LUA) -# -lpthread is only there for debugging (gdb & errno) # -lrt is only for glibc < 2.17 # -liconv may or may not be a part of libc -foreach (extra iconv rt pthread) +foreach (extra iconv rt) find_library (extra_lib_${extra} ${extra}) if (extra_lib_${extra}) list (APPEND project_libraries ${extra}) @@ -114,24 +116,31 @@ set_source_files_properties (${PROJECT_BINARY_DIR}/kike-replies.c # Build add_executable (zyklonb zyklonb.c ${common_sources} ${common_headers}) target_link_libraries (zyklonb ${project_libraries}) +add_threads (zyklonb) add_executable (degesch degesch.c kike-replies.c ${common_sources} ${common_headers}) target_link_libraries (degesch ${project_libraries}) +add_threads (degesch) add_executable (kike kike.c kike-replies.c ${common_sources} ${common_headers}) target_link_libraries (kike ${project_libraries}) +add_threads (kike) # Tests function (make_tests_for target_name) get_target_property (sources ${target_name} SOURCES) get_target_property (libraries ${target_name} LINK_LIBRARIES) + get_target_property (options ${target_name} COMPILE_OPTIONS) set (test test-${target_name}) add_executable (${test} ${sources}) target_link_libraries (${test} ${libraries}) + set_target_properties (${test} PROPERTIES + COMPILE_DEFINITIONS TESTING + COMPILE_OPTIONS ${options}) + add_test (NAME ${test} COMMAND ${test}) - set_target_properties (${test} PROPERTIES COMPILE_DEFINITIONS TESTING) endfunction (make_tests_for) include (CTest) diff --git a/NEWS b/NEWS index 49473f4..fccdfbc 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ +0.9.3 (2016-??-??) + + * Use TLS Server Name Indication when connecting to servers + + * degesch: resolve remote addresses asynchronously + + * degesch: various bugfixes + + 0.9.2 (2015-12-31) * degesch: added rudimentary support for Lua scripting diff --git a/common.c b/common.c index 0d34591..d4cf479 100644 --- a/common.c +++ b/common.c @@ -18,6 +18,7 @@ */ #define LIBERTY_WANT_SSL +#define LIBERTY_WANT_ASYNC #define LIBERTY_WANT_POLLER #define LIBERTY_WANT_PROTO_IRC @@ -40,9 +41,6 @@ return 0; \ BLOCK_END -#define CONTAINER_OF(pointer, type, member) \ - (type *) ((char *) pointer - offsetof (type, member)) - // --- To be moved to liberty -------------------------------------------------- static ssize_t @@ -223,7 +221,7 @@ struct socks_connector // You may destroy the connector object in these two main callbacks: /// Connection has been successfully established - void (*on_connected) (void *user_data, int socket); + void (*on_connected) (void *user_data, int socket, const char *hostname); /// Failed to establish a connection to either target void (*on_failure) (void *user_data); @@ -594,9 +592,11 @@ socks_connector_on_timeout (struct socks_connector *self) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static void -socks_connector_on_connected (void *user_data, int socket_fd) +socks_connector_on_connected + (void *user_data, int socket_fd, const char *hostname) { set_blocking (socket_fd, false); + (void) hostname; struct socks_connector *self = user_data; self->socket_fd = socket_fd; @@ -658,20 +658,8 @@ socks_connector_start (struct socks_connector *self) connector->on_error = socks_connector_on_error; connector->on_failure = socks_connector_on_failure; - struct error *e = NULL; - if (!connector_add_target (connector, self->hostname, self->service, &e)) - { - if (self->on_error) - self->on_error (self->user_data, e->message); - error_free (e); - - socks_connector_destroy_connector (self); - socks_connector_fail (self); - return; - } - + connector_add_target (connector, self->hostname, self->service); poller_timer_set (&self->timeout, 60 * 1000); - connector_step (connector); self->done = false; self->bound_port = 0; @@ -762,8 +750,10 @@ socks_connector_on_ready int fd = self->socket_fd; self->socket_fd = -1; + + struct socks_target *target = self->targets_iter; set_blocking (fd, true); - self->on_connected (self->user_data, fd); + self->on_connected (self->user_data, fd, target->address_str); } else // We've failed this target, let's try to move on diff --git a/degesch.c b/degesch.c index 59a60a0..7163098 100644 --- a/degesch.c +++ b/degesch.c @@ -1150,7 +1150,7 @@ enum transport_io_result struct transport { /// Initialize the transport - bool (*init) (struct server *s, struct error **e); + bool (*init) (struct server *s, const char *hostname, struct error **e); /// Destroy the user data pointer void (*cleanup) (struct server *s); @@ -4492,7 +4492,7 @@ transport_tls_init_cert (struct server *s, SSL *ssl, struct error **e) } static bool -transport_tls_init (struct server *s, struct error **e) +transport_tls_init (struct server *s, const char *hostname, struct error **e) { ERR_clear_error (); @@ -4519,6 +4519,12 @@ transport_tls_init (struct server *s, struct error **e) if (!SSL_set_fd (ssl, s->socket)) goto error_ssl_3; + // Enable SNI, FWIW; literal IP addresses aren't allowed + struct in6_addr dummy; + if (!inet_pton (AF_INET, hostname, &dummy) + && !inet_pton (AF_INET6, hostname, &dummy)) + SSL_set_tlsext_host_name (ssl, hostname); + struct transport_tls_data *data = xcalloc (1, sizeof *data); data->ssl_ctx = ssl_ctx; data->ssl = ssl; @@ -4749,7 +4755,7 @@ irc_register (struct server *s) } static void -irc_finish_connection (struct server *s, int socket) +irc_finish_connection (struct server *s, int socket, const char *hostname) { struct app_context *ctx = s->ctx; @@ -4766,7 +4772,7 @@ irc_finish_connection (struct server *s, int socket) : &g_transport_plain; struct error *e = NULL; - if (s->transport->init && !s->transport->init (s, &e)) + if (s->transport->init && !s->transport->init (s, hostname, &e)) { log_server_error (s, s->buffer, "Connection failed: #s", e->message); error_free (e); @@ -4837,16 +4843,17 @@ irc_on_connector_failure (void *user_data) } static void -irc_on_connector_connected (void *user_data, int socket) +irc_on_connector_connected (void *user_data, int socket, const char *hostname) { struct server *s = user_data; + char *hostname_copy = xstrdup (hostname); irc_destroy_connector (s); - irc_finish_connection (s, socket); + irc_finish_connection (s, socket, hostname_copy); + free (hostname_copy); } -static bool -irc_setup_connector (struct server *s, - const struct str_vector *addresses, struct error **e) +static void +irc_setup_connector (struct server *s, const struct str_vector *addresses) { struct connector *connector = xmalloc (sizeof *connector); connector_init (connector, &s->ctx->poller); @@ -4858,31 +4865,12 @@ irc_setup_connector (struct server *s, connector->on_connected = irc_on_connector_connected; connector->on_failure = irc_on_connector_failure; - bool at_least_one_address_succeeded = false; for (size_t i = 0; i < addresses->len; i++) { char *host, *port; irc_split_host_port (addresses->vector[i], &host, &port); - - struct error *error = NULL; - if (connector_add_target (connector, host, port, &error)) - at_least_one_address_succeeded = true; - else - { - log_server_error (s, s->buffer, - "Address resolution failed for #&s: #s", - format_host_port_pair (host, port), error->message); - error_free (error); - } + connector_add_target (connector, host, port); } - if (!at_least_one_address_succeeded) - { - error_set (e, "No address to connect to"); - return false; - } - - connector_step (connector); - return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -4963,7 +4951,7 @@ irc_initiate_connect (struct server *s) struct error *e = NULL; if (!irc_setup_connector_socks (s, &servers, &e) && !e) - irc_setup_connector (s, &servers, &e); + irc_setup_connector (s, &servers); str_vector_free (&servers); diff --git a/kike.c b/kike.c index c81d91c..b672339 100644 --- a/kike.c +++ b/kike.c @@ -3385,6 +3385,7 @@ irc_try_fetch_client (struct server_context *ctx, int listen_fd) return true; } + // FIXME: use async_getnameinfo() so that we never ever block here char host[NI_MAXHOST] = "unknown", port[NI_MAXSERV] = "unknown"; int err = getnameinfo ((struct sockaddr *) &peer, peer_len, host, sizeof host, port, sizeof port, NI_NUMERICSERV); diff --git a/liberty b/liberty index f6d7454..bc7e831 160000 --- a/liberty +++ b/liberty @@ -1 +1 @@ -Subproject commit f6d74544f82ce8186e73a6ba268c2bc56b3ce5c7 +Subproject commit bc7e83137ed2a14957e1b3feb5de658f8505ed57 diff --git a/zyklonb.c b/zyklonb.c index a99038d..34e6e7e 100644 --- a/zyklonb.c +++ b/zyklonb.c @@ -1663,8 +1663,10 @@ struct irc_socks_data }; static void -irc_on_socks_connected (void *user_data, int socket) +irc_on_socks_connected (void *user_data, int socket, const char *hostname) { + (void) hostname; + struct irc_socks_data *data = user_data; data->ctx->irc_fd = socket; data->succeeded = true;