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