diff options
| author | Garrett D'Amore <garrett@damore.org> | 2018-01-16 12:07:45 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2018-01-16 14:29:38 -0800 |
| commit | 02e6153236ae744fb614fcd14184924ec85c2993 (patch) | |
| tree | 6b41ca972d60e758c65c1adc0621500a92003c86 | |
| parent | bbf012364d9f1482b16c97b8bfd2fd07130446ca (diff) | |
| download | nng-02e6153236ae744fb614fcd14184924ec85c2993.tar.gz nng-02e6153236ae744fb614fcd14184924ec85c2993.tar.bz2 nng-02e6153236ae744fb614fcd14184924ec85c2993.zip | |
fixes #206 Want NNG_OPT_TLS_VERIFIED option
It is useful to have support for validating that a peer *was*
verified, especially in the presence of optional validation.
We have added a property that does this, NNG_OPT_TLS_VERIFIED.
Further, all the old NNG_OPT_WSS_TLS_* property names have also been
renamed to generic NNG_OPT_TLS property names, which have been
moved to nng.h to facilitate reuse and sharing, with the comments
moved and corrected as well.
Finally, the man pages have been updated, with substantial
improvements to the nng_ws man page in particular.
| -rw-r--r-- | docs/nng_ws.adoc | 75 | ||||
| -rw-r--r-- | src/nng.h | 47 | ||||
| -rw-r--r-- | src/platform/posix/posix_thread.c | 3 | ||||
| -rw-r--r-- | src/supplemental/http/http.c | 23 | ||||
| -rw-r--r-- | src/supplemental/http/http.h | 3 | ||||
| -rw-r--r-- | src/supplemental/tls/mbedtls/tls.c | 4 | ||||
| -rw-r--r-- | src/supplemental/tls/tls.h | 4 | ||||
| -rw-r--r-- | src/supplemental/websocket/websocket.c | 11 | ||||
| -rw-r--r-- | src/supplemental/websocket/websocket.h | 3 | ||||
| -rw-r--r-- | src/transport/tls/tls.c | 2 | ||||
| -rw-r--r-- | src/transport/tls/tls.h | 12 | ||||
| -rw-r--r-- | src/transport/ws/websocket.c | 67 | ||||
| -rw-r--r-- | src/transport/ws/websocket.h | 54 | ||||
| -rw-r--r-- | tests/wss.c | 5 | ||||
| -rw-r--r-- | tests/wssfile.c | 31 |
15 files changed, 209 insertions, 135 deletions
diff --git a/docs/nng_ws.adoc b/docs/nng_ws.adoc index d36062ab..a7933796 100644 --- a/docs/nng_ws.adoc +++ b/docs/nng_ws.adoc @@ -126,12 +126,36 @@ 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). +Server Instances +~~~~~~~~~~~~~~~~ + +This transport makes use of shared HTTP server instances, permitting multiple +sockets or listeners to be configured with the same hostname and port. When +creating a new listener, it is registered with an existing HTTP server instance +if one can be found. Note that the matching algorithm is somewhat simple, +using only a string based hostname or IP address and port to match. Therefore +it is recommended to use only IP addresses or the empty string as the hostname +in listener URLs. + +Likewise, when sharing a server instance, it may not be possible to alter +TLS configuration if the server is already running, as there is only a single +TLS configuration context for the entire server instance. + +All sharing of server instances is only typically possible within the same +process. + +The server may also be used by other things (for example to serve static +content), in the same process. + Transport Options ~~~~~~~~~~~~~~~~~ The following transport options are available. Note that setting these must be done before the transport is started. +NOTE: The TLS specific options (beginning with `NNG_OPT_TLS_`) are +only available for `wss://` endpoints. + `NNG_OPT_WS_REQUEST_HEADERS`:: This value is a string, consisting of multiple lines terminated @@ -146,40 +170,41 @@ by CRLF sequences, that can be used to add furthe headers to the HTTP response sent when connecting. This option can be set on listeners, and retrieved from pipes. -`NNG_OPT_WSS_TLS_CONFIG`:: +`NNG_OPT_TLS_CONFIG`:: This option is used on an endpoint to access the underlying TLS configuration object. The value is of type `nng_tls_config *`. -Note that attempts to set this object may fail on a listener if -the server is already running. Furthermore, attempts to modify the -configuration object will fail if it is already in active use. -This object is only available for `wss://` endpoints. -`NNG_OPT_WSS_TLS_CA_FILE`:: +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. The value is a C string -containing the path name of the file. The file itself must contain -https://tools.ietf.org/html/rfc7468[PEM] format objects for one or more -X.509 certificates. It may also contain certificate revocation list (CRL) -objects well. Note that attempts to call this will fail if the -configuration associated with the underlying endpoint -is already in use. This option is only available for `wss://` endpoints. +associated private key from a file. +See <<nng_tls_config_ca_file#,nng_tls_config_ca_file(3)>> for more +information. -`NNG_OPT_WSS_TLS_CERT_KEY_FILE`:: +`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 value is a C string -containing the path name of the file. The file itself must contain PEM -format objects for the X.509 certificate and private key. Multiple -certificates may be listed in the file, to provide a validation chain, -with the leaf certificate listed first, and subsequent certificates listed -afterwards. Note that attempts to call this will fail if the -configuration associated with the underlying endpoint -is already in use. This option is only available for `wss://` endpoints. -The private key must not be encrypted. (Use the `NNG_OPT_WSS_TLS_CONFIG` -option to get the underlying TLS configuration if more advanced -configuration is needed.) +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`:: + +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_VERIFIED`:: + +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. // 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 @@ -368,6 +368,53 @@ enum nng_flag_enum { #define NNG_OPT_RECONNMINT "reconnect-time-min" #define NNG_OPT_RECONNMAXT "reconnect-time-max" +// TLS options are only used when the underlying transport supports TLS. + +// NNG_OPT_TLS_CONFIG is a pointer to an nng_tls_config object. Generally +// this can used with endpoints, although once an endpoint is started, or +// once a configuration is used, the value becomes read-only. Note that +// when configuring the object, a hold is placed on the TLS configuration, +// using a reference count. When retrieving the object, no such hold is +// placed, and so the caller must take care not to use the associated object +// after the endpoint it is associated with is closed. +#define NNG_OPT_TLS_CONFIG "tls-config" + +// NNG_OPT_TLS_AUTH_MODE is a write-only integer (int) option that specifies +// whether peer authentication is needed. The option can take one of the +// values of NNG_TLS_AUTH_MODE_NONE, NNG_TLS_AUTH_MODE_OPTIONAL, or +// NNG_TLS_AUTH_MODE_REQUIRED. The default is typically NNG_TLS_AUTH_MODE_NONE +// for listeners, and NNG_TLS_AUTH_MODE_REQUIRED for dialers. If set to +// REQUIRED, then connections will be rejected if the peer cannot be verified. +// If set to OPTIONAL, then a verification step takes place, but the connection +// is still permitted. (The result can be checked with NNG_OPT_TLS_VERIFIED). +#define NNG_OPT_TLS_AUTH_MODE "tls-authmode" + +// NNG_OPT_TLS_CERT_KEY_FILE names a single file that contains a certificate +// and key identifying the endpoint. This is a write-only value. This can be +// set multiple times for times for different keys/certs corresponding to +// different algorithms on listeners, whereas dialers only support one. The +// file must contain both cert and key as PEM blocks, and the key must +// not be encrypted. (If more flexibility is needed, use the TLS configuration +// directly, via NNG_OPT_TLS_CONFIG.) +#define NNG_OPT_TLS_CERT_KEY_FILE "tls-cert-key-file" + +// NNG_OPT_TLS_CA_FILE names a single file that contains certificate(s) for a +// CA, and optionally CRLs, which are used to validate the peer's certificate. +// This is a write-only value, but multiple CAs can be loaded by setting this +// multiple times. +#define NNG_OPT_TLS_CA_FILE "tls-ca-file" + +// NNG_OPT_TLS_SERVER_NAME is a write-only string that can typically be +// set on dialers to check the CN of the server for a match. This +// can also affect SNI (server name indication). It usually has no effect +// on listeners. +#define NNG_OPT_TLS_SERVER_NAME "tls-server-name" + +// 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. +#define NNG_OPT_TLS_VERIFIED "tls-verified" + // XXX: TBD: priorities, socket names, ipv4only // Statistics. These are for informational purposes only, and subject diff --git a/src/platform/posix/posix_thread.c b/src/platform/posix/posix_thread.c index 115768dc..d3817d91 100644 --- a/src/platform/posix/posix_thread.c +++ b/src/platform/posix/posix_thread.c @@ -64,6 +64,9 @@ nni_plat_mtx_fini(nni_plat_mtx *mtx) { if (mtx->flags & NNI_PLAT_SYNC_INIT) { int rv; + // Locking and unlocking makes valgrind/helgrind happier. + pthread_mutex_lock(&mtx->mtx); + pthread_mutex_unlock(&mtx->mtx); if ((rv = pthread_mutex_destroy(&mtx->mtx)) != 0) { nni_panic("pthread_mutex_destroy: %s", strerror(rv)); } diff --git a/src/supplemental/http/http.c b/src/supplemental/http/http.c index 229a4a99..43db1d15 100644 --- a/src/supplemental/http/http.c +++ b/src/supplemental/http/http.c @@ -40,6 +40,7 @@ typedef struct nni_http_tran { void (*h_write)(void *, nni_aio *); int (*h_sock_addr)(void *, nni_sockaddr *); int (*h_peer_addr)(void *, nni_sockaddr *); + bool (*h_verified)(void *); void (*h_close)(void *); void (*h_fini)(void *); } nni_http_tran; @@ -55,6 +56,7 @@ struct nni_http { void (*wr)(void *, nni_aio *); int (*sock_addr)(void *, nni_sockaddr *); int (*peer_addr)(void *, nni_sockaddr *); + bool (*verified)(void *); void (*close)(void *); void (*fini)(void *); @@ -610,6 +612,17 @@ nni_http_peer_addr(nni_http *http, nni_sockaddr *sa) return (rv); } +bool +nni_http_tls_verified(nni_http *http) +{ + bool rv; + + nni_mtx_lock(&http->mtx); + rv = http->closed ? false : http->verified(http->sock); + nni_mtx_unlock(&http->mtx); + return (rv); +} + void nni_http_fini(nni_http *http) { @@ -655,6 +668,7 @@ http_init(nni_http **httpp, nni_http_tran *tran, void *data) http->fini = tran->h_fini; http->sock_addr = tran->h_sock_addr; http->peer_addr = tran->h_peer_addr; + http->verified = tran->h_verified; if (((rv = nni_aio_init(&http->wr_aio, http_wr_cb, http)) != 0) || ((rv = nni_aio_init(&http->rd_aio, http_rd_cb, http)) != 0)) { @@ -667,6 +681,13 @@ http_init(nni_http **httpp, nni_http_tran *tran, void *data) return (0); } +static bool +nni_http_verified_tcp(void *arg) +{ + NNI_ARG_UNUSED(arg); + return (false); +} + static nni_http_tran http_tcp_ops = { .h_read = (void *) nni_plat_tcp_pipe_recv, .h_write = (void *) nni_plat_tcp_pipe_send, @@ -674,6 +695,7 @@ static nni_http_tran http_tcp_ops = { .h_fini = (void *) nni_plat_tcp_pipe_fini, .h_sock_addr = (void *) nni_plat_tcp_pipe_sockname, .h_peer_addr = (void *) nni_plat_tcp_pipe_peername, + .h_verified = nni_http_verified_tcp, }; int @@ -690,6 +712,7 @@ static nni_http_tran http_tls_ops = { .h_fini = (void *) nni_tls_fini, .h_sock_addr = (void *) nni_tls_sockname, .h_peer_addr = (void *) nni_tls_peername, + .h_verified = (void *) nni_tls_verified, }; int diff --git a/src/supplemental/http/http.h b/src/supplemental/http/http.h index 06394fdd..47c8d654 100644 --- a/src/supplemental/http/http.h +++ b/src/supplemental/http/http.h @@ -156,6 +156,9 @@ extern void nni_http_write_full(nni_http *, nni_aio *); extern int nni_http_sock_addr(nni_http *, nni_sockaddr *); extern int nni_http_peer_addr(nni_http *, nni_sockaddr *); +// nni_tls_http_verified returns true if the peer has been verified using TLS. +extern bool nni_http_tls_verified(nni_http *); + typedef struct nni_http_server nni_http_server; typedef struct { diff --git a/src/supplemental/tls/mbedtls/tls.c b/src/supplemental/tls/mbedtls/tls.c index 4e846f98..7b959b2b 100644 --- a/src/supplemental/tls/mbedtls/tls.c +++ b/src/supplemental/tls/mbedtls/tls.c @@ -751,13 +751,13 @@ nni_tls_ciphersuite_name(nni_tls *tp) return (mbedtls_ssl_get_ciphersuite(&tp->ctx)); } -int +bool nni_tls_verified(nni_tls *tp) { int rv; rv = mbedtls_ssl_get_verify_result(&tp->ctx); - return (rv ? 1 : 0); + return (rv ? true : false); } int diff --git a/src/supplemental/tls/tls.h b/src/supplemental/tls/tls.h index 5fde50b4..57b552d7 100644 --- a/src/supplemental/tls/tls.h +++ b/src/supplemental/tls/tls.h @@ -11,6 +11,8 @@ #ifndef NNG_SUPPLEMENTAL_TLS_TLS_H #define NNG_SUPPLEMENTAL_TLS_TLS_H +#include <stdbool.h> + // nni_tls represents the context for a single TLS stream. typedef struct nni_tls nni_tls; @@ -41,7 +43,7 @@ extern int nni_tls_peername(nni_tls *, nni_sockaddr *); // verify. (During the handshake phase, the peer is not verified, so this // might return false if executed too soon. The verification status will // be accurate once the handshake is finished, however. -extern int nni_tls_verified(nni_tls *); +extern bool nni_tls_verified(nni_tls *); // nni_tls_ciphersuite_name returns the name of the ciphersuite in use. extern const char *nni_tls_ciphersuite_name(nni_tls *); diff --git a/src/supplemental/websocket/websocket.c b/src/supplemental/websocket/websocket.c index fe4f002f..514cf22d 100644 --- a/src/supplemental/websocket/websocket.c +++ b/src/supplemental/websocket/websocket.c @@ -1072,6 +1072,17 @@ nni_ws_response_headers(nni_ws *ws) return (ws->reshdrs); } +bool +nni_ws_tls_verified(nni_ws *ws) +{ + bool rv; + + nni_mtx_lock(&ws->mtx); + rv = nni_http_tls_verified(ws->http); + nni_mtx_unlock(&ws->mtx); + return (rv); +} + static void ws_fini(void *arg) { diff --git a/src/supplemental/websocket/websocket.h b/src/supplemental/websocket/websocket.h index 9a52f78c..ddd09b72 100644 --- a/src/supplemental/websocket/websocket.h +++ b/src/supplemental/websocket/websocket.h @@ -11,6 +11,8 @@ #ifndef NNG_SUPPLEMENTAL_WEBSOCKET_WEBSOCKET_H #define NNG_SUPPLEMENTAL_WEBSOCKET_WEBSOCKET_H +#include <stdbool.h> + // Pre-defined types for some prototypes. These are from other subsystems. typedef struct nni_http_req nni_http_req; typedef struct nni_http_res nni_http_res; @@ -63,6 +65,7 @@ extern void nni_ws_close_error(nni_ws *, uint16_t); extern void nni_ws_fini(nni_ws *); extern const char * nni_ws_response_headers(nni_ws *); extern const char * nni_ws_request_headers(nni_ws *); +extern bool nni_ws_tls_verified(nni_ws *); // The implementation will send periodic PINGs, and respond with PONGs. diff --git a/src/transport/tls/tls.c b/src/transport/tls/tls.c index 408ff50c..05d477b5 100644 --- a/src/transport/tls/tls.c +++ b/src/transport/tls/tls.c @@ -855,7 +855,7 @@ tls_getopt_verified(void *arg, void *v, size_t *szp) static nni_tran_pipe_option nni_tls_pipe_options[] = { { NNG_OPT_LOCADDR, nni_tls_pipe_getopt_locaddr }, { NNG_OPT_REMADDR, nni_tls_pipe_getopt_remaddr }, - { NNG_OPT_TLS_AUTH_VERIFIED, tls_getopt_verified }, + { NNG_OPT_TLS_VERIFIED, tls_getopt_verified }, // terminate list { NULL, NULL } }; diff --git a/src/transport/tls/tls.h b/src/transport/tls/tls.h index 25edfa3a..a3fa0eb9 100644 --- a/src/transport/tls/tls.h +++ b/src/transport/tls/tls.h @@ -15,16 +15,4 @@ NNG_DECL int nng_tls_register(void); -// TLS options. Note that these can only be set *before* the endpoint is -// started. Once started, it is no longer possible to alter the TLS -// configuration. - -// NNG_OPT_TLS_AUTH_VERIFIED is a boolean that can be read on pipes, -// indicating whether the peer certificate is verified. -#define NNG_OPT_TLS_AUTH_VERIFIED "tls:auth-verified" - -// NNG_OPT_TLS_CONFIG is used to access the underlying configuration -// (an nng_tls_config *). -#define NNG_OPT_TLS_CONFIG "tls:config" - #endif // NNG_TRANSPORT_TLS_TLS_H diff --git a/src/transport/ws/websocket.c b/src/transport/ws/websocket.c index 16cdf47b..a06910d3 100644 --- a/src/transport/ws/websocket.c +++ b/src/transport/ws/websocket.c @@ -43,6 +43,7 @@ struct ws_ep { nni_ws_listener *listener; nni_ws_dialer * dialer; nni_list headers; // to send, res or req + bool started; }; struct ws_pipe { @@ -261,16 +262,13 @@ ws_hook(void *arg, nni_http_req *req, nni_http_res *res) // Eventually we'll want user customizable hooks. // For now we just set the headers we want. - nni_mtx_lock(&ep->mtx); NNI_LIST_FOREACH (&ep->headers, h) { int rv; - rv = nni_http_req_set_header(req, h->name, h->value); + rv = nni_http_res_set_header(res, h->name, h->value); if (rv != 0) { - nni_mtx_unlock(&ep->mtx); return (rv); } } - nni_mtx_unlock(&ep->mtx); return (0); } @@ -278,9 +276,13 @@ static int ws_ep_bind(void *arg) { ws_ep *ep = arg; + int rv; nni_ws_listener_hook(ep->listener, ws_hook, ep); - return (nni_ws_listener_listen(ep->listener)); + if ((rv = nni_ws_listener_listen(ep->listener)) == 0) { + ep->started = true; + } + return (rv); } static void @@ -320,28 +322,29 @@ static void ws_ep_connect(void *arg, nni_aio *aio) { ws_ep * ep = arg; - int rv; + int rv = 0; ws_hdr *h; + if (!ep->started) { + NNI_LIST_FOREACH (&ep->headers, h) { + rv = nni_ws_dialer_header( + ep->dialer, h->name, h->value); + if (rv != 0) { + nni_aio_finish_error(aio, rv); + return; + } + } + } + nni_mtx_lock(&ep->mtx); NNI_ASSERT(nni_list_empty(&ep->aios)); - // If we can't start, then its dying and we can't report - // either. + // If we can't start, then its dying and we can't report either. if ((rv = nni_aio_start(aio, ws_ep_cancel, ep)) != 0) { nni_mtx_unlock(&ep->mtx); return; } - - NNI_LIST_FOREACH (&ep->headers, h) { - rv = nni_ws_dialer_header(ep->dialer, h->name, h->value); - if (rv != 0) { - nni_aio_finish_error(aio, rv); - nni_mtx_unlock(&ep->mtx); - return; - } - } - + ep->started = true; nni_list_append(&ep->aios, aio); nni_ws_dialer_dial(ep->dialer, ep->connaio); nni_mtx_unlock(&ep->mtx); @@ -374,6 +377,10 @@ ws_ep_setopt_headers(ws_ep *ep, const void *v, size_t sz) return (0); } + if (ep->started) { + return (NNG_EBUSY); + } + NNI_LIST_INIT(&l, ws_hdr, node); if ((dupstr = nni_strdup(v)) == NULL) { return (NNG_ENOMEM); @@ -418,7 +425,6 @@ ws_ep_setopt_headers(ws_ep *ep, const void *v, size_t sz) name = nl; } - nni_mtx_lock(&ep->mtx); while ((h = nni_list_first(&ep->headers)) != NULL) { nni_list_remove(&ep->headers, h); nni_strfree(h->name); @@ -429,7 +435,6 @@ ws_ep_setopt_headers(ws_ep *ep, const void *v, size_t sz) nni_list_remove(&l, h); nni_list_append(&ep->headers, h); } - nni_mtx_unlock(&ep->mtx); rv = 0; done: @@ -532,6 +537,13 @@ ws_pipe_getopt_reqhdrs(void *arg, void *v, size_t *szp) return (nni_getopt_str(s, v, szp)); } +static int +ws_pipe_getopt_tls_verified(void *arg, void *v, size_t *szp) +{ + ws_pipe *p = arg; + return (nni_getopt_int(nni_ws_tls_verified(p->ws) ? 1 : 0, v, szp)); +} + static nni_tran_pipe_option ws_pipe_options[] = { // clang-format off @@ -539,6 +551,7 @@ static nni_tran_pipe_option ws_pipe_options[] = { { NNG_OPT_REMADDR, ws_pipe_getopt_remaddr }, { NNG_OPT_WS_REQUEST_HEADERS, ws_pipe_getopt_reqhdrs }, { NNG_OPT_WS_RESPONSE_HEADERS, ws_pipe_getopt_reshdrs }, + { NNG_OPT_TLS_VERIFIED, ws_pipe_getopt_tls_verified }, // clang-format on // terminate list @@ -931,37 +944,37 @@ static nni_tran_ep_option wss_ep_options[] = { .eo_setopt = ws_ep_setopt_recvmaxsz, }, { - .eo_name = NNG_OPT_WSS_REQUEST_HEADERS, + .eo_name = NNG_OPT_WS_REQUEST_HEADERS, .eo_getopt = NULL, .eo_setopt = ws_ep_setopt_reqhdrs, }, { - .eo_name = NNG_OPT_WSS_RESPONSE_HEADERS, + .eo_name = NNG_OPT_WS_RESPONSE_HEADERS, .eo_getopt = NULL, .eo_setopt = ws_ep_setopt_reshdrs, }, { - .eo_name = NNG_OPT_WSS_TLS_CONFIG, + .eo_name = NNG_OPT_TLS_CONFIG, .eo_getopt = wss_ep_getopt_tlsconfig, .eo_setopt = wss_ep_setopt_tlsconfig, }, { - .eo_name = NNG_OPT_WSS_TLS_CERT_KEY_FILE, + .eo_name = NNG_OPT_TLS_CERT_KEY_FILE, .eo_getopt = NULL, .eo_setopt = wss_ep_setopt_tls_cert_key_file, }, { - .eo_name = NNG_OPT_WSS_TLS_CA_FILE, + .eo_name = NNG_OPT_TLS_CA_FILE, .eo_getopt = NULL, .eo_setopt = wss_ep_setopt_tls_ca_file, }, { - .eo_name = NNG_OPT_WSS_TLS_AUTH_MODE, + .eo_name = NNG_OPT_TLS_AUTH_MODE, .eo_getopt = NULL, .eo_setopt = wss_ep_setopt_tls_auth_mode, }, { - .eo_name = NNG_OPT_WSS_TLS_SERVER_NAME, + .eo_name = NNG_OPT_TLS_SERVER_NAME, .eo_getopt = NULL, .eo_setopt = wss_ep_setopt_tls_server_name, }, diff --git a/src/transport/ws/websocket.h b/src/transport/ws/websocket.h index 1f261067..76e94c3e 100644 --- a/src/transport/ws/websocket.h +++ b/src/transport/ws/websocket.h @@ -23,60 +23,6 @@ NNG_DECL int nng_ws_register(void); // response headers, formatted as CRLF terminated lines. #define NNG_OPT_WS_RESPONSE_HEADERS "ws:response-headers" -// NNG_OPT_WSS_TLS_CONFIG is a pointer to a an nng_tls_config -// object. This property is only available for wss:// style -// endpoints. Note that when configuring the object, a hold -// is placed on the TLS configuration. When retrieving the -// object, no hold is placed, and so the caller must take care -// not to use the configuration object after the endpoint it -// is associated with is removed. Furthermore, as this is a -// pointer, applications must take care to pass only valid -// data -- incorrect pointer values will lead to undefined -// behavior. -#define NNG_OPT_WSS_TLS_CONFIG "wss:tls-config" - -// NNG_OPT_WSS_TLS_CERT_KEY_FILE names a single file that -// contains a certificate and key identifying ourself. This -// is a write-only value. Listeners can call this multiple -// times for different keys/certs corresponding to different -// algorithms, whereas clients only get one. The file must -// contain both cert and key as PEM blocks, and the key must -// not be encrypted. (If more flexibility is needed, use the -// TLS configuration directly.) Note that TLS configuration -// cannot be changed if the listener, or any other from the same -// server and port, is already started. -#define NNG_OPT_WSS_TLS_CERT_KEY_FILE "wss:tls-cert-key-file" - -// NNG_OPT_WSS_TLS_CA_FILE names a single file that -// contains certificate(s) for a CA, and optinally CRLs. This -// is a write-only value. Listeners can call this multiple -// times for different keys/certs corresponding to different -// algorithms, whereas clients only get one. The file must -// contain certs as PEM blocks, and may contain CRLs as PEM -// as well. (If more flexibility is needed, use the -// TLS configuration directly.) Note that TLS configuration -// cannot be changed if the listener, or any other from the same -// server and port, is already started. -#define NNG_OPT_WSS_TLS_CA_FILE "wss:tls-ca-file" - -// NNG_OPT_WSS_TLS_AUTH_MODE is a write-only integer (int) option -// that specifies whether the peer is verified or not. The option -// can take one of the values of NNG_TLS_AUTH_MODE_NONE, -// NNG_TLS_AUTH_MODE_OPTIONAL, or NNG_TLS_AUTH_MODE_REQUIRED. -// The default is NNG_TLS_AUTH_MODE_NONE for listeners, and -// NNG_TLS_AUTH_MODE_REQUIRED for dialers. -#define NNG_OPT_WSS_TLS_AUTH_MODE "wss:tls-auth-mode" - -// NNG_OPT_WSS_TLS_SERVER_NAME is a write-only string that can be -// set on dialers to check the CN of the server for a match. This -// can also affect SNI (server name indication). -#define NNG_OPT_WSS_TLS_SERVER_NAME "wss:tls-server-name" - -// NNG_OPT_WSS_TLS_VERIFIED returns a single integer, indicating -// whether the peer was verified or not. This is a read-only value -// available only on pipes. -#define NNT_OPT_WSS_TLS_VERIFIED "wss:tls-verified" - // These aliases are for WSS naming consistency. #define NNG_OPT_WSS_REQUEST_HEADERS NNG_OPT_WS_REQUEST_HEADERS #define NNG_OPT_WSS_RESPONSE_HEADERS NNG_OPT_WS_RESPONSE_HEADERS diff --git a/tests/wss.c b/tests/wss.c index c087ed1e..aee982c8 100644 --- a/tests/wss.c +++ b/tests/wss.c @@ -198,7 +198,7 @@ init_dialer_wss(trantest *tt, nng_dialer d) 0) { goto out; } - rv = nng_dialer_setopt_ptr(d, NNG_OPT_WSS_TLS_CONFIG, cfg); + rv = nng_dialer_setopt_ptr(d, NNG_OPT_TLS_CONFIG, cfg); out: nng_tls_config_free(cfg); @@ -218,8 +218,7 @@ init_listener_wss(trantest *tt, nng_listener l) goto out; } - if ((rv = nng_listener_setopt_ptr(l, NNG_OPT_WSS_TLS_CONFIG, cfg)) != - 0) { + if ((rv = nng_listener_setopt_ptr(l, NNG_OPT_TLS_CONFIG, cfg)) != 0) { // We can wind up with EBUSY from the server already running. if (rv == NNG_EBUSY) { rv = 0; diff --git a/tests/wssfile.c b/tests/wssfile.c index 120e575d..73a0050b 100644 --- a/tests/wssfile.c +++ b/tests/wssfile.c @@ -138,6 +138,7 @@ check_props(nng_msg *msg, nng_listener l, nng_dialer d) nng_sockaddr ra; char * buf; size_t len; + int v; p = nng_msg_get_pipe(msg); So(p > 0); @@ -176,6 +177,10 @@ 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); } @@ -200,7 +205,7 @@ init_dialer_wss_file(trantest *tt, nng_dialer d) return (rv); } - rv = nng_dialer_setopt_string(d, NNG_OPT_WSS_TLS_CA_FILE, pth); + rv = nng_dialer_setopt_string(d, NNG_OPT_TLS_CA_FILE, pth); nni_file_delete(pth); nni_strfree(pth); @@ -237,7 +242,7 @@ init_listener_wss_file(trantest *tt, nng_listener l) return (rv); } - rv = nng_listener_setopt_string(l, NNG_OPT_WSS_TLS_CERT_KEY_FILE, pth); + 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. @@ -284,7 +289,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_WSS_TLS_AUTH_MODE, + 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); @@ -294,9 +299,10 @@ TestMain("WebSocket Secure (TLS) Transport (file based)", { nng_socket s1; nng_socket s2; nng_listener l; - char * buf; - size_t sz; char addr[NNG_MAXADDRLEN]; + nng_msg * msg; + nng_pipe p; + int v; So(nng_pair_open(&s1) == 0); So(nng_pair_open(&s2) == 0); @@ -312,17 +318,22 @@ 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_WSS_TLS_AUTH_MODE, + So(nng_setopt_int(s2, NNG_OPT_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); + 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); }); nng_fini(); |
