summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorLeorize <leorize+oss@disroot.org>2020-06-03 15:11:10 -0500
committerAndreas Rumpf <rumpf_a@web.de>2020-06-06 21:11:53 +0200
commit6cb94b5da6ac409915cc0ca3f50c50214edee0ef (patch)
treeec13cf8be68c3b9dc543aac813a978948a7c0e0e /lib
parentf243f9aeb5c5ef6f59efadbee81feb918a20fae8 (diff)
downloadNim-6cb94b5da6ac409915cc0ca3f50c50214edee0ef.tar.gz
asyncnet, net: clear openssl error queue before performing I/O
Per SSL_get_error(3):

  The current thread's error queue must be empty before the TLS/SSL I/O
  operation is attempted, or SSL_get_error() will not work reliably.

There has been records of not clearing the error queue causing weird SSL
errors when there shouldn't be any, see:

https://github.com/openssl/openssl/issues/11889
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/asyncnet.nim1
-rw-r--r--lib/pure/net.nim7
2 files changed, 8 insertions, 0 deletions
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index 8df839c14..bd9cd4312 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -718,6 +718,7 @@ proc close*(socket: AsyncSocket) =
         # established, see:
         # https://github.com/openssl/openssl/issues/710#issuecomment-253897666
         if SSL_in_init(socket.sslHandle) == 0:
+          ErrClearError()
           SSL_shutdown(socket.sslHandle)
         else:
           0
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index c60caab08..af66c3a15 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -752,12 +752,14 @@ when defineSsl:
         # Discard result in case OpenSSL version doesn't support SNI, or we're
         # not using TLSv1+
         discard SSL_set_tlsext_host_name(socket.sslHandle, hostname)
+      ErrClearError()
       let ret = SSL_connect(socket.sslHandle)
       socketError(socket, ret)
       when not defined(nimDisableCertificateValidation) and not defined(windows):
         if hostname.len > 0 and not isIpAddress(hostname):
           socket.checkCertName(hostname)
     of handshakeAsServer:
+      ErrClearError()
       let ret = SSL_accept(socket.sslHandle)
       socketError(socket, ret)
 
@@ -926,6 +928,7 @@ proc acceptAddr*(server: Socket, client: var owned(Socket), address: var string,
         # We must wrap the client sock in a ssl context.
 
         server.sslContext.wrapSocket(client)
+        ErrClearError()
         let ret = SSL_accept(client.sslHandle)
         socketError(client, ret, false)
 
@@ -955,6 +958,7 @@ when false: #defineSsl:
 
           if not client.isSsl or client.sslHandle == nil:
             server.sslContext.wrapSocket(client)
+          ErrClearError()
           let ret = SSL_accept(client.sslHandle)
           while ret <= 0:
             let err = SSL_get_error(client.sslHandle, ret)
@@ -1135,6 +1139,7 @@ proc uniRecv(socket: Socket, buffer: pointer, size, flags: cint): int =
   assert(not socket.isClosed, "Cannot `recv` on a closed socket")
   when defineSsl:
     if socket.isSsl:
+      ErrClearError()
       return SSL_read(socket.sslHandle, buffer, size)
 
   return recv(socket.fd, buffer, size, flags)
@@ -1484,6 +1489,7 @@ proc send*(socket: Socket, data: pointer, size: int): int {.
   assert(not socket.isClosed, "Cannot `send` on a closed socket")
   when defineSsl:
     if socket.isSsl:
+      ErrClearError()
       return SSL_write(socket.sslHandle, cast[cstring](data), size)
 
   when useWinVersion or defined(macosx):
@@ -1768,6 +1774,7 @@ proc connect*(socket: Socket, address: string,
         # not using TLSv1+
         discard SSL_set_tlsext_host_name(socket.sslHandle, address)
 
+      ErrClearError()
       let ret = SSL_connect(socket.sslHandle)
       socketError(socket, ret)
       when not defined(nimDisableCertificateValidation) and not defined(windows):