From e6f2fa19bbc4ef9d0962464baefa259e2beda8e4 Mon Sep 17 00:00:00 2001 From: Cizzle Date: Sun, 18 Nov 2018 23:45:34 +0100 Subject: [PATCH] Fix failing tls upgrade of plain-to-plain botlink. Fixes #580 Found by: maimizuno, Cizzle Patch by: Cizzle Fixes: #580 Upgrading a starting botlink to use TLS when both hub and leaf used non-TLS ports (no +prefix) occasionally timed out for no apparent reason. The failure happened due to the Client Hello of the TLS handshake arriving too soon and together with the "startls -" botlinkmessage at the hub causing that Client Hello to be missed by the TLS handshake. The fix consists of two parts, one for the hub and one for the leaf. This way the fix is backward compatible for hubs having to deal with unpatched leafs and leafs having to deal with unpatched hubs. --- src/dcc.c | 5 +++++ src/eggdrop.h | 4 ++++ src/net.c | 6 ++++++ src/tls.c | 3 +++ 4 files changed, 18 insertions(+) diff --git a/src/dcc.c b/src/dcc.c index 5deb77d8c..abe5aebad 100644 --- a/src/dcc.c +++ b/src/dcc.c @@ -1782,6 +1782,11 @@ static void dcc_telnet_pass(int idx, int atr) * will simply ignore the request and everything will go on as usual. */ if (!dcc[idx].ssl) { + /* find number in socklist */ + int i = findsock(dcc[idx].sock); + struct threaddata *td = threaddata(); + /* mark socket to read next incoming at reduced len */ + td->socklist[i].flags |= SOCK_SENTTLS; dprintf(idx, "starttls\n"); putlog(LOG_BOTS, "*", "Sent STARTTLS to %s...", dcc[idx].nick); } diff --git a/src/eggdrop.h b/src/eggdrop.h index cdf70c52a..9153a563e 100644 --- a/src/eggdrop.h +++ b/src/eggdrop.h @@ -652,6 +652,10 @@ typedef struct { #define SOCK_VIRTUAL 0x0200 /* not-connected socket (dont read it!) */ #define SOCK_BUFFER 0x0400 /* buffer data; don't notify dcc funcs */ #define SOCK_TCL 0x0800 /* tcl socket, don't do anything on it */ +#ifdef TLS +# define SOCK_SENTTLS 0x1000 /* Socket that awaits a starttls in the + * next read */ +#endif /* Flags to sock_has_data */ diff --git a/src/net.c b/src/net.c index 416116301..b892a8a7e 100644 --- a/src/net.c +++ b/src/net.c @@ -919,6 +919,12 @@ int sockread(char *s, int *len, sock_list *slist, int slistmax, int tclonly) ERR_error_string(ERR_get_error(), 0), err); x = -1; } + } else if (slist[i].flags & SOCK_SENTTLS) { + /* We are awaiting a reply on our "starttls", only read + * strlen("starttls -\n") bytes so we don't accidently + * read the Client Hello from the ssl handshake */ + x = read(slist[i].sock, s, strlen("starttls -\n")); + slist[i].flags &= ~SOCK_SENTTLS; } else x = read(slist[i].sock, s, grab); } diff --git a/src/tls.c b/src/tls.c index 535f95767..5c1100cf9 100644 --- a/src/tls.c +++ b/src/tls.c @@ -780,7 +780,10 @@ int ssl_handshake(int sock, int flags, int verify, int loglevel, char *host, SSL_set_mode(td->socklist[i].ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); if (data->flags & TLS_CONNECT) { + struct timespec req = { 0, 1000000L }; SSL_set_verify(td->socklist[i].ssl, SSL_VERIFY_PEER, ssl_verify); + /* Introduce 1ms lag so an unpatched hub has time to setup the ssl handshake */ + nanosleep(&req, NULL); ret = SSL_connect(td->socklist[i].ssl); if (!ret) debug0("TLS: connect handshake failed.");