aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/nng_tls.adoc55
-rw-r--r--docs/nng_ws.adoc3
-rw-r--r--src/core/aio.c17
-rw-r--r--src/core/aio.h13
-rw-r--r--src/core/endpt.c7
-rw-r--r--src/nng.h3
-rw-r--r--src/supplemental/tls/mbedtls/tls.c5
-rw-r--r--src/transport/inproc/inproc.c9
-rw-r--r--src/transport/tls/tls.c81
-rw-r--r--src/transport/ws/websocket.c65
-rw-r--r--src/transport/ws/websocket.h4
-rw-r--r--tests/tls.c246
-rw-r--r--tests/wssfile.c50
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);
}
diff --git a/src/nng.h b/src/nng.h
index 0653d533..26e851eb 100644
--- a/src/nng.h
+++ b/src/nng.h
@@ -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();
})