diff options
| -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(); |
