diff options
Diffstat (limited to 'src/libutil/ssl_util.c')
-rw-r--r-- | src/libutil/ssl_util.c | 99 |
1 files changed, 66 insertions, 33 deletions
diff --git a/src/libutil/ssl_util.c b/src/libutil/ssl_util.c index 62e22a3c6..32778f265 100644 --- a/src/libutil/ssl_util.c +++ b/src/libutil/ssl_util.c @@ -47,6 +47,7 @@ struct rspamd_ssl_connection { gboolean verify_peer; SSL *ssl; gchar *hostname; + const gchar *log_tag; struct rspamd_io_ev *ev; struct ev_loop *event_loop; rspamd_ssl_handler_t handler; @@ -54,6 +55,13 @@ struct rspamd_ssl_connection { gpointer handler_data; }; +#define msg_debug_ssl(...) rspamd_conditional_debug_fast (NULL, NULL, \ + rspamd_ssl_log_id, "ssl", conn->log_tag, \ + G_STRFUNC, \ + __VA_ARGS__) + +INIT_LOG_MODULE(ssl) + static GQuark rspamd_ssl_quark (void) { @@ -421,6 +429,7 @@ rspamd_ssl_shutdown (struct rspamd_ssl_connection *conn) if ((ret = SSL_shutdown (conn->ssl)) == 1) { /* All done */ + msg_debug_ssl ("ssl shutdown: all done"); rspamd_ssl_connection_dtor (conn); } else { @@ -430,13 +439,16 @@ rspamd_ssl_shutdown (struct rspamd_ssl_connection *conn) conn->state = ssl_next_shutdown; if (ret == SSL_ERROR_WANT_READ) { + msg_debug_ssl ("ssl shutdown: need read"); what = EV_READ; } else if (ret == SSL_ERROR_WANT_WRITE) { + msg_debug_ssl ("ssl shutdown: need read"); what = EV_WRITE; } else { /* Cannot do anything else, fatal error */ + msg_debug_ssl ("ssl shutdown: fatal error"); rspamd_ssl_connection_dtor (conn); return; @@ -451,89 +463,93 @@ rspamd_ssl_shutdown (struct rspamd_ssl_connection *conn) static void rspamd_ssl_event_handler (gint fd, short what, gpointer ud) { - struct rspamd_ssl_connection *c = ud; + struct rspamd_ssl_connection *conn = ud; gint ret; GError *err = NULL; if (what == EV_TIMER) { - if (c->state == ssl_next_shutdown) { + if (conn->state == ssl_next_shutdown) { /* No way to restore, just terminate */ - rspamd_ssl_connection_dtor (c); + rspamd_ssl_connection_dtor (conn); } else { - c->shut = ssl_shut_unclean; - rspamd_ev_watcher_stop (c->event_loop, c->ev); + conn->shut = ssl_shut_unclean; + rspamd_ev_watcher_stop (conn->event_loop, conn->ev); g_set_error (&err, rspamd_ssl_quark (), ETIMEDOUT, "ssl connection timed out"); - c->err_handler (c->handler_data, err); + conn->err_handler (conn->handler_data, err); g_error_free (err); } return; } - msg_debug ("ssl event; what=%d; c->state=%d", (int)what, (int)c->state); + msg_debug_ssl ("ssl event; what=%d; c->state=%d", (int)what, + (int)conn->state); - switch (c->state) { + switch (conn->state) { case ssl_conn_init: /* Continue connection */ - ret = SSL_connect (c->ssl); + ret = SSL_connect (conn->ssl); if (ret == 1) { - rspamd_ev_watcher_stop (c->event_loop, c->ev); + rspamd_ev_watcher_stop (conn->event_loop, conn->ev); /* Verify certificate */ - if ((!c->verify_peer) || rspamd_ssl_peer_verify (c)) { - c->state = ssl_conn_connected; - c->handler (fd, EV_WRITE, c->handler_data); + if ((!conn->verify_peer) || rspamd_ssl_peer_verify (conn)) { + msg_debug_ssl ("ssl connect: connected"); + conn->state = ssl_conn_connected; + conn->handler (fd, EV_WRITE, conn->handler_data); } else { return; } } else { - ret = SSL_get_error (c->ssl, ret); + ret = SSL_get_error (conn->ssl, ret); if (ret == SSL_ERROR_WANT_READ) { + msg_debug_ssl ("ssl connect: need read"); what = EV_READ; } else if (ret == SSL_ERROR_WANT_WRITE) { + msg_debug_ssl ("ssl connect: need write"); what = EV_WRITE; } else { - rspamd_ev_watcher_stop (c->event_loop, c->ev); + rspamd_ev_watcher_stop (conn->event_loop, conn->ev); rspamd_tls_set_error (ret, "connect", &err); - c->err_handler (c->handler_data, err); + conn->err_handler (conn->handler_data, err); g_error_free (err); return; } - rspamd_ev_watcher_reschedule (c->event_loop, c->ev, what); + rspamd_ev_watcher_reschedule (conn->event_loop, conn->ev, what); } break; case ssl_next_read: - rspamd_ev_watcher_reschedule (c->event_loop, c->ev, EV_READ); - c->state = ssl_conn_connected; - c->handler (fd, EV_READ, c->handler_data); + rspamd_ev_watcher_reschedule (conn->event_loop, conn->ev, EV_READ); + conn->state = ssl_conn_connected; + conn->handler (fd, EV_READ, conn->handler_data); break; case ssl_next_write: - rspamd_ev_watcher_reschedule (c->event_loop, c->ev, EV_WRITE); - c->state = ssl_conn_connected; - c->handler (fd, EV_WRITE, c->handler_data); + rspamd_ev_watcher_reschedule (conn->event_loop, conn->ev, EV_WRITE); + conn->state = ssl_conn_connected; + conn->handler (fd, EV_WRITE, conn->handler_data); break; case ssl_conn_connected: - rspamd_ev_watcher_reschedule (c->event_loop, c->ev, what); - c->state = ssl_conn_connected; - c->handler (fd, what, c->handler_data); + rspamd_ev_watcher_reschedule (conn->event_loop, conn->ev, what); + conn->state = ssl_conn_connected; + conn->handler (fd, what, conn->handler_data); break; case ssl_next_shutdown: - rspamd_ssl_shutdown (c); + rspamd_ssl_shutdown (conn); break; default: - rspamd_ev_watcher_stop (c->event_loop, c->ev); + rspamd_ev_watcher_stop (conn->event_loop, conn->ev); g_set_error (&err, rspamd_ssl_quark (), EINVAL, - "ssl bad state error: %d", c->state); - c->err_handler (c->handler_data, err); + "ssl bad state error: %d", conn->state); + conn->err_handler (conn->handler_data, err); g_error_free (err); break; } @@ -541,7 +557,7 @@ rspamd_ssl_event_handler (gint fd, short what, gpointer ud) struct rspamd_ssl_connection * rspamd_ssl_connection_new (gpointer ssl_ctx, struct ev_loop *ev_base, - gboolean verify_peer) + gboolean verify_peer, const gchar *log_tag) { struct rspamd_ssl_connection *c; @@ -550,6 +566,7 @@ rspamd_ssl_connection_new (gpointer ssl_ctx, struct ev_loop *ev_base, c->ssl = SSL_new (ssl_ctx); c->event_loop = ev_base; c->verify_peer = verify_peer; + c->log_tag = log_tag; return c; } @@ -603,6 +620,7 @@ rspamd_ssl_connect_fd (struct rspamd_ssl_connection *conn, gint fd, if (ret == 1) { conn->state = ssl_conn_connected; + msg_debug_ssl ("connected, start write event"); rspamd_ev_watcher_stop (conn->event_loop, ev); rspamd_ev_watcher_init (ev, fd, EV_WRITE, rspamd_ssl_event_handler, conn); rspamd_ev_watcher_start (conn->event_loop, ev, timeout); @@ -611,13 +629,16 @@ rspamd_ssl_connect_fd (struct rspamd_ssl_connection *conn, gint fd, ret = SSL_get_error (conn->ssl, ret); if (ret == SSL_ERROR_WANT_READ) { + msg_debug_ssl ("not connected, want read"); what = EV_READ; } else if (ret == SSL_ERROR_WANT_WRITE) { + msg_debug_ssl ("not connected, want write"); what = EV_WRITE; } else { conn->shut = ssl_shut_unclean; + msg_debug_ssl ("not connected, fatal error %d", ret); return FALSE; } @@ -653,6 +674,7 @@ rspamd_ssl_read (struct rspamd_ssl_connection *conn, gpointer buf, } ret = SSL_read (conn->ssl, buf, buflen); + msg_debug_ssl ("ssl read: %d", ret); if (ret > 0) { conn->state = ssl_conn_connected; @@ -681,9 +703,11 @@ rspamd_ssl_read (struct rspamd_ssl_connection *conn, gpointer buf, what = 0; if (ret == SSL_ERROR_WANT_READ) { + msg_debug_ssl ("ssl read: need read"); what |= EV_READ; } else if (ret == SSL_ERROR_WANT_WRITE) { + msg_debug_ssl ("ssl read: need write"); what |= EV_WRITE; } else { @@ -719,6 +743,7 @@ rspamd_ssl_write (struct rspamd_ssl_connection *conn, gconstpointer buf, } ret = SSL_write (conn->ssl, buf, buflen); + msg_debug_ssl ("ssl write: ret=%d, buflen=%z", ret, buflen); if (ret > 0) { conn->state = ssl_conn_connected; @@ -751,9 +776,11 @@ rspamd_ssl_write (struct rspamd_ssl_connection *conn, gconstpointer buf, conn->state = ssl_next_write; if (ret == SSL_ERROR_WANT_READ) { + msg_debug_ssl ("ssl write: need read"); what = EV_READ; } else if (ret == SSL_ERROR_WANT_WRITE) { + msg_debug_ssl ("ssl write: need write"); what = EV_WRITE; } else { @@ -777,10 +804,14 @@ gssize rspamd_ssl_writev (struct rspamd_ssl_connection *conn, struct iovec *iov, gsize iovlen) { - guchar ssl_buf[16000]; + /* + * Static is needed to avoid issue: + * https://github.com/openssl/openssl/issues/6865 + */ + static guchar ssl_buf[16384]; guchar *p; struct iovec *cur; - guint i, remain; + gsize i, remain; remain = sizeof (ssl_buf); p = ssl_buf; @@ -816,10 +847,12 @@ rspamd_ssl_connection_free (struct rspamd_ssl_connection *conn) if (conn) { if (conn->shut == ssl_shut_unclean) { /* Ignore return result and close socket */ + msg_debug_ssl ("unclean shutdown"); (void)SSL_shutdown (conn->ssl); rspamd_ssl_connection_dtor (conn); } else { + msg_debug_ssl ("normal shutdown"); rspamd_ssl_shutdown (conn); } } |