thttpclient_ssl.nim 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. discard """
  2. cmd: "nim $target --mm:refc -d:ssl $options $file"
  3. disabled: "openbsd"
  4. """
  5. # Nim - Basic SSL integration tests
  6. # (c) Copyright 2018 Nim contributors
  7. #
  8. # See the file "copying.txt", included in this
  9. # distribution, for details about the copyright.
  10. #
  11. ## Warning: this test performs local networking.
  12. ## Test with:
  13. ## ./bin/nim c -d:ssl -p:. --threads:on -r tests/stdlib/thttpclient_ssl.nim
  14. from stdtest/testutils import disableSSLTesting
  15. when not defined(windows) and not disableSSLTesting():
  16. # Disabled on Windows due to old OpenSSL version
  17. import std/[formatfloat, syncio]
  18. import
  19. httpclient,
  20. net,
  21. openssl,
  22. os,
  23. strutils,
  24. threadpool,
  25. times,
  26. unittest
  27. # bogus self-signed certificate
  28. const
  29. certFile = "tests/stdlib/thttpclient_ssl_cert.pem"
  30. keyFile = "tests/stdlib/thttpclient_ssl_key.pem"
  31. proc log(msg: string) =
  32. when defined(ssldebug):
  33. echo " [" & $epochTime() & "] " & msg
  34. # FIXME
  35. echo " [" & $epochTime() & "] " & msg
  36. discard
  37. proc runServer(port: Port): bool {.thread.} =
  38. ## Run a trivial HTTPS server in a {.thread.}
  39. ## Exit after serving one request
  40. var socket = newSocket()
  41. socket.setSockOpt(OptReusePort, true)
  42. socket.bindAddr(port)
  43. var ctx = newContext(certFile=certFile, keyFile=keyFile)
  44. ## Handle one connection
  45. socket.listen()
  46. var client: Socket
  47. var address = ""
  48. log "server: ready"
  49. socket.acceptAddr(client, address)
  50. log "server: incoming connection"
  51. var ssl: SslPtr = SSL_new(ctx.context)
  52. discard SSL_set_fd(ssl, client.getFd())
  53. log "server: accepting connection"
  54. ErrClearError()
  55. if SSL_accept(ssl) <= 0:
  56. ERR_print_errors_fp(stderr)
  57. else:
  58. const reply = "HTTP/1.0 200 OK\r\nServer: test\r\nContent-type: text/html\r\nContent-Length: 0\r\n\r\n"
  59. log "server: sending reply"
  60. discard SSL_write(ssl, reply.cstring, reply.len)
  61. log "server: receiving a line"
  62. let line = client.recvLine()
  63. log "server: received $# bytes" % $line.len
  64. log "closing"
  65. SSL_free(ssl)
  66. close(client)
  67. close(socket)
  68. log "server: exited"
  69. suite "SSL self signed certificate check":
  70. test "TCP socket":
  71. const port = 12347.Port
  72. let t = spawn runServer(port)
  73. sleep(100)
  74. var sock = newSocket()
  75. var ctx = newContext()
  76. ctx.wrapSocket(sock)
  77. try:
  78. log "client: connect"
  79. sock.connect("127.0.0.1", port)
  80. fail()
  81. except:
  82. let msg = getCurrentExceptionMsg()
  83. check(msg.contains("certificate verify failed"))
  84. test "HttpClient default: no check":
  85. const port = 12345.Port
  86. let t = spawn runServer(port)
  87. sleep(100)
  88. var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyNone))
  89. try:
  90. log "client: connect"
  91. discard client.getContent("https://127.0.0.1:12345")
  92. except:
  93. let msg = getCurrentExceptionMsg()
  94. log "client: unexpected exception: " & msg
  95. fail()
  96. test "HttpClient with CVerifyPeer":
  97. const port = 12346.Port
  98. let t = spawn runServer(port)
  99. sleep(100)
  100. var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyPeer))
  101. try:
  102. log "client: connect"
  103. discard client.getContent("https://127.0.0.1:12346")
  104. log "getContent should have raised an exception"
  105. fail()
  106. except:
  107. let msg = getCurrentExceptionMsg()
  108. log "client: exception: " & msg
  109. # SSL_shutdown:shutdown while in init
  110. if not (msg.contains("alert number 48") or
  111. msg.contains("certificate verify failed")):
  112. echo "CVerifyPeer exception: " & msg
  113. check(false)
  114. test "HttpClient with CVerifyPeerUseEnvVars":
  115. const port = 12346.Port
  116. let t = spawn runServer(port)
  117. sleep(100)
  118. putEnv("SSL_CERT_FILE", getCurrentDir() / certFile)
  119. var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyPeerUseEnvVars))
  120. try:
  121. log "client: connect"
  122. discard client.getContent("https://127.0.0.1:12346")
  123. except:
  124. let msg = getCurrentExceptionMsg()
  125. log "client: exception: " & msg
  126. log "getContent should not have raised an exception"
  127. fail()