# HG changeset patch # User David Demelier # Date 1624171342 -7200 # Node ID a4afc89f6ea8992519a14caa5aaaa7d718ce7b10 # Parent 0e48e22a7493bf3c6ed08e15199e22cc22471630 irccd: detect SSL handshake failure diff -r 0e48e22a7493 -r a4afc89f6ea8 lib/irccd/conn.c --- a/lib/irccd/conn.c Thu Jun 17 13:57:37 2021 +0200 +++ b/lib/irccd/conn.c Sun Jun 20 08:42:22 2021 +0200 @@ -275,20 +275,23 @@ } /* - * From SSL_do_handshake manual page: - * < 0 -> fatal error - * == 0 -> incomplete handshake - * == 1 -> success + * AFAIK, there is no way to detect that we're discussing with + * a non SSL server, as a consequence SSL_get_error will return + * SSL_ERROR_WANT_READ indefinitely. What we do is to detect + * the failure to complete SSL_do_handshake in the amount of + * three seconds before indicating that we've failed to + * connect. */ - if ((r = SSL_do_handshake(conn->ssl)) < 0) { - irc_log_warn("server %s: handshake failed (is the port SSL?)", conn->sv->name); - irc_conn_disconnect(conn); - return -1; + if ((r = SSL_do_handshake(conn->ssl)) <= 0) { + if (difftime(time(NULL), conn->statetime) >= 3) + return irc_log_warn("server %s: unable to complete handshake", conn->sv->name), -1; + + irc_log_debug("server %s: handshake incomplete", conn->sv->name); + + return update_ssl_state(conn, r); } - if (r == 0) - return update_ssl_state(conn, r); - + conn->statetime = time(NULL); conn->state = IRC_CONN_STATE_READY; conn->ssl_cond = IRC_CONN_SSL_ACT_NONE; conn->ssl_step = IRC_CONN_SSL_ACT_NONE; @@ -400,6 +403,8 @@ { assert(conn); + conn->statetime = time(NULL); + if (lookup(conn) < 0) return irc_conn_disconnect(conn), -1; diff -r 0e48e22a7493 -r a4afc89f6ea8 lib/irccd/conn.h --- a/lib/irccd/conn.h Thu Jun 17 13:57:37 2021 +0200 +++ b/lib/irccd/conn.h Sun Jun 20 08:42:22 2021 +0200 @@ -25,6 +25,8 @@ # include #endif +#include + #include "limits.h" #if defined(__cplusplus) @@ -68,6 +70,7 @@ enum irc_conn_state state; enum irc_conn_flags flags; struct irc_server *sv; + time_t statetime; #if defined(IRCCD_WITH_SSL) SSL_CTX *ctx;