diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 9e16b130..16375439 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -96,22 +96,40 @@ static gboolean irssi_ssl_verify(SSL *ssl, SSL_CTX *ctx, X509 *cert) static GIOStatus irssi_ssl_read(GIOChannel *handle, gchar *buf, gsize len, gsize *ret, GError **gerr) { GIOSSLChannel *chan = (GIOSSLChannel *)handle; - gint err; + gint ret1, err; + const char *errstr; - err = SSL_read(chan->ssl, buf, len); - if(err < 0) + ret1 = SSL_read(chan->ssl, buf, len); + if(ret1 <= 0) { *ret = 0; - err = SSL_get_error(chan->ssl, err); + err = SSL_get_error(chan->ssl, ret1); if(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) return G_IO_STATUS_AGAIN; + else if(err == SSL_ERROR_ZERO_RETURN) + return G_IO_STATUS_EOF; + else if (err == SSL_ERROR_SYSCALL) + { + errstr = ERR_reason_error_string(ERR_get_error()); + if (errstr == NULL && ret1 == -1) + errstr = strerror(errno); + if (errstr == NULL) + errstr = "server closed connection unexpectedly"; + } + else + { + errstr = ERR_reason_error_string(ERR_get_error()); + if (errstr == NULL) + errstr = "unknown SSL error"; + } + g_warning("SSL read error: %s", errstr); *gerr = g_error_new_literal(G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, - ERR_reason_error_string(ERR_get_error())); + errstr); return G_IO_STATUS_ERROR; } else { - *ret = err; + *ret = ret1; return G_IO_STATUS_NORMAL; } /*UNREACH*/ @@ -121,22 +139,40 @@ static GIOStatus irssi_ssl_read(GIOChannel *handle, gchar *buf, gsize len, gsize static GIOStatus irssi_ssl_write(GIOChannel *handle, const gchar *buf, gsize len, gsize *ret, GError **gerr) { GIOSSLChannel *chan = (GIOSSLChannel *)handle; - gint err; + gint ret1, err; + const char *errstr; - err = SSL_write(chan->ssl, (const char *)buf, len); - if(err < 0) + ret1 = SSL_write(chan->ssl, (const char *)buf, len); + if(ret1 <= 0) { *ret = 0; - err = SSL_get_error(chan->ssl, err); + err = SSL_get_error(chan->ssl, ret1); if(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) return G_IO_STATUS_AGAIN; + else if(err == SSL_ERROR_ZERO_RETURN) + errstr = "server closed connection"; + else if (err == SSL_ERROR_SYSCALL) + { + errstr = ERR_reason_error_string(ERR_get_error()); + if (errstr == NULL && ret1 == -1) + errstr = strerror(errno); + if (errstr == NULL) + errstr = "server closed connection unexpectedly"; + } + else + { + errstr = ERR_reason_error_string(ERR_get_error()); + if (errstr == NULL) + errstr = "unknown SSL error"; + } + g_warning("SSL write error: %s", errstr); *gerr = g_error_new_literal(G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, - ERR_reason_error_string(ERR_get_error())); + errstr); return G_IO_STATUS_ERROR; } else { - *ret = err; + *ret = ret1; return G_IO_STATUS_NORMAL; } /*UNREACH*/ @@ -320,12 +356,25 @@ int irssi_ssl_handshake(GIOChannel *handle) ret = SSL_connect(chan->ssl); if (ret <= 0) { err = SSL_get_error(chan->ssl, ret); - if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { - errstr = ERR_reason_error_string(ERR_get_error()); - g_warning("SSL handshake failed: %s", errstr != NULL ? errstr : "server closed connection"); - return -1; + switch (err) { + case SSL_ERROR_WANT_READ: + return 1; + case SSL_ERROR_WANT_WRITE: + return 3; + case SSL_ERROR_ZERO_RETURN: + g_warning("SSL handshake failed: %s", "server closed connection"); + return -1; + case SSL_ERROR_SYSCALL: + errstr = ERR_reason_error_string(ERR_get_error()); + if (errstr == NULL && ret == -1) + errstr = strerror(errno); + g_warning("SSL handshake failed: %s", errstr != NULL ? errstr : "server closed connection unexpectedly"); + return -1; + default: + errstr = ERR_reason_error_string(ERR_get_error()); + g_warning("SSL handshake failed: %s", errstr != NULL ? errstr : "unknown SSL error"); + return -1; } - return err == SSL_ERROR_WANT_READ ? 1 : 3; } cert = SSL_get_peer_certificate(chan->ssl);