thttpclient_ssl.nim 4.1 KB

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