From 20315637aa5c6f018d868b7c3c26ca1b52d4cc65 Mon Sep 17 00:00:00 2001 From: alaviss Date: Wed, 29 Jul 2020 22:35:02 +0000 Subject: asyncnet, net: don't attempt SSL_shutdown if a fatal error occurred (#15066) * asyncnet, net: don't attempt SSL_shutdown if a fatal error occurred Per TLS standard and SSL_shutdown(3ssl). This should prevent errors coming from a close() after a bad event (ie. the other end of the pipe is closed before shutdown can be negotiated). Ref #9867 * tssl: try sending until an error occur * tssl: cleanup * tssl: actually run the test I forgot to make the test run :P * tssl: run the test on ARC, maybe then it'll be happy * tssl: turns off ARC, switch tlsEmulation on for freebsd * tssl: document why tlsEmulation is employed * net: move SafeDisconn handling logic to socketError --- lib/pure/asyncnet.nim | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'lib/pure/asyncnet.nim') diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 410310e29..9846f8999 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -123,6 +123,7 @@ type sslContext: SslContext bioIn: BIO bioOut: BIO + sslNoShutdown: bool domain: Domain sockType: SockType protocol: Protocol @@ -200,9 +201,10 @@ proc newAsyncSocket*(domain, sockType, protocol: cint, Protocol(protocol), buffered, inheritable) when defineSsl: - proc getSslError(handle: SslPtr, err: cint): cint = + proc getSslError(socket: AsyncSocket, err: cint): cint = + assert socket.isSsl assert err < 0 - var ret = SSL_get_error(handle, err.cint) + var ret = SSL_get_error(socket.sslHandle, err.cint) case ret of SSL_ERROR_ZERO_RETURN: raiseSSLError("TLS/SSL connection failed to initiate, socket closed prematurely.") @@ -213,6 +215,7 @@ when defineSsl: of SSL_ERROR_WANT_X509_LOOKUP: raiseSSLError("Function for x509 lookup has been called.") of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: + socket.sslNoShutdown = true raiseSSLError() else: raiseSSLError("Unknown Error") @@ -265,7 +268,7 @@ when defineSsl: # If the operation failed, try to see if SSL has some data to read # or write. if opResult < 0: - let err = getSslError(socket.sslHandle, opResult.cint) + let err = getSslError(socket, opResult.cint) let fut = appeaseSsl(socket, flags, err.cint) yield fut if not fut.read(): @@ -718,7 +721,7 @@ proc close*(socket: AsyncSocket) = # Don't call SSL_shutdown if the connection has not been fully # established, see: # https://github.com/openssl/openssl/issues/710#issuecomment-253897666 - if SSL_in_init(socket.sslHandle) == 0: + if not socket.sslNoShutdown and SSL_in_init(socket.sslHandle) == 0: ErrClearError() SSL_shutdown(socket.sslHandle) else: @@ -747,6 +750,8 @@ when defineSsl: socket.bioOut = bioNew(bioSMem()) sslSetBio(socket.sslHandle, socket.bioIn, socket.bioOut) + socket.sslNoShutdown = true + proc wrapConnectedSocket*(ctx: SslContext, socket: AsyncSocket, handshake: SslHandshakeType, hostname: string = "") = -- cgit 1.4.1-2-gfad0