diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | tests/httpclient.c | 14 | ||||
| -rw-r--r-- | tests/httpserver.c | 11 | ||||
| -rw-r--r-- | tests/trantest.h | 1 | ||||
| -rw-r--r-- | tests/ws.c | 8 | ||||
| -rw-r--r-- | tests/wss.c | 143 | ||||
| -rw-r--r-- | tests/wssfile.c | 329 |
7 files changed, 446 insertions, 61 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f6c9a62d..358e9d00 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -161,6 +161,7 @@ add_nng_test(udp 5 ON) add_nng_test(url 5 ON) add_nng_test(ws 30 NNG_TRANSPORT_WS) add_nng_test(wss 30 NNG_TRANSPORT_WSS) +add_nng_test(wssfile 30 NNG_TRANSPORT_WSS) add_nng_test(zt 60 NNG_TRANSPORT_ZEROTIER) add_nng_proto_test(bus 5 NNG_PROTO_BUS0 NNG_PROTO_BUS0) diff --git a/tests/httpclient.c b/tests/httpclient.c index e377d334..76a3566b 100644 --- a/tests/httpclient.c +++ b/tests/httpclient.c @@ -1,5 +1,5 @@ // -// Copyright 2018 Garrett D'Amore <garrett@damore.org> +// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a @@ -32,21 +32,13 @@ TestMain("HTTP Client", { Convey("Given a TCP connection to httpbin.org", { nng_aio * aio; nni_aio * iaio; - nng_sockaddr rsa; nni_http_client *cli; nni_http * http; So(nng_aio_alloc(&aio, NULL, NULL) == 0); - iaio = (nni_aio *) aio; - iaio->a_addr = &rsa; + iaio = (nni_aio *) aio; - nng_aio_set_timeout(aio, 20000); - nni_plat_tcp_resolv("httpbin.org", "80", NNG_AF_INET, 0, iaio); - nng_aio_wait(aio); - So(nng_aio_result(aio) == 0); - So(rsa.s_un.s_in.sa_port == htons(80)); - - So(nni_http_client_init(&cli, &rsa) == 0); + So(nni_http_client_init(&cli, "http://httpbin.org") == 0); nni_http_client_connect(cli, iaio); nng_aio_wait(aio); So(nng_aio_result(aio) == 0); diff --git a/tests/httpserver.c b/tests/httpserver.c index fa2753ea..147d0532 100644 --- a/tests/httpserver.c +++ b/tests/httpserver.c @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// Copyright 2018 Garrett D'Amore <garrett@damore.org> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -41,17 +41,20 @@ TestMain("HTTP Client", { nng_sockaddr sa; nni_aio * aio; char portbuf[16]; + char url[32]; char *doc = "<html><body>Someone <b>is</b> home!</body</html>"; trantest_next_address(portbuf, "%u"); + snprintf(url, sizeof(url), "http://127.0.0.1:%s", portbuf); + So(nni_aio_init(&aio, NULL, NULL) == 0); aio->a_addr = &sa; nni_plat_tcp_resolv("127.0.0.1", portbuf, NNG_AF_INET, 0, aio); nni_aio_wait(aio); So(nni_aio_result(aio) == 0); - So(nni_http_server_init(&s, &sa) == 0); + So(nni_http_server_init(&s, url) == 0); Reset({ nni_aio_fini(aio); @@ -68,7 +71,7 @@ TestMain("HTTP Client", { nni_http_req * req; nni_http_res * res; - So(nni_http_client_init(&cli, &sa) == 0); + So(nni_http_client_init(&cli, url) == 0); nni_http_client_connect(cli, aio); nni_aio_wait(aio); diff --git a/tests/trantest.h b/tests/trantest.h index 205a54b1..c85b3429 100644 --- a/tests/trantest.h +++ b/tests/trantest.h @@ -217,6 +217,7 @@ trantest_conn_refused(trantest *tt) Convey("Connection refused works", { nng_dialer d = 0; + int rv = trantest_dial(tt, &d); So(trantest_dial(tt, &d) == NNG_ECONNREFUSED); So(d == 0); So(trantest_dial(tt, &d) == NNG_ECONNREFUSED); @@ -80,7 +80,7 @@ TestMain("WebSocket Transport", { trantest_test_extended("ws://127.0.0.1:%u/test", check_props_v4); - Convey("Wild cards work", { + Convey("Empty hostname works", { nng_socket s1; nng_socket s2; char addr[NNG_MAXADDRLEN]; @@ -91,7 +91,7 @@ TestMain("WebSocket Transport", { nng_close(s2); nng_close(s1); }); - trantest_next_address(addr, "ws://*:%u/test"); + trantest_next_address(addr, "ws://:%u/test"); So(nng_listen(s1, addr, NULL, 0) == 0); nng_msleep(100); // reset port back one @@ -110,10 +110,10 @@ TestMain("WebSocket Transport", { nng_close(s2); nng_close(s1); }); - trantest_next_address(addr, "ws://*:%u/test"); + trantest_next_address(addr, "ws://:%u/test"); So(nng_listen(s1, addr, NULL, 0) == 0); // reset port back one - trantest_prev_address(addr, "ws://127.0.0.1:%u/nothere"); + trantest_prev_address(addr, "ws://localhost:%u/nothere"); So(nng_dial(s2, addr, NULL, 0) == NNG_ECONNREFUSED); }); diff --git a/tests/wss.c b/tests/wss.c index 00d37621..c087ed1e 100644 --- a/tests/wss.c +++ b/tests/wss.c @@ -27,50 +27,110 @@ // // Generated using openssl: // -// % openssl ecparam -name secp521r1 -noout -genkey -out key.key -// % openssl req -new -key key.key -out cert.csr -// % openssl x509 -req -in cert.csr -days 36500 -out cert.crt -signkey key.key +// % openssl rsa -genkey -out key.key +// % openssl req -new -key key.key -out cert.csr -sha256 +// % openssl x509 -req -in cert.csr -days 36500 -out cert.crt +// -signkey key.key -sha256 // // Relevant metadata: // // Certificate: -// Data: +// Data: // Version: 1 (0x0) -// Serial Number: 9808857926806240008 (0x882010509b8f7b08) -// Signature Algorithm: ecdsa-with-SHA1 -// Issuer: C=US, ST=CA, L=San Diego, O=nanomsg, CN=127.0.0.1 +// Serial Number: 17127835813110005400 (0xedb24becc3a2be98) +// Signature Algorithm: sha256WithRSAEncryption +// Issuer: C=US, ST=CA, L=San Diego, O=nanomsg.org, CN=localhost // Validity -// Not Before: Nov 17 20:08:06 2017 GMT -// Not After : Oct 24 20:08:06 2117 GMT -// Subject: C=US, ST=CA, L=San Diego, O=nanomsg, CN=127.0.0.1 +// Not Before: Jan 11 22:34:35 2018 GMT +// Not After : Dec 18 22:34:35 2117 GMT +// Subject: C=US, ST=CA, L=San Diego, O=nanomsg.org, CN=localhost +// Subject Public Key Info: +// Public Key Algorithm: rsaEncryption +// Public-Key: (2048 bit) // static const char cert[] = "-----BEGIN CERTIFICATE-----\n" - "MIICIjCCAYMCCQDaC9ARg31kIjAKBggqhkjOPQQDAjBUMQswCQYDVQQGEwJVUzEL\n" - "MAkGA1UECAwCQ0ExEjAQBgNVBAcMCVNhbiBEaWVnbzEQMA4GA1UECgwHbmFub21z\n" - "ZzESMBAGA1UEAwwJMTI3LjAuMC4xMCAXDTE3MTExNzIwMjczMloYDzIxMTcxMDI0\n" - "MjAyNzMyWjBUMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCVNh\n" - "biBEaWVnbzEQMA4GA1UECgwHbmFub21zZzESMBAGA1UEAwwJMTI3LjAuMC4xMIGb\n" - "MBAGByqGSM49AgEGBSuBBAAjA4GGAAQAN7vDK6GEiSguMsOuhfOvGyiVc37Sog0b\n" - "UkpaiS6+SagTmXFSN1Rgh9isxKFYJvcCtAko3v0I8rAVQucdhf5B3hEBMQlbBIuM\n" - "rMKT6ZQJ+eiwyb4O3Scgd7DoL3tc/kOqijwB/5hJ4sZdquDKP5DDFe5fAf4MNtzY\n" - "4C+iApWlKq/LoXkwCgYIKoZIzj0EAwIDgYwAMIGIAkIBOuJAWmNSdd6Ovmr6Ebg3\n" - "UF9ZrsNwARd9BfYbBk5OQhUOjCLB6d8aLi49WOm1WoRvOS5PaVvmvSfNhaw8b5nV\n" - "hnYCQgC+EmJ6C3bEcZrndhfbqvCaOGkc7/SrKhC6fS7mJW4wL90QUV9WjQ2Ll6X5\n" - "PxkSj7s0SvD6T8j7rju5LDgkdZc35A==\n" + "MIIDLjCCAhYCCQDtskvsw6K+mDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJV\n" + "UzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCVNhbiBEaWVnbzEUMBIGA1UECgwLbmFu\n" + "b21zZy5vcmcxEjAQBgNVBAMMCWxvY2FsaG9zdDAgFw0xODAxMTEyMjM0MzVaGA8y\n" + "MTE3MTIxODIyMzQzNVowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYD\n" + "VQQHDAlTYW4gRGllZ28xFDASBgNVBAoMC25hbm9tc2cub3JnMRIwEAYDVQQDDAls\n" + "b2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMvoHdEnfO\n" + "hmG3PTj6YC5qz6N5hgmcwf4EZkor4+R1Q5hDOKqOknWmVuGBD5mA61ObK76vycIT\n" + "Tp+H+vKvfgunySZrlyYg8IbgoDbvVgj9RF8xFHdN0PVeqnkBCsCzLtSu6TP8PSgI\n" + "SKiRMH0NUSakWqCPEc2E1r1CKdOpa7av/Na30LPsuKFcAUhu7QiVYfER86ktrO8G\n" + "F2PeVy44Q8RkiLw8uhU0bpAflqkR1KCjOLajw1eL3C+Io75Io8qUOLxWc3LH0hl3\n" + "oEI0jWu7JYlRAw/O7xm4pcGTwy5L8Odz4a7ZTAmuapFRarGOIcDg8Yr0tllRd1mH\n" + "1T4Z2Wv7Rs0tAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIfUXK7UonrYAOrlXUHH\n" + "gfHNdOXMzQP2Ms6Sxov+1tCTfgsYE65Mggo7hRJUqmKpstpbdRBVXhTyht/xjyTz\n" + "5sMjoeCyv1tXOHpLTfD3LBXwYZwsFdoLS1UHhD3qiYjCyyY2LWa6S786CtlcbCvu\n" + "Uij2q8zJ4WFrNqAzxZtsTfg16/6JRFw9zpVSCNlHqCxNQxzWucbmUFTiWn9rnc/N\n" + "r7utG4JsDPZbEI6QS43R7gGLDF7s0ftWKqzlQiZEtuDQh2p7Uejbft8XmZd/VuV/\n" + "dFMXOO1rleU0lWAJcXWOWHH3er0fivu2ISL8fRjjikYvhRGxtkwC0kPDa2Ntzgd3\n" + "Hsg=\n" "-----END CERTIFICATE-----\n"; - static const char key[] = - "-----BEGIN EC PRIVATE KEY-----\n" - "MIHcAgEBBEIB20OHMntU2UJW2yuQn2f+bLsuhTT5KRGorcocnqxatWLvxuF1cfUA\n" - "TjQxRRS6BIUvFt1fMIklp9qedJF00JHy4qWgBwYFK4EEACOhgYkDgYYABAA3u8Mr\n" - "oYSJKC4yw66F868bKJVzftKiDRtSSlqJLr5JqBOZcVI3VGCH2KzEoVgm9wK0CSje\n" - "/QjysBVC5x2F/kHeEQExCVsEi4yswpPplAn56LDJvg7dJyB3sOgve1z+Q6qKPAH/\n" - "mEnixl2q4Mo/kMMV7l8B/gw23NjgL6IClaUqr8uheQ==\n" - "-----END EC PRIVATE KEY-----\n"; + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpQIBAAKCAQEAzL6B3RJ3zoZhtz04+mAuas+jeYYJnMH+BGZKK+PkdUOYQziq\n" + "jpJ1plbhgQ+ZgOtTmyu+r8nCE06fh/ryr34Lp8kma5cmIPCG4KA271YI/URfMRR3\n" + "TdD1Xqp5AQrAsy7Urukz/D0oCEiokTB9DVEmpFqgjxHNhNa9QinTqWu2r/zWt9Cz\n" + "7LihXAFIbu0IlWHxEfOpLazvBhdj3lcuOEPEZIi8PLoVNG6QH5apEdSgozi2o8NX\n" + "i9wviKO+SKPKlDi8VnNyx9IZd6BCNI1ruyWJUQMPzu8ZuKXBk8MuS/Dnc+Gu2UwJ\n" + "rmqRUWqxjiHA4PGK9LZZUXdZh9U+Gdlr+0bNLQIDAQABAoIBAC82HqvjfkzZH98o\n" + "9uKFGy72AjQbfEvxT6mkDKZiPmPr2khl4K5Ph2F71zPzbOoVWYoGZEoUs/PPxWmN\n" + "rDhbUES4VWupxtkBnZheWUyHAjukcG7Y0UnYTTwvAwgCerzWp6RNkfcwAvMmDfis\n" + "vak8dTSg0TUsXb+r5KhFDNGcTNv3f7R0cJmaZ/t9FT7SerXf1LW7itvTjRor8/ZK\n" + "KPwT4oklp1o6RFXSenn/e2e3rAjI+TEwJA3Zp5dqO/M/AhaZKVaxL4voDVdVVkT+\n" + "LHJWVhjLY5ilPkmPWqmZ2reTaF+gGSSjAQ+t/ahGWFqEdWIz9UoXhBBOd1ibeyvd\n" + "Kyxp1QECgYEA8KcDkmwPrhqFlQe/U+Md27OhrQ4cecLCa6EVLsCXN1bFyCi3NSo2\n" + "o5zFCC699KOL0ZwSmYlaQP4xjnqv4Gsa0s3uL7tqOJR2UuEtGK/MPMluGHVaWsGt\n" + "zbnWH3xgsvvsxdt6hInFhcABLDupW336tJ8EcH7mOKoIP+azwF4kPiUCgYEA2c09\n" + "zJBUW6SZXhgJ5vgENYc+UwDT7pfhIWZaRL+wXnwSoa7igodTKJtQp/KfFBJK4RA0\n" + "prvwj4Wr/1ScaboR2hYZApbqXU5zkEkjC1hHIbg1fBe0EcnhP7ojMXrk6B5ed+Lq\n" + "OVdYhUuvtdL/perelmbTJLnb8S214+tzVyg7EGkCgYEA6JLwX8zxpnhZSztOjBr9\n" + "2zuSb7YojQBNd0kZOLLGMaQ5xwSactYWMi8rOIo76Lc6RFxKmXnl8NP5PtKRMRkx\n" + "tjNxE05UDNRmOhkGxUn433JoZVjc9sMhXqZQKuPAbJoOLPW9RWQEsgtq1r3eId7x\n" + "sSfRWYs6od6p1F/4rlwNOMUCgYEAtJmqf+DCAoe3IL3gICRSISy28k7CbZqE9JQR\n" + "j+Y/Uemh7W29pyydOROoysq1PAh7DKrKbeNzcx8NYxh+5nCC8wrVzD7lsV8nFmJ+\n" + "655UxVIhD3f8Oa/j1lr7acEU5KCiBtkjDU8vOMBsv+FpWOQrlB1JQa/X/+G+bHLF\n" + "XmUerNkCgYEAv7R8vIKgJ1f69imgHdB31kue3wnOO/6NlfY3GTcaZcTdChY8SZ5B\n" + "xits8xog0VcaxXhWlfO0hyCnZ9YRQbyDu0qp5eBU2p3qcE01x4ljJBZUOTweG06N\n" + "cL9dYcwse5FhNMjrQ/OKv6B38SIXpoKQUtjgkaMtmpK8cXX1eqEMNkM=\n" + "-----END RSA PRIVATE KEY-----\n"; + +static int +validloopback(nng_sockaddr *sa) +{ + char ipv6[16]; + memset(ipv6, 0, sizeof(ipv6)); + ipv6[15] = 1; + + switch (sa->s_un.s_family) { + case NNG_AF_INET: + if (sa->s_un.s_in.sa_port == 0) { + return (0); + } + if (sa->s_un.s_in.sa_addr != htonl(0x7f000001)) { + return (0); + } + return (1); + + case NNG_AF_INET6: + if (sa->s_un.s_in6.sa_port == 0) { + return (0); + } + if (memcmp(sa->s_un.s_in6.sa_addr, ipv6, sizeof(ipv6)) != 0) { + return (0); + } + return (1); + + default: + return (0); + } +} static int -check_props_v4(nng_msg *msg, nng_listener l, nng_dialer d) +check_props(nng_msg *msg, nng_listener l, nng_dialer d) { nng_pipe p; size_t z; @@ -85,17 +145,12 @@ check_props_v4(nng_msg *msg, nng_listener l, nng_dialer d) z = sizeof(nng_sockaddr); So(nng_pipe_getopt(p, NNG_OPT_LOCADDR, &la, &z) == 0); So(z == sizeof(la)); - So(la.s_un.s_family == NNG_AF_INET); - So(la.s_un.s_in.sa_port == htons(trantest_port - 1)); - So(la.s_un.s_in.sa_port != 0); - So(la.s_un.s_in.sa_addr == htonl(0x7f000001)); + So(validloopback(&la)); z = sizeof(nng_sockaddr); So(nng_pipe_getopt(p, NNG_OPT_REMADDR, &ra, &z) == 0); So(z == sizeof(ra)); - So(ra.s_un.s_family == NNG_AF_INET); - So(ra.s_un.s_in.sa_port != 0); - So(ra.s_un.s_in.sa_addr == htonl(0x7f000001)); + So(validloopback(&ra)); // Request header z = 0; @@ -136,10 +191,13 @@ init_dialer_wss(trantest *tt, nng_dialer d) if ((rv = nng_tls_config_ca_chain(cfg, cert, NULL)) != 0) { goto out; } - if ((rv = nng_tls_config_server_name(cfg, "127.0.0.1")) != 0) { + if ((rv = nng_tls_config_server_name(cfg, "localhost")) != 0) { + goto out; + } + if ((rv = nng_tls_config_auth_mode(cfg, NNG_TLS_AUTH_MODE_REQUIRED)) != + 0) { goto out; } - nng_tls_config_auth_mode(cfg, NNG_TLS_AUTH_MODE_NONE); rv = nng_dialer_setopt_ptr(d, NNG_OPT_WSS_TLS_CONFIG, cfg); out: @@ -174,12 +232,13 @@ out: } TestMain("WebSocket Secure (TLS) Transport", { + static trantest tt; tt.dialer_init = init_dialer_wss; tt.listener_init = init_listener_wss; - tt.tmpl = "wss://127.0.0.1:%u/test"; - tt.proptest = check_props_v4; + tt.tmpl = "wss://localhost:%u/test"; + tt.proptest = check_props; trantest_test(&tt); diff --git a/tests/wssfile.c b/tests/wssfile.c new file mode 100644 index 00000000..120e575d --- /dev/null +++ b/tests/wssfile.c @@ -0,0 +1,329 @@ +// +// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#include "convey.h" +#include "nng.h" +#include "protocol/pair1/pair.h" +#include "transport/ws/websocket.h" +#include "trantest.h" + +#include "stubs.h" +// TCP tests. + +#ifndef _WIN32 +#include <arpa/inet.h> +#endif + +// These keys are for demonstration purposes ONLY. DO NOT USE. +// The certificate is valid for 100 years, because I don't want to +// have to regenerate it ever again. The CN is 127.0.0.1, and self-signed. +// +// Generated using openssl: +// +// % openssl rsa -genkey -out key.key +// % openssl req -new -key key.key -out cert.csr -sha256 +// % openssl x509 -req -in cert.csr -days 36500 -out cert.crt +// -signkey key.key -sha256 +// +// Relevant metadata: +// +// Certificate: +// Data: +// Version: 1 (0x0) +// Serial Number: 17127835813110005400 (0xedb24becc3a2be98) +// Signature Algorithm: sha256WithRSAEncryption +// Issuer: C=US, ST=CA, L=San Diego, O=nanomsg.org, CN=localhost +// Validity +// Not Before: Jan 11 22:34:35 2018 GMT +// Not After : Dec 18 22:34:35 2117 GMT +// Subject: C=US, ST=CA, L=San Diego, O=nanomsg.org, CN=localhost +// Subject Public Key Info: +// Public Key Algorithm: rsaEncryption +// Public-Key: (2048 bit) +// +static const char cert[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIDLjCCAhYCCQDtskvsw6K+mDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJV\n" + "UzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCVNhbiBEaWVnbzEUMBIGA1UECgwLbmFu\n" + "b21zZy5vcmcxEjAQBgNVBAMMCWxvY2FsaG9zdDAgFw0xODAxMTEyMjM0MzVaGA8y\n" + "MTE3MTIxODIyMzQzNVowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYD\n" + "VQQHDAlTYW4gRGllZ28xFDASBgNVBAoMC25hbm9tc2cub3JnMRIwEAYDVQQDDAls\n" + "b2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMvoHdEnfO\n" + "hmG3PTj6YC5qz6N5hgmcwf4EZkor4+R1Q5hDOKqOknWmVuGBD5mA61ObK76vycIT\n" + "Tp+H+vKvfgunySZrlyYg8IbgoDbvVgj9RF8xFHdN0PVeqnkBCsCzLtSu6TP8PSgI\n" + "SKiRMH0NUSakWqCPEc2E1r1CKdOpa7av/Na30LPsuKFcAUhu7QiVYfER86ktrO8G\n" + "F2PeVy44Q8RkiLw8uhU0bpAflqkR1KCjOLajw1eL3C+Io75Io8qUOLxWc3LH0hl3\n" + "oEI0jWu7JYlRAw/O7xm4pcGTwy5L8Odz4a7ZTAmuapFRarGOIcDg8Yr0tllRd1mH\n" + "1T4Z2Wv7Rs0tAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIfUXK7UonrYAOrlXUHH\n" + "gfHNdOXMzQP2Ms6Sxov+1tCTfgsYE65Mggo7hRJUqmKpstpbdRBVXhTyht/xjyTz\n" + "5sMjoeCyv1tXOHpLTfD3LBXwYZwsFdoLS1UHhD3qiYjCyyY2LWa6S786CtlcbCvu\n" + "Uij2q8zJ4WFrNqAzxZtsTfg16/6JRFw9zpVSCNlHqCxNQxzWucbmUFTiWn9rnc/N\n" + "r7utG4JsDPZbEI6QS43R7gGLDF7s0ftWKqzlQiZEtuDQh2p7Uejbft8XmZd/VuV/\n" + "dFMXOO1rleU0lWAJcXWOWHH3er0fivu2ISL8fRjjikYvhRGxtkwC0kPDa2Ntzgd3\n" + "Hsg=\n" + "-----END CERTIFICATE-----\n"; +static const char key[] = + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpQIBAAKCAQEAzL6B3RJ3zoZhtz04+mAuas+jeYYJnMH+BGZKK+PkdUOYQziq\n" + "jpJ1plbhgQ+ZgOtTmyu+r8nCE06fh/ryr34Lp8kma5cmIPCG4KA271YI/URfMRR3\n" + "TdD1Xqp5AQrAsy7Urukz/D0oCEiokTB9DVEmpFqgjxHNhNa9QinTqWu2r/zWt9Cz\n" + "7LihXAFIbu0IlWHxEfOpLazvBhdj3lcuOEPEZIi8PLoVNG6QH5apEdSgozi2o8NX\n" + "i9wviKO+SKPKlDi8VnNyx9IZd6BCNI1ruyWJUQMPzu8ZuKXBk8MuS/Dnc+Gu2UwJ\n" + "rmqRUWqxjiHA4PGK9LZZUXdZh9U+Gdlr+0bNLQIDAQABAoIBAC82HqvjfkzZH98o\n" + "9uKFGy72AjQbfEvxT6mkDKZiPmPr2khl4K5Ph2F71zPzbOoVWYoGZEoUs/PPxWmN\n" + "rDhbUES4VWupxtkBnZheWUyHAjukcG7Y0UnYTTwvAwgCerzWp6RNkfcwAvMmDfis\n" + "vak8dTSg0TUsXb+r5KhFDNGcTNv3f7R0cJmaZ/t9FT7SerXf1LW7itvTjRor8/ZK\n" + "KPwT4oklp1o6RFXSenn/e2e3rAjI+TEwJA3Zp5dqO/M/AhaZKVaxL4voDVdVVkT+\n" + "LHJWVhjLY5ilPkmPWqmZ2reTaF+gGSSjAQ+t/ahGWFqEdWIz9UoXhBBOd1ibeyvd\n" + "Kyxp1QECgYEA8KcDkmwPrhqFlQe/U+Md27OhrQ4cecLCa6EVLsCXN1bFyCi3NSo2\n" + "o5zFCC699KOL0ZwSmYlaQP4xjnqv4Gsa0s3uL7tqOJR2UuEtGK/MPMluGHVaWsGt\n" + "zbnWH3xgsvvsxdt6hInFhcABLDupW336tJ8EcH7mOKoIP+azwF4kPiUCgYEA2c09\n" + "zJBUW6SZXhgJ5vgENYc+UwDT7pfhIWZaRL+wXnwSoa7igodTKJtQp/KfFBJK4RA0\n" + "prvwj4Wr/1ScaboR2hYZApbqXU5zkEkjC1hHIbg1fBe0EcnhP7ojMXrk6B5ed+Lq\n" + "OVdYhUuvtdL/perelmbTJLnb8S214+tzVyg7EGkCgYEA6JLwX8zxpnhZSztOjBr9\n" + "2zuSb7YojQBNd0kZOLLGMaQ5xwSactYWMi8rOIo76Lc6RFxKmXnl8NP5PtKRMRkx\n" + "tjNxE05UDNRmOhkGxUn433JoZVjc9sMhXqZQKuPAbJoOLPW9RWQEsgtq1r3eId7x\n" + "sSfRWYs6od6p1F/4rlwNOMUCgYEAtJmqf+DCAoe3IL3gICRSISy28k7CbZqE9JQR\n" + "j+Y/Uemh7W29pyydOROoysq1PAh7DKrKbeNzcx8NYxh+5nCC8wrVzD7lsV8nFmJ+\n" + "655UxVIhD3f8Oa/j1lr7acEU5KCiBtkjDU8vOMBsv+FpWOQrlB1JQa/X/+G+bHLF\n" + "XmUerNkCgYEAv7R8vIKgJ1f69imgHdB31kue3wnOO/6NlfY3GTcaZcTdChY8SZ5B\n" + "xits8xog0VcaxXhWlfO0hyCnZ9YRQbyDu0qp5eBU2p3qcE01x4ljJBZUOTweG06N\n" + "cL9dYcwse5FhNMjrQ/OKv6B38SIXpoKQUtjgkaMtmpK8cXX1eqEMNkM=\n" + "-----END RSA PRIVATE KEY-----\n"; + +static int +validloopback(nng_sockaddr *sa) +{ + char ipv6[16]; + memset(ipv6, 0, sizeof(ipv6)); + ipv6[15] = 1; + + switch (sa->s_un.s_family) { + case NNG_AF_INET: + if (sa->s_un.s_in.sa_port == 0) { + return (0); + } + if (sa->s_un.s_in.sa_addr != htonl(0x7f000001)) { + return (0); + } + return (1); + + case NNG_AF_INET6: + if (sa->s_un.s_in6.sa_port == 0) { + return (0); + } + if (memcmp(sa->s_un.s_in6.sa_addr, ipv6, sizeof(ipv6)) != 0) { + return (0); + } + return (1); + + default: + return (0); + } +} + +static int +check_props(nng_msg *msg, nng_listener l, nng_dialer d) +{ + nng_pipe p; + size_t z; + nng_sockaddr la; + nng_sockaddr ra; + char * buf; + size_t len; + + p = nng_msg_get_pipe(msg); + So(p > 0); + + z = sizeof(nng_sockaddr); + So(nng_pipe_getopt(p, NNG_OPT_LOCADDR, &la, &z) == 0); + So(z == sizeof(la)); + So(validloopback(&la)); + + z = sizeof(nng_sockaddr); + So(nng_pipe_getopt(p, NNG_OPT_REMADDR, &ra, &z) == 0); + So(z == sizeof(ra)); + So(validloopback(&ra)); + + // Request header + z = 0; + buf = NULL; + So(nng_pipe_getopt(p, NNG_OPT_WS_REQUEST_HEADERS, buf, &z) == 0); + So(z > 0); + len = z; + So((buf = nni_alloc(len)) != NULL); + So(nng_pipe_getopt(p, NNG_OPT_WS_REQUEST_HEADERS, buf, &z) == 0); + So(strstr(buf, "Sec-WebSocket-Key") != NULL); + So(z == len); + nni_free(buf, len); + + // Response header + z = 0; + buf = NULL; + So(nng_pipe_getopt(p, NNG_OPT_WS_RESPONSE_HEADERS, buf, &z) == 0); + So(z > 0); + len = z; + So((buf = nni_alloc(len)) != NULL); + So(nng_pipe_getopt(p, NNG_OPT_WS_RESPONSE_HEADERS, buf, &z) == 0); + So(strstr(buf, "Sec-WebSocket-Accept") != NULL); + So(z == len); + nni_free(buf, len); + + return (0); +} + +static int +init_dialer_wss_file(trantest *tt, nng_dialer d) +{ + int rv; + char *tmpdir; + char *pth; + + if ((tmpdir = nni_plat_temp_dir()) == NULL) { + return (NNG_ENOTSUP); + } + if ((pth = nni_file_join(tmpdir, "wss_test_cacert.pem")) == NULL) { + nni_strfree(tmpdir); + return (NNG_ENOMEM); + } + nni_strfree(tmpdir); + + if ((rv = nni_file_put(pth, cert, strlen(cert))) != 0) { + nni_strfree(pth); + return (rv); + } + + rv = nng_dialer_setopt_string(d, NNG_OPT_WSS_TLS_CA_FILE, pth); + nni_file_delete(pth); + nni_strfree(pth); + + return (rv); +} + +static int +init_listener_wss_file(trantest *tt, nng_listener l) +{ + int rv; + char *tmpdir; + char *pth; + char *certkey; + + if ((tmpdir = nni_plat_temp_dir()) == NULL) { + return (NNG_ENOTSUP); + } + + if ((pth = nni_file_join(tmpdir, "wss_test_certkey.pem")) == NULL) { + nni_strfree(tmpdir); + return (NNG_ENOMEM); + } + nni_strfree(tmpdir); + + if ((rv = nni_asprintf(&certkey, "%s\r\n%s\r\n", cert, key)) != 0) { + nni_strfree(pth); + return (rv); + } + + rv = nni_file_put(pth, certkey, strlen(certkey)); + nni_strfree(certkey); + if (rv != 0) { + nni_strfree(pth); + return (rv); + } + + rv = nng_listener_setopt_string(l, NNG_OPT_WSS_TLS_CERT_KEY_FILE, pth); + if (rv != 0) { + // We can wind up with EBUSY from the server already + // running. + if (rv == NNG_EBUSY) { + rv = 0; + } + } + + nni_file_delete(pth); + nni_strfree(pth); + return (rv); +} + +TestMain("WebSocket Secure (TLS) Transport (file based)", { + + static trantest tt; + + tt.dialer_init = init_dialer_wss_file; + tt.listener_init = init_listener_wss_file; + tt.tmpl = "wss://localhost:%u/test"; + tt.proptest = check_props; + + trantest_test(&tt); + + Convey("Verify works", { + nng_socket s1; + nng_socket s2; + nng_listener l; + char * buf; + size_t sz; + char addr[NNG_MAXADDRLEN]; + + So(nng_pair_open(&s1) == 0); + So(nng_pair_open(&s2) == 0); + Reset({ + nng_close(s2); + nng_close(s1); + }); + trantest_next_address(addr, "wss://:%u/test"); + So(nng_listener_create(&l, s1, addr) == 0); + So(init_listener_wss_file(NULL, l) == 0); + So(nng_listener_start(l, 0) == 0); + nng_msleep(100); + + // reset port back one + trantest_prev_address(addr, "wss://127.0.0.1:%u/test"); + So(nng_setopt_int(s2, NNG_OPT_WSS_TLS_AUTH_MODE, + NNG_TLS_AUTH_MODE_REQUIRED) == 0); + + So(nng_dial(s2, addr, NULL, 0) == NNG_EPEERAUTH); + }); + + Convey("No verify works", { + nng_socket s1; + nng_socket s2; + nng_listener l; + char * buf; + size_t sz; + char addr[NNG_MAXADDRLEN]; + + So(nng_pair_open(&s1) == 0); + So(nng_pair_open(&s2) == 0); + Reset({ + nng_close(s2); + nng_close(s1); + }); + trantest_next_address(addr, "wss://:%u/test"); + So(nng_listener_create(&l, s1, addr) == 0); + So(init_listener_wss_file(NULL, l) == 0); + So(nng_listener_start(l, 0) == 0); + nng_msleep(100); + + // reset port back one + trantest_prev_address(addr, "wss://127.0.0.1:%u/test"); + So(nng_setopt_int(s2, NNG_OPT_WSS_TLS_AUTH_MODE, + NNG_TLS_AUTH_MODE_NONE) == 0); + So(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, 200) == 0); + So(nng_dial(s2, addr, NULL, 0) == 0); + nng_msleep(100); + + So(nng_send(s1, "hello", 6, 0) == 0); + So(nng_recv(s2, &buf, &sz, NNG_FLAG_ALLOC) == 0); + So(sz == 6); + So(strcmp(buf, "hello") == 0); + nng_free(buf, sz); + }); + + nng_fini(); +}) |
