nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.58k stars 1.47k forks source link

asyncnet crashes with OpenSSL 1.0.x #11384

Open Dankr4d opened 5 years ago

Dankr4d commented 5 years ago

Asyncnet crashes with OpenSSL 1.0.x (OpenSSL 1.0.x works fine with net module). When sniffing with wireshark it seems, that no handshake is done but the server/client are already reading/sending data. I've also get an SSL_ERROR_SSL when printing SSLGetError result in asyncnet's getSslError function.

Example Server

{.passL: "-Lopenssl-1.0.2s -lcrypto -lssl".}

import asyncnet, asyncdispatch, net

proc handle(client: AsyncSocket) {.async.} =
  var line: string
  while true:
    line = await client.recvLine()
    echo "Line: ", line
    if line == "":
      echo "client disconnected"
      if not client.isClosed:
        client.close()
      break

proc main() {.async.} =
  var ctx: SslContext = newContext(certFile = "publicKey.pem", keyFile = "secretKey.pem")
  var server: AsyncSocket = newAsyncSocket()
  server.setSockOpt(OptReuseAddr, true)
  server.setSockOpt(OptReusePort, true)
  server.bindAddr(Port(9000))
  server.listen()
  while true:
    var (address, client) = await server.acceptAddr()
    echo "connection from: ", address
    wrapConnectedSocket(ctx, client, handshakeAsServer)
    asyncCheck client.handle()

waitFor main()

Example Client

{.passL: "-Lopenssl-1.0.2s -lcrypto -lssl".}

import asyncnet, asyncdispatch, net

proc handle(client: AsyncSocket) {.async.} =
  ## We speek to the ssl server.
  while true:
    await client.send("TEST\n")
    await sleepAsync(1000)

proc main() {.async.} =
  var ctx: SslContext = newContext(verifyMode = CVerifyNone)
  var client: AsyncSocket = newAsyncSocket()
  wrapSocket(ctx, client)
  await client.connect("127.0.0.1", Port(9000))
  await client.handle()

waitFor main()

Compiling and start server: nim c -d:ssl -d:openssl10 --dynlibOverride:ssl asyncSsl10Bug.nim; LD_LIBRARY_PATH=openssl-1.0.2s ./asyncSsl10Bug Compiling and start client: nim c -d:ssl -d:openssl10 --dynlibOverride:ssl asyncSsl10BugCli.nim; LD_LIBRARY_PATH=openssl-1.0.2s ./asyncSsl10BugCli

Output server

connection from: 127.0.0.1
asyncSsl10Bug.nim(29)    asyncSsl10Bug
asyncdispatch.nim(1839)  waitFor
asyncdispatch.nim(1533)  poll
asyncdispatch.nim(1299)  runOnce
asyncdispatch.nim(210)   processPendingCallbacks
asyncmacro.nim(34)       main_continue
asyncSsl10Bug.nim(27)    mainIter
asyncmacro.nim(311)      handle
asyncmacro.nim(34)       handle_continue
asyncSsl10Bug.nim(8)     handleIter
asyncmacro.nim(311)      recvLine
asyncmacro.nim(34)       recvLine_continue
asyncnet.nim(606)        recvLineIter
asyncmacro.nim(311)      recvLineInto
asyncmacro.nim(37)       recvLineInto_continue
asyncnet.nim(258)        recvLineIntoIter
asyncnet.nim(207)        getSslError
net.nim(461)             raiseSSLError
[[reraised from:
asyncSsl10Bug.nim(29)    asyncSsl10Bug
asyncdispatch.nim(1839)  waitFor
asyncdispatch.nim(1533)  poll
asyncdispatch.nim(1299)  runOnce
asyncdispatch.nim(210)   processPendingCallbacks
asyncmacro.nim(34)       main_continue
asyncSsl10Bug.nim(27)    mainIter
asyncmacro.nim(311)      handle
asyncmacro.nim(34)       handle_continue
asyncSsl10Bug.nim(8)     handleIter
asyncmacro.nim(311)      recvLine
asyncmacro.nim(37)       recvLine_continue
asyncnet.nim(606)        recvLineIter
asyncfutures.nim(353)    read
]]
[[reraised from:
asyncSsl10Bug.nim(29)    asyncSsl10Bug
asyncdispatch.nim(1839)  waitFor
asyncdispatch.nim(1533)  poll
asyncdispatch.nim(1299)  runOnce
asyncdispatch.nim(210)   processPendingCallbacks
asyncmacro.nim(34)       main_continue
asyncSsl10Bug.nim(27)    mainIter
asyncmacro.nim(311)      handle
asyncmacro.nim(37)       handle_continue
asyncSsl10Bug.nim(8)     handleIter
asyncfutures.nim(353)    read
]]
[[reraised from:
asyncSsl10Bug.nim(29)    asyncSsl10Bug
asyncdispatch.nim(1839)  waitFor
asyncdispatch.nim(1533)  poll
asyncdispatch.nim(1299)  runOnce
asyncdispatch.nim(210)   processPendingCallbacks
asyncfutures.nim(400)    :anonymous
]]
Error: unhandled exception: No error reported.
Async traceback:
  asyncSsl10Bug.nim(29)   asyncSsl10Bug
  asyncdispatch.nim(1839) waitFor
  asyncdispatch.nim(1533) poll
    ## Processes asynchronous completion events
  asyncdispatch.nim(1299) runOnce
  asyncdispatch.nim(210)  processPendingCallbacks
    ## Executes pending callbacks
  asyncmacro.nim(34)      main_continue
    ## Resumes an async procedure
  asyncSsl10Bug.nim(27)   mainIter
  asyncmacro.nim(311)     handle
  asyncmacro.nim(34)      handle_continue
    ## Resumes an async procedure
  asyncSsl10Bug.nim(8)    handleIter
  asyncmacro.nim(311)     recvLine
  asyncmacro.nim(34)      recvLine_continue
    ## Resumes an async procedure
  asyncnet.nim(606)       recvLineIter
  asyncmacro.nim(311)     recvLineInto
  asyncmacro.nim(37)      recvLineInto_continue
    ## Resumes an async procedure
  asyncnet.nim(258)       recvLineIntoIter
  asyncnet.nim(207)       getSslError
  net.nim(461)            raiseSSLError
  #[
    asyncSsl10Bug.nim(29)   asyncSsl10Bug
    asyncdispatch.nim(1839) waitFor
    asyncdispatch.nim(1533) poll
      ## Processes asynchronous completion events
    asyncdispatch.nim(1299) runOnce
    asyncdispatch.nim(210)  processPendingCallbacks
      ## Executes pending callbacks
    asyncmacro.nim(34)      main_continue
      ## Resumes an async procedure
    asyncSsl10Bug.nim(27)   mainIter
    asyncmacro.nim(311)     handle
    asyncmacro.nim(34)      handle_continue
      ## Resumes an async procedure
    asyncSsl10Bug.nim(8)    handleIter
    asyncmacro.nim(311)     recvLine
    asyncmacro.nim(37)      recvLine_continue
      ## Resumes an async procedure
    asyncnet.nim(606)       recvLineIter
    asyncfutures.nim(353)   read
  ]#
  #[
    asyncSsl10Bug.nim(29)   asyncSsl10Bug
    asyncdispatch.nim(1839) waitFor
    asyncdispatch.nim(1533) poll
      ## Processes asynchronous completion events
    asyncdispatch.nim(1299) runOnce
    asyncdispatch.nim(210)  processPendingCallbacks
      ## Executes pending callbacks
    asyncmacro.nim(34)      main_continue
      ## Resumes an async procedure
    asyncSsl10Bug.nim(27)   mainIter
    asyncmacro.nim(311)     handle
    asyncmacro.nim(37)      handle_continue
      ## Resumes an async procedure
    asyncSsl10Bug.nim(8)    handleIter
    asyncfutures.nim(353)   read
  ]#
