diff options
| author | Garrett D'Amore <garrett@damore.org> | 2018-01-17 10:04:23 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2018-01-17 10:14:39 -0800 |
| commit | 99778897f483d6882d5104123e27e95eaac26837 (patch) | |
| tree | a1051fa299ad182a050e3287cd96aea0dad30749 | |
| parent | 02e6153236ae744fb614fcd14184924ec85c2993 (diff) | |
| download | nng-99778897f483d6882d5104123e27e95eaac26837.tar.gz nng-99778897f483d6882d5104123e27e95eaac26837.tar.bz2 nng-99778897f483d6882d5104123e27e95eaac26837.zip | |
fixes #209 NNG_OPT_TLS_VERIFIED is busted
fixes #210 Want NNG_OPT_TLS_* options for TLS transport
fixes #212 Eliminate a_endpt member of aio
| -rw-r--r-- | docs/nng_tls.adoc | 55 | ||||
| -rw-r--r-- | docs/nng_ws.adoc | 3 | ||||
| -rw-r--r-- | src/core/aio.c | 17 | ||||
| -rw-r--r-- | src/core/aio.h | 13 | ||||
| -rw-r--r-- | src/core/endpt.c | 7 | ||||
| -rw-r--r-- | src/nng.h | 3 | ||||
| -rw-r--r-- | src/supplemental/tls/mbedtls/tls.c | 5 | ||||
| -rw-r--r-- | src/transport/inproc/inproc.c | 9 | ||||
| -rw-r--r-- | src/transport/tls/tls.c | 81 | ||||
| -rw-r--r-- | src/transport/ws/websocket.c | 65 | ||||
| -rw-r--r-- | src/transport/ws/websocket.h | 4 | ||||
| -rw-r--r-- | tests/tls.c | 246 | ||||
| -rw-r--r-- | tests/wssfile.c | 50 |
13 files changed, 443 insertions, 115 deletions
diff --git a/docs/nng_tls.adoc b/docs/nng_tls.adoc index 404923aa..6284fc8d 100644 --- a/docs/nng_tls.adoc +++ b/docs/nng_tls.adoc @@ -141,15 +141,6 @@ The `sa_family` member will have the value `NNG_AF_INET` or `NNG_AF_INET6`. The `sa_port` and `sa_addr` are the TCP port number and address, both in network byte order (most significant byte is first). -X.509 Formats -~~~~~~~~~~~~~ - -The _tls_ transport supports certificates and key material provided -in either PEM or DER encoding. When using PEM format data, the -encoding must be at the start of the data, with no intervening -content. Furthermore, PEM encoded objects may have a terminating -NUL byte, which will be ignored if present. - Transport Options ~~~~~~~~~~~~~~~~~ @@ -158,24 +149,40 @@ setting these must be done before the transport is started. `NNG_OPT_TLS_CONFIG`:: -This option is used to set or obtain the TLS configuration -object (type `nng_tls_config *`), which is passed as a pointer. -Setting this option adds a reference to the object; obtaining the -object pointer does not. (Therefore when retrieving this option, -care must be taken not to access it after the endpoint is closed.) +This option is used on an endpoint to access the underlying TLS +configuration object. The value is of type `nng_tls_config *`. + +TIP: Use this option when advanced TLS configuration is required. + +`NNG_OPT_TLS_CA_FILE`:: + +This is a write-only option used to load certificates associated +associated private key from a file. +See <<nng_tls_config_ca_file#,nng_tls_config_ca_file(3)>> for more +information. + +`NNG_OPT_TLS_CERT_KEY_FILE`:: + +This is a write-only option used to load the local certificate and +associated private key from a file. The private key used must be +unencrypted. (Use the `NNG_OPT_TLS_CONFIG` option to access the underlying +TLS configuration if more advanced configuration is needed.) +See <<nng_tls_config_own_cert#,nng_tls_config_own_cert(3)>> for more +information. + +`NNG_OPT_TLS_AUTH_MODE`:: -Note that configuration object is not modifiable once it has been -used in a running TLS stream. +This is a write-only option used to configure the authentication mode +used. It can take an integer with value `NNG_TLS_AUTH_MODE_NONE`, +`NNG_TLS_AUTH_MODE_REQUIRED`, or `NNG_TLS_AUTH_MODE_OPTIONAL`. See +<<nng_tls_config_auth_mode#,nng_tls_config_auth_mode(3)>> for more details. -`NNG_OPT_TLS_AUTH_VERIFIED`:: +`NNG_OPT_TLS_VERIFIED`:: -This is a read-only boolean option available only for -pipes, indicating whether the peer certificate was -valdiated or not. This is only set when the pipe -has completed the handshake with the peer (which always -occurs before exchanging data), and will only be set -if the `NNG_OPT_TLS_AUTH_MODE` option is set to -`nng_tls_auth_mode_optional` or `nng_tls_auth_mode_required`. +This is a read-only option which returns a boolean value (integer 0 or 1). +It will true (1) if the remote peer has been properly verified using TLS +authentication, or false (0) otherwise. This option may return incorrect +results if peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`. SEE ALSO -------- diff --git a/docs/nng_ws.adoc b/docs/nng_ws.adoc index a7933796..ebab433c 100644 --- a/docs/nng_ws.adoc +++ b/docs/nng_ws.adoc @@ -204,7 +204,8 @@ used. It can take an integer with value `NNG_TLS_AUTH_MODE_NONE`, This is a read-only option which returns a boolean value (integer 0 or 1). It will true (1) if the remote peer has been properly verified using TLS -authentication, or false (0) otherwise. +authentication, or false (0) otherwise. This option may return incorrect +results if peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`. // We should also look at a hook mechanism for listeners. Probably this could // look like NNG_OPT_WS_LISTEN_HOOK_FUNC which would take a function pointer diff --git a/src/core/aio.c b/src/core/aio.c index 350bf52a..c6e0ed97 100644 --- a/src/core/aio.c +++ b/src/core/aio.c @@ -1,7 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> -// Copyright 2017 Staysail Systems, Inc. <info@staysail.tech> +// 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 @@ -148,18 +147,6 @@ nni_aio_get_pipe(nni_aio *aio) } void -nni_aio_set_ep(nni_aio *aio, void *ep) -{ - aio->a_endpt = ep; -} - -void * -nni_aio_get_ep(nni_aio *aio) -{ - return (aio->a_endpt); -} - -void nni_aio_set_data(nni_aio *aio, int index, void *data) { if ((index >= 0) && (index < NNI_NUM_ELEMENTS(aio->a_user_data))) { diff --git a/src/core/aio.h b/src/core/aio.h index c4c09421..b5db29c9 100644 --- a/src/core/aio.h +++ b/src/core/aio.h @@ -1,7 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> -// Copyright 2017 Staysail Systems, Inc. <info@staysail.tech> +// 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 @@ -47,8 +46,7 @@ struct nni_aio { nni_msg *a_msg; // Connect/accept operations. - void *a_endpt; // opaque endpoint handle - void *a_pipe; // opaque pipe handle + void *a_pipe; // opaque pipe handle // Resolver operations. nni_sockaddr *a_addr; @@ -128,14 +126,11 @@ extern void nni_aio_set_output(nni_aio *, int, void *); // nni_get_output returns an output previously stored on the AIO. extern void *nni_aio_get_output(nni_aio *, int); -// XXX: These should be refactored in terms of the generic inputs and -// outputs. +// XXX: These should be refactored in terms of generic inputs and outputs. extern void nni_aio_set_msg(nni_aio *, nni_msg *); extern nni_msg *nni_aio_get_msg(nni_aio *); extern void nni_aio_set_pipe(nni_aio *, void *); extern void * nni_aio_get_pipe(nni_aio *); -extern void nni_aio_set_ep(nni_aio *, void *); -extern void * nni_aio_get_ep(nni_aio *); // nni_aio_set_synch sets a synchronous completion flag on the AIO. // When this is set, the next time the AIO is completed, the callback diff --git a/src/core/endpt.c b/src/core/endpt.c index 3058f5c0..57e4bc62 100644 --- a/src/core/endpt.c +++ b/src/core/endpt.c @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// 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 @@ -406,7 +406,6 @@ nni_ep_con_start(nni_ep *ep) return; } - nni_aio_set_ep(aio, ep->ep_data); ep->ep_ops.ep_connect(ep->ep_data, aio); } @@ -444,7 +443,6 @@ nni_ep_dial(nni_ep *ep, int flags) // Synchronous mode: so we have to wait for it to complete. aio = ep->ep_con_syn; - nni_aio_set_ep(aio, ep->ep_data); ep->ep_ops.ep_connect(ep->ep_data, aio); ep->ep_started = 1; nni_mtx_unlock(&ep->ep_mtx); @@ -509,7 +507,6 @@ nni_ep_acc_start(nni_ep *ep) return; } nni_aio_set_pipe(aio, NULL); - nni_aio_set_ep(aio, ep->ep_data); ep->ep_ops.ep_accept(ep->ep_data, aio); } @@ -412,7 +412,8 @@ enum nng_flag_enum { // NNG_OPT_TLS_VERIFIED returns a single integer, indicating whether the peer // has been verified (1) or not (0). Typically this is read-only, and only -// available for pipes. +// available for pipes. This option may return incorrect results if peer +// authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`. #define NNG_OPT_TLS_VERIFIED "tls-verified" // XXX: TBD: priorities, socket names, ipv4only diff --git a/src/supplemental/tls/mbedtls/tls.c b/src/supplemental/tls/mbedtls/tls.c index 7b959b2b..4ae842a2 100644 --- a/src/supplemental/tls/mbedtls/tls.c +++ b/src/supplemental/tls/mbedtls/tls.c @@ -754,10 +754,7 @@ nni_tls_ciphersuite_name(nni_tls *tp) bool nni_tls_verified(nni_tls *tp) { - int rv; - - rv = mbedtls_ssl_get_verify_result(&tp->ctx); - return (rv ? true : false); + return (mbedtls_ssl_get_verify_result(&tp->ctx) == 0); } int diff --git a/src/transport/inproc/inproc.c b/src/transport/inproc/inproc.c index ae64263c..5b52e80a 100644 --- a/src/transport/inproc/inproc.c +++ b/src/transport/inproc/inproc.c @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// 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 @@ -222,7 +222,7 @@ nni_inproc_ep_fini(void *arg) static void nni_inproc_conn_finish(nni_aio *aio, int rv) { - nni_inproc_ep *ep = aio->a_endpt; + nni_inproc_ep *ep = aio->a_prov_extra[0]; void * pipe; nni_aio_list_remove(aio); @@ -361,6 +361,7 @@ nni_inproc_ep_connect(void *arg, nni_aio *aio) return; } + aio->a_prov_extra[0] = ep; if ((rv = nni_inproc_pipe_init((void *) &aio->a_pipe, ep)) != 0) { nni_aio_finish_error(aio, rv); nni_mtx_unlock(&nni_inproc.mx); @@ -418,6 +419,8 @@ nni_inproc_ep_accept(void *arg, nni_aio *aio) return; } + aio->a_prov_extra[0] = ep; + // We are already on the master list of servers, thanks to bind. if ((rv = nni_inproc_pipe_init((void *) &aio->a_pipe, ep)) != 0) { diff --git a/src/transport/tls/tls.c b/src/transport/tls/tls.c index 05d477b5..9832c36c 100644 --- a/src/transport/tls/tls.c +++ b/src/transport/tls/tls.c @@ -843,13 +843,68 @@ tls_getopt_config(void *arg, void *v, size_t *szp) } static int +tls_setopt_ca_file(void *arg, const void *v, size_t sz) +{ + nni_tls_ep *ep = arg; + + if (nni_strnlen(v, sz) >= sz) { + return (NNG_EINVAL); + } + if (ep == NULL) { + return (0); + } + return (nng_tls_config_ca_file(ep->cfg, v)); +} + +static int +tls_setopt_auth_mode(void *arg, const void *v, size_t sz) +{ + nni_tls_ep *ep = arg; + int mode; + int rv; + + rv = nni_setopt_int( + &mode, v, sz, NNG_TLS_AUTH_MODE_NONE, NNG_TLS_AUTH_MODE_REQUIRED); + if ((rv != 0) || (ep == NULL)) { + return (rv); + } + return (nng_tls_config_auth_mode(ep->cfg, mode)); +} + +static int +tls_setopt_server_name(void *arg, const void *v, size_t sz) +{ + nni_tls_ep *ep = arg; + + if (nni_strnlen(v, sz) >= sz) { + return (NNG_EINVAL); + } + if (ep == NULL) { + return (0); + } + return (nng_tls_config_server_name(ep->cfg, v)); +} + +static int +tls_setopt_cert_key_file(void *arg, const void *v, size_t sz) +{ + nni_tls_ep *ep = arg; + + if (nni_strnlen(v, sz) >= sz) { + return (NNG_EINVAL); + } + if (ep == NULL) { + return (0); + } + return (nng_tls_config_cert_key_file(ep->cfg, v, NULL)); +} + +static int tls_getopt_verified(void *arg, void *v, size_t *szp) { nni_tls_pipe *p = arg; - int verified; - verified = nni_tls_verified(p->tls); - return (nni_getopt_int(verified, v, szp)); + return (nni_getopt_int(nni_tls_verified(p->tls) ? 1 : 0, v, szp)); } static nni_tran_pipe_option nni_tls_pipe_options[] = { @@ -886,6 +941,26 @@ static nni_tran_ep_option nni_tls_ep_options[] = { .eo_getopt = tls_getopt_config, .eo_setopt = tls_setopt_config, }, + { + .eo_name = NNG_OPT_TLS_CERT_KEY_FILE, + .eo_getopt = NULL, + .eo_setopt = tls_setopt_cert_key_file, + }, + { + .eo_name = NNG_OPT_TLS_CA_FILE, + .eo_getopt = NULL, + .eo_setopt = tls_setopt_ca_file, + }, + { + .eo_name = NNG_OPT_TLS_AUTH_MODE, + .eo_getopt = NULL, + .eo_setopt = tls_setopt_auth_mode, + }, + { + .eo_name = NNG_OPT_TLS_SERVER_NAME, + .eo_getopt = NULL, + .eo_setopt = tls_setopt_server_name, + }, // terminate list { NULL, NULL, NULL }, }; diff --git a/src/transport/ws/websocket.c b/src/transport/ws/websocket.c index a06910d3..83155046 100644 --- a/src/transport/ws/websocket.c +++ b/src/transport/ws/websocket.c @@ -363,7 +363,6 @@ ws_ep_setopt_recvmaxsz(void *arg, const void *v, size_t sz) static int ws_ep_setopt_headers(ws_ep *ep, const void *v, size_t sz) { - // XXX: check that the string is well formed. char * dupstr; size_t duplen; char * name; @@ -373,6 +372,10 @@ ws_ep_setopt_headers(ws_ep *ep, const void *v, size_t sz) ws_hdr * h; int rv; + if (nni_strnlen(v, sz) >= sz) { + return (NNG_EINVAL); + } + if (ep == NULL) { return (0); } @@ -835,13 +838,11 @@ wss_ep_setopt_tlsconfig(void *arg, const void *v, size_t sz) if (ep == NULL) { return (0); } - nni_mtx_lock(&ep->mtx); if (ep->mode == NNI_EP_MODE_LISTEN) { rv = nni_ws_listener_set_tls(ep->listener, cfg); } else { rv = nni_ws_dialer_set_tls(ep->dialer, cfg); } - nni_mtx_unlock(&ep->mtx); return (rv); } @@ -852,20 +853,16 @@ wss_ep_setopt_tls_cert_key_file(void *arg, const void *v, size_t sz) int rv; nng_tls_config *tls; + if (nni_strnlen(v, sz) >= sz) { + return (NNG_EINVAL); + } if (ep == NULL) { - if (nni_strnlen(v, sz) >= sz) { - return (NNG_EINVAL); - } return (0); } - nni_mtx_lock(&ep->mtx); - if (((rv = wss_get_tls(ep, &tls)) != 0) || - ((rv = nng_tls_config_cert_key_file(tls, v, NULL)) != 0)) { - goto done; + if ((rv = wss_get_tls(ep, &tls)) != 0) { + return (rv); } -done: - nni_mtx_unlock(&ep->mtx); - return (rv); + return (nng_tls_config_cert_key_file(tls, v, NULL)); } static int @@ -875,20 +872,16 @@ wss_ep_setopt_tls_ca_file(void *arg, const void *v, size_t sz) int rv; nng_tls_config *tls; + if (nni_strnlen(v, sz) >= sz) { + return (NNG_EINVAL); + } if (ep == NULL) { - if (nni_strnlen(v, sz) >= sz) { - return (NNG_EINVAL); - } return (0); } - nni_mtx_lock(&ep->mtx); - if (((rv = wss_get_tls(ep, &tls)) != 0) || - ((rv = nng_tls_config_ca_file(tls, v)) != 0)) { - goto done; + if ((rv = wss_get_tls(ep, &tls)) != 0) { + return (rv); } -done: - nni_mtx_unlock(&ep->mtx); - return (rv); + return (nng_tls_config_ca_file(tls, v)); } static int @@ -904,14 +897,10 @@ wss_ep_setopt_tls_auth_mode(void *arg, const void *v, size_t sz) if ((rv != 0) || (ep == NULL)) { return (rv); } - nni_mtx_lock(&ep->mtx); - if (((rv = wss_get_tls(ep, &tls)) != 0) || - ((rv = nng_tls_config_auth_mode(tls, mode)) != 0)) { - goto done; + if ((rv = wss_get_tls(ep, &tls)) != 0) { + return (rv); } -done: - nni_mtx_unlock(&ep->mtx); - return (rv); + return (nng_tls_config_auth_mode(tls, mode)); } static int @@ -921,20 +910,16 @@ wss_ep_setopt_tls_server_name(void *arg, const void *v, size_t sz) int rv; nng_tls_config *tls; + if (nni_strnlen(v, sz) >= sz) { + return (NNG_EINVAL); + } if (ep == NULL) { - if (nni_strnlen(v, sz) >= sz) { - return (NNG_EINVAL); - } return (0); } - nni_mtx_lock(&ep->mtx); - if (((rv = wss_get_tls(ep, &tls)) != 0) || - ((rv = nng_tls_config_server_name(tls, v)) != 0)) { - goto done; + if ((rv = wss_get_tls(ep, &tls)) != 0) { + return (rv); } -done: - nni_mtx_unlock(&ep->mtx); - return (rv); + return (nng_tls_config_server_name(tls, v)); } static nni_tran_ep_option wss_ep_options[] = { diff --git a/src/transport/ws/websocket.h b/src/transport/ws/websocket.h index 76e94c3e..8179beab 100644 --- a/src/transport/ws/websocket.h +++ b/src/transport/ws/websocket.h @@ -1,6 +1,6 @@ // -// Copyright 2017 Staysail Systems, Inc. <info@staysail.tech> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// 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 diff --git a/tests/tls.c b/tests/tls.c index 5f4f5523..1196aab3 100644 --- a/tests/tls.c +++ b/tests/tls.c @@ -46,7 +46,7 @@ // Not After : Oct 24 20:08:06 2117 GMT // Subject: C=US, ST=CA, L=San Diego, O=nanomsg, CN=127.0.0.1 // -static const char cert[] = +static const char eccert[] = "-----BEGIN CERTIFICATE-----\n" "MIICIjCCAYMCCQDaC9ARg31kIjAKBggqhkjOPQQDAjBUMQswCQYDVQQGEwJVUzEL\n" "MAkGA1UECAwCQ0ExEjAQBgNVBAcMCVNhbiBEaWVnbzEQMA4GA1UECgwHbmFub21z\n" @@ -62,7 +62,7 @@ static const char cert[] = "PxkSj7s0SvD6T8j7rju5LDgkdZc35A==\n" "-----END CERTIFICATE-----\n"; -static const char key[] = +static const char eckey[] = "-----BEGIN EC PRIVATE KEY-----\n" "MIHcAgEBBEIB20OHMntU2UJW2yuQn2f+bLsuhTT5KRGorcocnqxatWLvxuF1cfUA\n" "TjQxRRS6BIUvFt1fMIklp9qedJF00JHy4qWgBwYFK4EEACOhgYkDgYYABAA3u8Mr\n" @@ -71,11 +71,62 @@ static const char key[] = "mEnixl2q4Mo/kMMV7l8B/gw23NjgL6IClaUqr8uheQ==\n" "-----END EC PRIVATE KEY-----\n"; +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 check_props_v4(nng_msg *msg, nng_listener l, nng_dialer d) { nng_pipe p; size_t z; + p = nng_msg_get_pipe(msg); So(p > 0); nng_sockaddr la; @@ -108,9 +159,11 @@ init_dialer_tls(trantest *tt, nng_dialer d) if ((rv = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_CLIENT)) != 0) { return (rv); } + 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) { goto out; } @@ -142,6 +195,78 @@ out: return (0); } +static int +init_dialer_tls_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, "tls_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_TLS_CA_FILE, pth); + nni_file_delete(pth); + nni_strfree(pth); + + return (rv); +} + +static int +init_listener_tls_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, "tls_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_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("TLS Transport", { static trantest tt; @@ -210,4 +335,121 @@ TestMain("TLS Transport", { So(nng_listen(s1, "tls+tcp://127.0.x.1.32", NULL, 0) == NNG_EADDRINVAL); }); + +#if 0 +// We really need to have pipe start/negotiate as one of the key steps during +// connect establish. Until that happens, we cannot verify the peer. +// See bug #208. + 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, "tls+tcp://:%u"); + So(nng_listener_create(&l, s1, addr) == 0); + So(init_listener_tls_file(NULL, l) == 0); + So(nng_listener_start(l, 0) == 0); + nng_msleep(100); + + // reset port back one + trantest_prev_address(addr, "tls+tcp://127.0.0.1:%u"); + So(nng_setopt_int(s2, NNG_OPT_TLS_AUTH_MODE, + NNG_TLS_AUTH_MODE_REQUIRED) == 0); + + So(nng_dial(s2, addr, NULL, 0) == NNG_EPEERAUTH); + }); +#endif + + Convey("No verify works", { + nng_socket s1; + nng_socket s2; + nng_listener l; + char addr[NNG_MAXADDRLEN]; + nng_msg * msg; + nng_pipe p; + int v; + + So(nng_pair_open(&s1) == 0); + So(nng_pair_open(&s2) == 0); + Reset({ + nng_close(s2); + nng_close(s1); + }); + trantest_next_address(addr, "tls+tcp://*:%u"); + So(nng_listener_create(&l, s1, addr) == 0); + So(init_listener_tls_file(NULL, l) == 0); + So(nng_listener_start(l, 0) == 0); + nng_msleep(100); + + // reset port back one + trantest_prev_address(addr, "tls+tcp://127.0.0.1:%u"); + So(nng_setopt_int(s2, NNG_OPT_TLS_AUTH_MODE, + NNG_TLS_AUTH_MODE_OPTIONAL) == 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_recvmsg(s2, &msg, 0) == 0); + So(msg != NULL); + So(nng_msg_len(msg) == 6); + So(strcmp(nng_msg_body(msg), "hello") == 0); + p = nng_msg_get_pipe(msg); + So(p > 0); + So(nng_pipe_getopt_int(p, NNG_OPT_TLS_VERIFIED, &v) == 0); + So(v == 0); + nng_msg_free(msg); + }); + + Convey("Valid verify works", { + nng_socket s1; + nng_socket s2; + nng_listener l; + nng_dialer d; + char addr[NNG_MAXADDRLEN]; + nng_msg * msg; + nng_pipe p; + int v; + + So(nng_pair_open(&s1) == 0); + So(nng_pair_open(&s2) == 0); + Reset({ + nng_close(s2); + nng_close(s1); + }); + trantest_next_address(addr, "tls+tcp://*:%u"); + So(nng_listener_create(&l, s1, addr) == 0); + So(init_listener_tls_file(NULL, l) == 0); + So(nng_listener_start(l, 0) == 0); + nng_msleep(100); + + // reset port back one + trantest_prev_address(addr, "tls+tcp://localhost:%u"); + So(nng_dialer_create(&d, s2, addr) == 0); + So(init_dialer_tls_file(NULL, d) == 0); + So(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, 200) == 0); + So(nng_dialer_start(d, 0) == 0); + nng_msleep(100); + + So(nng_send(s1, "hello", 6, 0) == 0); + So(nng_recvmsg(s2, &msg, 0) == 0); + So(msg != NULL); + So(nng_msg_len(msg) == 6); + So(strcmp(nng_msg_body(msg), "hello") == 0); + p = nng_msg_get_pipe(msg); + So(p > 0); + So(nng_pipe_getopt_int(p, NNG_OPT_TLS_VERIFIED, &v) == 0); + So(v == 1); + nng_msg_free(msg); + }); + }) diff --git a/tests/wssfile.c b/tests/wssfile.c index 73a0050b..28cdf6b6 100644 --- a/tests/wssfile.c +++ b/tests/wssfile.c @@ -177,10 +177,6 @@ check_props(nng_msg *msg, nng_listener l, nng_dialer d) So(z == len); nni_free(buf, len); - // Verified - So(nng_pipe_getopt_int(p, NNG_OPT_TLS_VERIFIED, &v) == 0); - So(v == 1); - return (0); } @@ -267,7 +263,7 @@ TestMain("WebSocket Secure (TLS) Transport (file based)", { trantest_test(&tt); - Convey("Verify works", { + Convey("Invalid verify works", { nng_socket s1; nng_socket s2; nng_listener l; @@ -319,7 +315,7 @@ TestMain("WebSocket Secure (TLS) Transport (file based)", { // reset port back one trantest_prev_address(addr, "wss://127.0.0.1:%u/test"); So(nng_setopt_int(s2, NNG_OPT_TLS_AUTH_MODE, - NNG_TLS_AUTH_MODE_NONE) == 0); + NNG_TLS_AUTH_MODE_OPTIONAL) == 0); So(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, 200) == 0); So(nng_dial(s2, addr, NULL, 0) == 0); nng_msleep(100); @@ -336,5 +332,47 @@ TestMain("WebSocket Secure (TLS) Transport (file based)", { nng_msg_free(msg); }); + Convey("Valid verify works", { + nng_socket s1; + nng_socket s2; + nng_listener l; + nng_dialer d; + char addr[NNG_MAXADDRLEN]; + nng_msg * msg; + nng_pipe p; + int v; + + 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://localhost:%u/test"); + So(nng_dialer_create(&d, s2, addr) == 0); + So(init_dialer_wss_file(NULL, d) == 0); + So(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, 200) == 0); + So(nng_dialer_start(d, 0) == 0); + nng_msleep(100); + + So(nng_send(s1, "hello", 6, 0) == 0); + So(nng_recvmsg(s2, &msg, 0) == 0); + So(msg != NULL); + So(nng_msg_len(msg) == 6); + So(strcmp(nng_msg_body(msg), "hello") == 0); + p = nng_msg_get_pipe(msg); + So(p > 0); + So(nng_pipe_getopt_int(p, NNG_OPT_TLS_VERIFIED, &v) == 0); + So(v == 1); + nng_msg_free(msg); + }); + nng_fini(); }) |
