1 //
2 // Copyright 2018 Capitar IT Group BV <info@capitar.com>
3 // Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
4 //
5 // This software is supplied under the terms of the MIT License, a
6 // copy of which should be located in the distribution where this
7 // file was obtained (LICENSE.txt).  A copy of the license may also be
8 // found online at https://opensource.org/licenses/MIT.
9 //
10 
11 // TLS tests.
12 
13 #ifndef _WIN32
14 #include <arpa/inet.h>
15 #endif
16 
17 #include <nng/nng.h>
18 #include <nng/protocol/pair1/pair.h>
19 #include <nng/supplemental/tls/tls.h>
20 #include <nng/transport/tls/tls.h>
21 
22 #include "convey.h"
23 #include "stubs.h"
24 #include "trantest.h"
25 
26 // These keys are for demonstration purposes ONLY.  DO NOT USE.
27 // The certificate is valid for 100 years, because I don't want to
28 // have to regenerate it ever again. The CN is 127.0.0.1, and self-signed.
29 //
30 
31 static const char cert[] =
32     "-----BEGIN CERTIFICATE-----\n"
33     "MIIDRzCCAi8CFCOIJGs6plMawgBYdDuCRV7UuJuyMA0GCSqGSIb3DQEBCwUAMF8x\n"
34     "CzAJBgNVBAYTAlhYMQ8wDQYDVQQIDAZVdG9waWExETAPBgNVBAcMCFBhcmFkaXNl\n"
35     "MRgwFgYDVQQKDA9OTkcgVGVzdHMsIEluYy4xEjAQBgNVBAMMCWxvY2FsaG9zdDAg\n"
36     "Fw0yMDA1MjMyMzMxMTlaGA8yMTIwMDQyOTIzMzExOVowXzELMAkGA1UEBhMCWFgx\n"
37     "DzANBgNVBAgMBlV0b3BpYTERMA8GA1UEBwwIUGFyYWRpc2UxGDAWBgNVBAoMD05O\n"
38     "RyBUZXN0cywgSW5jLjESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0B\n"
39     "AQEFAAOCAQ8AMIIBCgKCAQEAyPdnRbMrQj9902TGQsmMbG6xTSl9XKbJr55BcnyZ\n"
40     "ifsrqA7BbNSkndVw9Qq+OJQIDBTfRhGdG+o9j3h6SDVvIb62fWtwJ5Fe0eUmeYwP\n"
41     "c1PKQzOmMFlMYekXiZsx60yu5LeuUhGlb84+csImH+m3NbutInPJcStSq0WfSV6V\n"
42     "Nk6DN3535ex66zV2Ms6ikys1vCC434YqIpe1VxUh+IC2widJcLDCxmmJt3TOlx5f\n"
43     "9OcKMkxuH4fMAzgjIEpIrUjdb19CGNVvsNrEEB2CShBMgBdqMaAnKFxpKgfzS0JF\n"
44     "ulxRGNtpsrweki+j+a4sJXTv40kELkRQS6uB6wWZNjcPywIDAQABMA0GCSqGSIb3\n"
45     "DQEBCwUAA4IBAQA86Fqrd4aiih6R3fwiMLwV6IQJv+u5rQeqA4D0xu6v6siP42SJ\n"
46     "YMaI2DkNGrWdSFVSHUK/efceCrhnMlW7VM8I1cyl2F/qKMfnT72cxqqquiKtQKdT\n"
47     "NDTzv61QMUP9n86HxMzGS7jg0Pknu55BsIRNK6ndDvI3D/K/rzZs4xbqWSSfNfQs\n"
48     "fNFBbOuDrkS6/1h3p8SY1uPM18WLVv3GO2T3aeNMHn7YJAKSn+sfaxzAPyPIK3UT\n"
49     "W8ecGQSHOqBJJQELyUfMu7lx/FCYKUhN7/1uhU5Qf1pCR8hkIMegtqr64yVBNMOn\n"
50     "248fuiHbs9BRknuA/PqjxIDDZTwtDrfVSO/S\n"
51     "-----END CERTIFICATE-----\n";
52 
53 static const char key[] =
54     "-----BEGIN RSA PRIVATE KEY-----\n"
55     "MIIEowIBAAKCAQEAyPdnRbMrQj9902TGQsmMbG6xTSl9XKbJr55BcnyZifsrqA7B\n"
56     "bNSkndVw9Qq+OJQIDBTfRhGdG+o9j3h6SDVvIb62fWtwJ5Fe0eUmeYwPc1PKQzOm\n"
57     "MFlMYekXiZsx60yu5LeuUhGlb84+csImH+m3NbutInPJcStSq0WfSV6VNk6DN353\n"
58     "5ex66zV2Ms6ikys1vCC434YqIpe1VxUh+IC2widJcLDCxmmJt3TOlx5f9OcKMkxu\n"
59     "H4fMAzgjIEpIrUjdb19CGNVvsNrEEB2CShBMgBdqMaAnKFxpKgfzS0JFulxRGNtp\n"
60     "srweki+j+a4sJXTv40kELkRQS6uB6wWZNjcPywIDAQABAoIBAQCGSUsot+BgFCzv\n"
61     "5JbWafb7Pbwb421xS8HZJ9Zzue6e1McHNVTqc+zLyqQAGX2iMMhvykKnf32L+anJ\n"
62     "BKgxOANaeSVYCUKYLfs+JfDfp0druMGexhR2mjT/99FSkfF5WXREQLiq/j+dxiLU\n"
63     "bActq+5QaWf3bYddp6VF7O/TBvCNqBfD0+S0o0wtBdvxXItrKPTD5iKr9JfLWdAt\n"
64     "YNAk2QgFywFtY5zc2wt4queghF9GHeBzzZCuVj9QvPA4WdVq0mePaPTmvTYQUD0j\n"
65     "GT6X5j9JhqCwfh7trb/HfkmLHwwc62zPDFps+Dxao80+vss5b/EYZ4zY3S/K3vpG\n"
66     "f/e42S2BAoGBAP51HQYFJGC/wsNtOcX8RtXnRo8eYmyboH6MtBFrZxWl6ERigKCN\n"
67     "5Tjni7EI3nwi3ONg0ENPFkoQ8h0bcVFS7iW5kz5te73WaOFtpkU9rmuFDUz37eLP\n"
68     "d+JLZ5Kwfn2FM9HoiSAZAHowE0MIlmmIEXSnFtqA2zzorPQLO/4QlR+VAoGBAMov\n"
69     "R0yaHg3qPlxmCNyLXKiGaGNzvsvWjYw825uCGmVZfhzDhOiCFMaMb51BS5Uw/gwm\n"
70     "zHxmJjoqak8JjxaQ1qKPoeY1TJ5ps1+TRq9Wzm2/zGqJHOXnRPlqwBQ6AFllAMgt\n"
71     "Rlp5uqb8QJ+YEo6/1kdGhw9kZWCZEEue6MNQjxnfAoGARLkUkZ+p54di7qz9QX+V\n"
72     "EghYgibOpk6R1hviNiIvwSUByhZgbvxjwC6pB7NBg31W8wIevU8K0g4plbrnq/Md\n"
73     "5opsPhwLo4XY5albkq/J/7f7k6ISWYN2+WMsIe4Q+42SJUsMXeLiwh1h1mTnWrEp\n"
74     "JbxK69CJZbXhoDe4iDGqVNECgYAjlgS3n9ywWE1XmAHxR3osk1OmRYYMfJv3VfLV\n"
75     "QSYCNqkyyNsIzXR4qdkvVYHHJZNhcibFsnkB/dsuRCFyOFX+0McPLMxqiXIv3U0w\n"
76     "qVe2C28gRTfX40fJmpdqN/c9xMBJe2aJoClRIM8DCBIkG/HMI8a719DcGrS6iqKv\n"
77     "VeuKAwKBgEgD+KWW1KtoSjCBlS0NP8HjC/Rq7j99YhKE6b9h2slIa7JTO8RZKCa0\n"
78     "qbuomdUeJA3R8h+5CFkEKWqO2/0+dUdLNOjG+CaTFHaUJevzHOzIjpn+VsfCLV13\n"
79     "yupGzHG+tGtdrWgLn9Dzdp67cDfSnsSh+KODPECAAFfo+wPvD8DS\n"
80     "-----END RSA PRIVATE KEY-----\n";
81 
82 static int
check_props_v4(nng_msg * msg)83 check_props_v4(nng_msg *msg)
84 {
85 	nng_pipe     p;
86 	size_t       z;
87 	bool         b;
88 	nng_sockaddr la;
89 	nng_sockaddr ra;
90 
91 	p = nng_msg_get_pipe(msg);
92 	So(nng_pipe_id(p) > 0);
93 
94 	// Typed access
95 	So(nng_pipe_getopt_sockaddr(p, NNG_OPT_LOCADDR, &la) == 0);
96 	So(la.s_family == NNG_AF_INET);
97 	So(la.s_in.sa_port == htons(trantest_port - 1));
98 	So(la.s_in.sa_port != 0);
99 	So(la.s_in.sa_addr == htonl(0x7f000001));
100 
101 	// Untyped access
102 	z = sizeof(nng_sockaddr);
103 	So(nng_pipe_getopt(p, NNG_OPT_REMADDR, &ra, &z) == 0);
104 	So(z == sizeof(ra));
105 	So(ra.s_family == NNG_AF_INET);
106 	So(ra.s_in.sa_port != 0);
107 	So(ra.s_in.sa_addr == htonl(0x7f000001));
108 
109 	So(nng_pipe_getopt_bool(p, NNG_OPT_TCP_KEEPALIVE, &b) == 0);
110 	So(b == false); // default
111 
112 	So(nng_pipe_getopt_bool(p, NNG_OPT_TCP_NODELAY, &b) == 0);
113 	So(b == true); // default
114 
115 	// Check for type enforcement
116 	int i;
117 	So(nng_pipe_getopt_int(p, NNG_OPT_REMADDR, &i) == NNG_EBADTYPE);
118 
119 	z = 1;
120 	So(nng_pipe_getopt(p, NNG_OPT_REMADDR, &ra, &z) == NNG_EINVAL);
121 
122 	return (0);
123 }
124 
125 static int
init_dialer_tls_ex(nng_dialer d,bool own_cert)126 init_dialer_tls_ex(nng_dialer d, bool own_cert)
127 {
128 	nng_tls_config *cfg;
129 	int             rv;
130 
131 	if ((rv = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_CLIENT)) != 0) {
132 		return (rv);
133 	}
134 
135 	if ((rv = nng_tls_config_ca_chain(cfg, cert, NULL)) != 0) {
136 		goto out;
137 	}
138 
139 	if ((rv = nng_tls_config_server_name(cfg, "localhost")) != 0) {
140 		goto out;
141 	}
142 	nng_tls_config_auth_mode(cfg, NNG_TLS_AUTH_MODE_REQUIRED);
143 
144 	if (own_cert) {
145 		if ((rv = nng_tls_config_own_cert(cfg, cert, key, NULL)) !=
146 		    0) {
147 			goto out;
148 		}
149 	}
150 
151 	rv = nng_dialer_setopt_ptr(d, NNG_OPT_TLS_CONFIG, cfg);
152 
153 out:
154 	nng_tls_config_free(cfg);
155 	return (rv);
156 }
157 
158 static int
init_dialer_tls(nng_dialer d)159 init_dialer_tls(nng_dialer d)
160 {
161 	return (init_dialer_tls_ex(d, false));
162 }
163 
164 static int
init_listener_tls_ex(nng_listener l,int auth_mode)165 init_listener_tls_ex(nng_listener l, int auth_mode)
166 {
167 	nng_tls_config *cfg;
168 	int             rv;
169 
170 	if ((rv = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_SERVER)) != 0) {
171 		return (rv);
172 	}
173 	if ((rv = nng_tls_config_own_cert(cfg, cert, key, NULL)) != 0) {
174 		goto out;
175 	}
176 	if ((rv = nng_listener_setopt_ptr(l, NNG_OPT_TLS_CONFIG, cfg)) != 0) {
177 		goto out;
178 	}
179 	switch (auth_mode) {
180 	case NNG_TLS_AUTH_MODE_REQUIRED:
181 	case NNG_TLS_AUTH_MODE_OPTIONAL:
182 		if ((rv = nng_tls_config_ca_chain(cfg, cert, NULL)) != 0) {
183 			goto out;
184 		}
185 		break;
186 	default:
187 		break;
188 	}
189 	if ((rv = nng_tls_config_auth_mode(cfg, auth_mode)) != 0) {
190 		goto out;
191 	}
192 out:
193 	nng_tls_config_free(cfg);
194 	return (0);
195 }
196 
197 static int
init_listener_tls(nng_listener l)198 init_listener_tls(nng_listener l)
199 {
200 	return (init_listener_tls_ex(l, NNG_TLS_AUTH_MODE_NONE));
201 }
202 
203 static int
init_dialer_tls_file(nng_dialer d)204 init_dialer_tls_file(nng_dialer d)
205 {
206 	int   rv;
207 	char *tmpdir;
208 	char *pth;
209 
210 	if ((tmpdir = nni_plat_temp_dir()) == NULL) {
211 		return (NNG_ENOTSUP);
212 	}
213 	if ((pth = nni_file_join(tmpdir, "tls_test_cacert.pem")) == NULL) {
214 		nni_strfree(tmpdir);
215 		return (NNG_ENOMEM);
216 	}
217 	nni_strfree(tmpdir);
218 
219 	if ((rv = nni_file_put(pth, cert, strlen(cert))) != 0) {
220 		nni_strfree(pth);
221 		return (rv);
222 	}
223 
224 	rv = nng_dialer_setopt_string(d, NNG_OPT_TLS_CA_FILE, pth);
225 	nni_file_delete(pth);
226 	nni_strfree(pth);
227 
228 	return (rv);
229 }
230 
231 static int
init_listener_tls_file(nng_listener l)232 init_listener_tls_file(nng_listener l)
233 {
234 	int   rv;
235 	char *tmpdir;
236 	char *pth;
237 	char *certkey;
238 
239 	if ((tmpdir = nni_plat_temp_dir()) == NULL) {
240 		return (NNG_ENOTSUP);
241 	}
242 
243 	if ((pth = nni_file_join(tmpdir, "tls_test_certkey.pem")) == NULL) {
244 		nni_strfree(tmpdir);
245 		return (NNG_ENOMEM);
246 	}
247 	nni_strfree(tmpdir);
248 
249 	if ((rv = nni_asprintf(&certkey, "%s\r\n%s\r\n", cert, key)) != 0) {
250 		nni_strfree(pth);
251 		return (rv);
252 	}
253 
254 	rv = nni_file_put(pth, certkey, strlen(certkey));
255 	nni_strfree(certkey);
256 	if (rv != 0) {
257 		nni_strfree(pth);
258 		return (rv);
259 	}
260 
261 	rv = nng_listener_setopt_string(l, NNG_OPT_TLS_CERT_KEY_FILE, pth);
262 	if (rv != 0) {
263 		// We can wind up with EBUSY from the server already
264 		// running.
265 		if (rv == NNG_EBUSY) {
266 			rv = 0;
267 		}
268 	}
269 
270 	nni_file_delete(pth);
271 	nni_strfree(pth);
272 	return (rv);
273 }
274 
275 TestMain("TLS Transport", {
276 	static trantest tt;
277 
278 	if (strcmp(nng_tls_engine_name(), "none") == 0) {
279 		Skip("TLS not enabled");
280 	}
281 
282 	tt.dialer_init   = init_dialer_tls;
283 	tt.listener_init = init_listener_tls;
284 	tt.tmpl          = "tls+tcp://127.0.0.1:%u";
285 	tt.proptest      = check_props_v4;
286 
287 	trantest_test(&tt);
288 
289 	Convey("We can register the TLS transport",
290 	    { So(nng_tls_register() == 0); });
291 
292 	Convey("We cannot connect to wild cards", {
293 		nng_socket s;
294 		char       addr[NNG_MAXADDRLEN];
295 
296 		So(nng_tls_register() == 0);
297 		So(nng_pair_open(&s) == 0);
298 		Reset({ nng_close(s); });
299 		trantest_next_address(addr, "tls+tcp://*:%u");
300 		So(nng_dial(s, addr, NULL, 0) == NNG_EADDRINVAL);
301 	});
302 
303 	Convey("We can bind to wild card", {
304 		nng_socket   s1;
305 		nng_socket   s2;
306 		char         addr[NNG_MAXADDRLEN];
307 		nng_listener l;
308 		nng_dialer   d;
309 
310 		So(nng_tls_register() == 0);
311 		So(nng_pair_open(&s1) == 0);
312 		So(nng_pair_open(&s2) == 0);
313 		Reset({
314 			nng_close(s2);
315 			nng_close(s1);
316 		});
317 		trantest_next_address(addr, "tls+tcp://*:%u");
318 		So(nng_listener_create(&l, s1, addr) == 0);
319 		So(init_listener_tls(l) == 0);
320 		// reset port back one
321 		trantest_prev_address(addr, "tls+tcp://127.0.0.1:%u");
322 		So(nng_dialer_create(&d, s2, addr) == 0);
323 		So(init_dialer_tls(d) == 0);
324 		So(nng_dialer_setopt_int(
325 		       d, NNG_OPT_TLS_AUTH_MODE, NNG_TLS_AUTH_MODE_NONE) == 0);
326 		So(nng_listener_start(l, 0) == 0);
327 		So(nng_dialer_start(d, 0) == 0);
328 	});
329 
330 	SkipConvey("We can bind to port zero", {
331 		nng_socket   s1;
332 		nng_socket   s2;
333 		nng_listener l;
334 		nng_dialer   d;
335 		char *       addr;
336 
337 		So(nng_tls_register() == 0);
338 		So(nng_pair_open(&s1) == 0);
339 		So(nng_pair_open(&s2) == 0);
340 		Reset({
341 			nng_close(s2);
342 			nng_close(s1);
343 		});
344 		So(nng_listener_create(&l, s1, "tls+tcp://127.0.0.1:0") == 0);
345 		So(init_listener_tls(l) == 0);
346 		So(nng_listener_start(l, 0) == 0);
347 		So(nng_listener_getopt_string(l, NNG_OPT_URL, &addr) == 0);
348 		So(nng_dialer_create(&d, s2, addr) == 0);
349 		So(init_dialer_tls(d) == 0);
350 		So(nng_dialer_setopt_int(
351 		       d, NNG_OPT_TLS_AUTH_MODE, NNG_TLS_AUTH_MODE_NONE) == 0);
352 		So(nng_dialer_start(d, 0) == 0);
353 		nng_strfree(addr);
354 	});
355 
356 	Convey("Malformed TLS addresses do not panic", {
357 		nng_socket s1;
358 
359 		So(nng_tls_register() == 0);
360 		So(nng_pair_open(&s1) == 0);
361 		Reset({ nng_close(s1); });
362 
363 		// Note that if we listen to an unspecified port, then we
364 		// get a random port.  So we don't look at that.  This allows
365 		// a user to obtain a port at random and then query to see
366 		// which one was chosen.
367 
368 		So(nng_dial(s1, "tls+tcp://127.0.0.1", NULL, 0) ==
369 		    NNG_EADDRINVAL);
370 		So(nng_dial(s1, "tls+tcp://127.0.0.1.32", NULL, 0) ==
371 		    NNG_EADDRINVAL);
372 		So(nng_dial(s1, "tls+tcp://127.0.x.1.32", NULL, 0) ==
373 		    NNG_EADDRINVAL);
374 		So(nng_listen(s1, "tls+tcp://127.0.0.1.32", NULL, 0) ==
375 		    NNG_EADDRINVAL);
376 		So(nng_listen(s1, "tls+tcp://127.0.x.1.32", NULL, 0) ==
377 		    NNG_EADDRINVAL);
378 	});
379 
380 	Convey("We can use local interface to connect", {
381 		nng_socket   s1;
382 		nng_socket   s2;
383 		nng_listener l;
384 		nng_dialer   d;
385 		char         addr[NNG_MAXADDRLEN];
386 
387 		So(nng_pair_open(&s1) == 0);
388 		So(nng_pair_open(&s2) == 0);
389 		Reset({
390 			nng_close(s2);
391 			nng_close(s1);
392 		});
393 		trantest_next_address(addr, "tls+tcp://127.0.0.1:%u");
394 		So(nng_listener_create(&l, s1, addr) == 0);
395 		So(init_listener_tls(l) == 0);
396 		So(nng_listener_start(l, 0) == 0);
397 		// reset port back one
398 		trantest_prev_address(
399 		    addr, "tls+tcp://127.0.0.1;127.0.0.1:%u");
400 		So(nng_dialer_create(&d, s2, addr) == 0);
401 		So(init_dialer_tls(d) == 0);
402 		So(nng_dialer_start(d, 0) == 0);
403 	});
404 
405 	Convey("Botched local interfaces fail reasonably", {
406 		nng_socket s1;
407 
408 		So(nng_pair_open(&s1) == 0);
409 		Reset({ nng_close(s1); });
410 		So(nng_dial(s1, "tcp://1x.2;127.0.0.1:80", NULL, 0) ==
411 		    NNG_EADDRINVAL);
412 	});
413 
414 	Convey("Can't specify address that isn't ours", {
415 		nng_socket s1;
416 
417 		So(nng_pair_open(&s1) == 0);
418 		Reset({ nng_close(s1); });
419 		So(nng_dial(s1, "tcp://8.8.8.8;127.0.0.1:80", NULL, 0) ==
420 		    NNG_EADDRINVAL);
421 	});
422 
423 	// We really need to have pipe start/negotiate as one of the key steps
424 	// during connect establish.  Until that happens, we cannot verify the
425 	// peer. See bug #208.
426 	SkipConvey("Verify works", {
427 		nng_socket   s1;
428 		nng_socket   s2;
429 		nng_listener l;
430 		size_t       sz;
431 		char         addr[NNG_MAXADDRLEN];
432 
433 		So(nng_pair_open(&s1) == 0);
434 		So(nng_pair_open(&s2) == 0);
435 		Reset({
436 			nng_close(s2);
437 			nng_close(s1);
438 		});
439 		trantest_next_address(addr, "tls+tcp://:%u");
440 		So(nng_listener_create(&l, s1, addr) == 0);
441 		So(init_listener_tls_file(NULL, l) == 0);
442 		So(nng_listener_start(l, 0) == 0);
443 		nng_msleep(100);
444 
445 		// reset port back one
446 		trantest_prev_address(addr, "tls+tcp://127.0.0.1:%u");
447 		So(nng_setopt_int(s2, NNG_OPT_TLS_AUTH_MODE,
448 		       NNG_TLS_AUTH_MODE_REQUIRED) == 0);
449 
450 		So(nng_dial(s2, addr, NULL, 0) == NNG_EPEERAUTH);
451 	});
452 
453 	Convey("No verify works", {
454 		nng_socket   s1; // server
455 		nng_socket   s2; // client
456 		nng_listener l;
457 		char         addr[NNG_MAXADDRLEN];
458 		nng_msg *    msg;
459 		nng_pipe     p;
460 		bool         b;
461 		nng_dialer   d;
462 
463 		So(nng_pair_open(&s1) == 0);
464 		So(nng_pair_open(&s2) == 0);
465 		Reset({
466 			nng_close(s2);
467 			nng_close(s1);
468 		});
469 		trantest_next_address(addr, "tls+tcp://*:%u");
470 		So(nng_listener_create(&l, s1, addr) == 0);
471 		So(init_listener_tls_file(l) == 0);
472 		So(nng_listener_setopt_int(l, NNG_OPT_TLS_AUTH_MODE,
473 		       NNG_TLS_AUTH_MODE_OPTIONAL) == 0);
474 		So(nng_listener_start(l, 0) == 0);
475 		nng_msleep(100);
476 
477 		// reset port back one
478 		trantest_prev_address(addr, "tls+tcp://127.0.0.1:%u");
479 		So(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, 200) == 0);
480 		So(nng_dialer_create(&d, s2, addr) == 0);
481 		So(init_dialer_tls_file(d) == 0);
482 		So(nng_dialer_setopt_string(
483 		       d, NNG_OPT_TLS_SERVER_NAME, "localhost") == 0);
484 		So(nng_dialer_start(d, 0) == 0);
485 
486 		So(nng_send(s2, "hello", 6, 0) == 0);
487 		So(nng_recvmsg(s1, &msg, 0) == 0);
488 		So(msg != NULL);
489 		So(nng_msg_len(msg) == 6);
490 		So(strcmp(nng_msg_body(msg), "hello") == 0);
491 		p = nng_msg_get_pipe(msg);
492 		So(nng_pipe_id(p) > 0);
493 		So(nng_pipe_getopt_bool(p, NNG_OPT_TLS_VERIFIED, &b) == 0);
494 		So(b == false);
495 		nng_msg_free(msg);
496 	});
497 
498 	Convey("Valid verify works", {
499 		nng_socket   s1;
500 		nng_socket   s2;
501 		nng_listener l;
502 		nng_dialer   d;
503 		char         addr[NNG_MAXADDRLEN];
504 		nng_msg *    msg;
505 		nng_pipe     p;
506 		bool         b;
507 
508 		So(nng_pair_open(&s1) == 0);
509 		So(nng_pair_open(&s2) == 0);
510 		Reset({
511 			nng_close(s2);
512 			nng_close(s1);
513 		});
514 		trantest_next_address(addr, "tls+tcp4://*:%u");
515 		So(nng_listener_create(&l, s1, addr) == 0);
516 		So(init_listener_tls_ex(l, NNG_TLS_AUTH_MODE_REQUIRED) == 0);
517 		So(nng_listener_start(l, 0) == 0);
518 
519 		nng_msleep(100);
520 
521 		// reset port back one
522 		trantest_prev_address(addr, "tls+tcp4://localhost:%u");
523 		So(nng_dialer_create(&d, s2, addr) == 0);
524 		So(init_dialer_tls_ex(d, true) == 0);
525 
526 		So(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, 200) == 0);
527 		So(nng_dialer_start(d, 0) == 0);
528 		nng_msleep(100);
529 
530 		// send from the server to the client-- the client always
531 		// verifies the server.
532 		So(nng_send(s2, "hello", 6, 0) == 0);
533 		So(nng_recvmsg(s1, &msg, 0) == 0);
534 		So(msg != NULL);
535 		So(nng_msg_len(msg) == 6);
536 		So(strcmp(nng_msg_body(msg), "hello") == 0);
537 		p = nng_msg_get_pipe(msg);
538 		So(nng_pipe_id(p) > 0);
539 		So(nng_pipe_getopt_bool(p, NNG_OPT_TLS_VERIFIED, &b) == 0);
540 		So(b == true);
541 		int i;
542 		So(nng_pipe_getopt_int(p, NNG_OPT_TLS_VERIFIED, &i) ==
543 		    NNG_EBADTYPE);
544 		nng_msg_free(msg);
545 	});
546 
547 	Convey("No delay option", {
548 		nng_socket   s;
549 		nng_dialer   d;
550 		nng_listener l;
551 		bool         v;
552 		int          x;
553 
554 		So(nng_pair_open(&s) == 0);
555 		Reset({ nng_close(s); });
556 		So(nng_getopt_bool(s, NNG_OPT_TCP_NODELAY, &v) == 0);
557 		So(v == true);
558 		So(nng_dialer_create(&d, s, "tcp://127.0.0.1:4999") == 0);
559 		So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_NODELAY, &v) == 0);
560 		So(v == true);
561 		So(nng_dialer_setopt_bool(d, NNG_OPT_TCP_NODELAY, false) == 0);
562 		So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_NODELAY, &v) == 0);
563 		So(v == false);
564 		So(nng_dialer_getopt_int(d, NNG_OPT_TCP_NODELAY, &x) ==
565 		    NNG_EBADTYPE);
566 		x = 0;
567 		So(nng_dialer_setopt_int(d, NNG_OPT_TCP_NODELAY, x) ==
568 		    NNG_EBADTYPE);
569 		// This assumes sizeof (bool) != sizeof (int)
570 		So(nng_dialer_setopt(d, NNG_OPT_TCP_NODELAY, &x, sizeof(x)) ==
571 		    NNG_EINVAL);
572 
573 		So(nng_listener_create(&l, s, "tcp://127.0.0.1:4999") == 0);
574 		So(nng_listener_getopt_bool(l, NNG_OPT_TCP_NODELAY, &v) == 0);
575 		So(v == true);
576 		x = 0;
577 		So(nng_listener_setopt_int(l, NNG_OPT_TCP_NODELAY, x) ==
578 		    NNG_EBADTYPE);
579 		// This assumes sizeof (bool) != sizeof (int)
580 		So(nng_listener_setopt(
581 		       l, NNG_OPT_TCP_NODELAY, &x, sizeof(x)) == NNG_EINVAL);
582 
583 		nng_dialer_close(d);
584 		nng_listener_close(l);
585 
586 		// Make sure socket wide defaults apply.
587 		So(nng_setopt_bool(s, NNG_OPT_TCP_NODELAY, true) == 0);
588 		v = false;
589 		So(nng_getopt_bool(s, NNG_OPT_TCP_NODELAY, &v) == 0);
590 		So(v == true);
591 		So(nng_setopt_bool(s, NNG_OPT_TCP_NODELAY, false) == 0);
592 		So(nng_dialer_create(&d, s, "tcp://127.0.0.1:4999") == 0);
593 		So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_NODELAY, &v) == 0);
594 		So(v == false);
595 	});
596 
597 	Convey("Keepalive option", {
598 		nng_socket   s;
599 		nng_dialer   d;
600 		nng_listener l;
601 		bool         v;
602 		int          x;
603 
604 		So(nng_pair_open(&s) == 0);
605 		Reset({ nng_close(s); });
606 		So(nng_getopt_bool(s, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
607 		So(v == false);
608 		So(nng_dialer_create(&d, s, "tcp://127.0.0.1:4999") == 0);
609 		So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
610 		So(v == false);
611 		So(nng_dialer_setopt_bool(d, NNG_OPT_TCP_KEEPALIVE, true) ==
612 		    0);
613 		So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
614 		So(v == true);
615 		So(nng_dialer_getopt_int(d, NNG_OPT_TCP_KEEPALIVE, &x) ==
616 		    NNG_EBADTYPE);
617 		x = 1;
618 		So(nng_dialer_setopt_int(d, NNG_OPT_TCP_KEEPALIVE, x) ==
619 		    NNG_EBADTYPE);
620 
621 		So(nng_listener_create(&l, s, "tcp://127.0.0.1:4999") == 0);
622 		So(nng_listener_getopt_bool(l, NNG_OPT_TCP_KEEPALIVE, &v) ==
623 		    0);
624 		So(v == false);
625 		x = 1;
626 		So(nng_listener_setopt_int(l, NNG_OPT_TCP_KEEPALIVE, x) ==
627 		    NNG_EBADTYPE);
628 
629 		nng_dialer_close(d);
630 		nng_listener_close(l);
631 
632 		// Make sure socket wide defaults apply.
633 		So(nng_setopt_bool(s, NNG_OPT_TCP_KEEPALIVE, false) == 0);
634 		v = true;
635 		So(nng_getopt_bool(s, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
636 		So(v == false);
637 		So(nng_setopt_bool(s, NNG_OPT_TCP_KEEPALIVE, true) == 0);
638 		So(nng_dialer_create(&d, s, "tcp://127.0.0.1:4999") == 0);
639 		So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
640 		So(v == true);
641 	});
642 })
643