Exception message: No error reported.

Output client

asyncSsl10BugCli.nim(18) asyncSsl10BugCli
asyncdispatch.nim(1839)  waitFor
asyncdispatch.nim(1533)  poll
asyncdispatch.nim(1299)  runOnce
asyncdispatch.nim(210)   processPendingCallbacks
asyncmacro.nim(37)       connect_continue
asyncnet.nim(258)        connectIter
asyncnet.nim(207)        getSslError
net.nim(461)             raiseSSLError
[[reraised from:
asyncSsl10BugCli.nim(18) asyncSsl10BugCli
asyncdispatch.nim(1839)  waitFor
asyncdispatch.nim(1533)  poll
asyncdispatch.nim(1299)  runOnce
asyncdispatch.nim(210)   processPendingCallbacks
asyncmacro.nim(34)       main_continue
asyncSsl10BugCli.nim(15) mainIter
asyncfutures.nim(353)    read
]]
[[reraised from:
asyncSsl10BugCli.nim(18) asyncSsl10BugCli
asyncdispatch.nim(1841)  waitFor
asyncfutures.nim(353)    read
]]
Error: unhandled exception: No error reported.
Async traceback:
  asyncSsl10BugCli.nim(18) asyncSsl10BugCli
  asyncdispatch.nim(1839)  waitFor
  asyncdispatch.nim(1533)  poll
    ## Processes asynchronous completion events
  asyncdispatch.nim(1299)  runOnce
  asyncdispatch.nim(210)   processPendingCallbacks
    ## Executes pending callbacks
  asyncmacro.nim(37)       connect_continue
    ## Resumes an async procedure
  asyncnet.nim(258)        connectIter
  asyncnet.nim(207)        getSslError
  net.nim(461)             raiseSSLError
  #[
    asyncSsl10BugCli.nim(18) asyncSsl10BugCli
    asyncdispatch.nim(1839)  waitFor
    asyncdispatch.nim(1533)  poll
      ## Processes asynchronous completion events
    asyncdispatch.nim(1299)  runOnce
    asyncdispatch.nim(210)   processPendingCallbacks
      ## Executes pending callbacks
    asyncmacro.nim(34)       main_continue
      ## Resumes an async procedure
    asyncSsl10BugCli.nim(15) mainIter
    asyncfutures.nim(353)    read
  ]#
Exception message: No error reported.

Additional Information

$ nim -v
Nim Compiler Version 0.19.9 [Linux: amd64]
Compiled at 2019-06-02
Copyright (c) 2006-2019 by Andreas Rumpf

git hash: d67a9f024eeeb2bc26fb38a98be9a53956003290
active boot switches: -d:release
dom96 commented 5 years ago

Just asyncnet or net as well?

Dankr4d commented 5 years ago

It's just asyncnet! The net modul works fine with OpenSSL 1.0.x. Momently as a workaround I'm working with the net module and threads for my project. Please let me know if I can help in any case to fix this problem!

dom96 commented 5 years ago

If you're feeling adventurous you can try digging into the asyncnet source code to try and figure out why this crash happens. It's likely that we are simply calling OpenSSL functions incorrectly and/or need to call some new functions.