aboutsummaryrefslogtreecommitdiff
path: root/src/supplemental
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2024-11-09 20:10:32 -0800
committerGarrett D'Amore <garrett@damore.org>2024-11-09 20:22:50 -0800
commitcbe9a27ef7485977fbc7c713376b096b6723da3d (patch)
treebaba50d93018ac6ce6873be46284f5f893da6e39 /src/supplemental
parent0058b766b91f08b34dcef3c7bb55b216099f3f66 (diff)
downloadnng-cbe9a27ef7485977fbc7c713376b096b6723da3d.tar.gz
nng-cbe9a27ef7485977fbc7c713376b096b6723da3d.tar.bz2
nng-cbe9a27ef7485977fbc7c713376b096b6723da3d.zip
websocket: Do not allow a listener or dialer to change TLS while running
This also covers a few test cases that we were missing.
Diffstat (limited to 'src/supplemental')
-rw-r--r--src/supplemental/tls/tls_common.c19
-rw-r--r--src/supplemental/websocket/wssfile_test.c58
2 files changed, 77 insertions, 0 deletions
diff --git a/src/supplemental/tls/tls_common.c b/src/supplemental/tls/tls_common.c
index 49d1a292..b197af91 100644
--- a/src/supplemental/tls/tls_common.c
+++ b/src/supplemental/tls/tls_common.c
@@ -102,6 +102,7 @@ typedef struct {
nng_stream_dialer ops;
nng_stream_dialer *d; // underlying TCP dialer
nng_tls_config *cfg;
+ bool started;
nni_mtx lk; // protects the config
} tls_dialer;
@@ -186,6 +187,9 @@ tls_dialer_dial(void *arg, nng_aio *aio)
tls_free(conn);
return;
}
+ nni_mtx_lock(&d->lk);
+ d->started = true;
+ nni_mtx_unlock(&d->lk);
nng_stream_dialer_dial(d->d, &conn->conn_aio);
}
@@ -198,9 +202,15 @@ tls_dialer_set_tls(void *arg, nng_tls_config *cfg)
if (cfg == NULL) {
return (NNG_EINVAL);
}
+
nng_tls_config_hold(cfg);
nni_mtx_lock(&d->lk);
+ if (d->started) {
+ nni_mtx_unlock(&d->lk);
+ nng_tls_config_free(cfg);
+ return (NNG_EBUSY);
+ }
old = d->cfg;
d->cfg = cfg;
nni_mtx_unlock(&d->lk);
@@ -287,6 +297,7 @@ typedef struct {
nng_stream_listener ops;
nng_stream_listener *l;
nng_tls_config *cfg;
+ bool started;
nni_mtx lk;
} tls_listener;
@@ -314,6 +325,9 @@ static int
tls_listener_listen(void *arg)
{
tls_listener *l = arg;
+ nni_mtx_lock(&l->lk);
+ l->started = true;
+ nni_mtx_unlock(&l->lk);
return (nng_stream_listener_listen(l->l));
}
@@ -352,6 +366,11 @@ tls_listener_set_tls(void *arg, nng_tls_config *cfg)
nng_tls_config_hold(cfg);
nni_mtx_lock(&l->lk);
+ if (l->started) {
+ nni_mtx_unlock(&l->lk);
+ nng_tls_config_free(cfg);
+ return (NNG_EBUSY);
+ }
old = l->cfg;
l->cfg = cfg;
nni_mtx_unlock(&l->lk);
diff --git a/src/supplemental/websocket/wssfile_test.c b/src/supplemental/websocket/wssfile_test.c
index 584f8481..972f040f 100644
--- a/src/supplemental/websocket/wssfile_test.c
+++ b/src/supplemental/websocket/wssfile_test.c
@@ -9,6 +9,7 @@
//
#include "core/nng_impl.h"
+#include "nng/nng.h"
#include "nng/supplemental/tls/tls.h"
#include <nuts.h>
@@ -214,6 +215,62 @@ test_cert_file_not_present(void)
nng_tls_config_free(c);
}
+static void
+test_tls_config(void)
+{
+ uint16_t port = nuts_next_port();
+ nng_socket s1;
+ nng_socket s2;
+ nng_listener l;
+ nng_dialer d;
+ char addr[40];
+ nng_tls_config *cfg;
+
+ (void) snprintf(addr, sizeof(addr), "wss4://:%u/test", port);
+
+ NUTS_PASS(nng_pair_open(&s1));
+ NUTS_PASS(nng_pair_open(&s2));
+ NUTS_PASS(nng_listener_create(&l, s1, addr));
+ NUTS_PASS(nng_listener_get_tls(l, &cfg));
+ nng_tls_config_hold(cfg);
+ NUTS_TRUE(cfg != NULL);
+
+ init_listener_wss_file(l);
+ NUTS_PASS(nng_listener_start(l, 0));
+
+ // make sure we cannot change the auth mode while running
+
+ NUTS_FAIL(nng_listener_set_tls(l, cfg), NNG_EBUSY);
+ nng_tls_config_free(cfg);
+
+ NUTS_PASS(nng_listener_get_tls(l, &cfg));
+
+ NUTS_FAIL(
+ nng_tls_config_auth_mode(cfg, NNG_TLS_AUTH_MODE_NONE), NNG_EBUSY);
+
+ nng_msleep(100);
+
+ snprintf(addr, sizeof(addr), "wss://127.0.0.1:%u/test", port);
+
+ // We find that sometimes this fails due to NNG_EPEERAUTH, but it
+ // can also fail due to NNG_ECLOSED. This seems to be timing
+ // dependent, based on receive vs. send timing most likely.
+ // Applications shouldn't really depend that much on this.
+ int rv;
+
+ NUTS_PASS(nng_dialer_create(&d, s2, addr));
+ rv = nng_dialer_start(d, 0);
+ NUTS_PASS(nng_dialer_get_tls(d, &cfg));
+ NUTS_FAIL(nng_dialer_set_tls(d, cfg), NNG_EBUSY);
+
+ NUTS_TRUE(rv != 0);
+ NUTS_TRUE((rv == NNG_EPEERAUTH) || (rv == NNG_ECLOSED) ||
+ (rv == NNG_ECRYPTO));
+
+ NUTS_PASS(nng_close(s1));
+ NUTS_PASS(nng_close(s2));
+}
+
#endif
NUTS_TESTS = {
@@ -222,6 +279,7 @@ NUTS_TESTS = {
{ "wss file no verify", test_no_verify },
{ "wss file verify works", test_verify_works },
{ "wss file ca cert missing", test_cert_file_not_present },
+ { "wss tls config", test_tls_config },
#endif
{ NULL, NULL },
};