thttpclient_ssl.nim 4.3 KB

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