From adba870534bdcdd11f0f344e66090be8e2cd9ae4 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Fri, 20 Jan 2023 01:51:35 +0100 Subject: [NET] Refactor TLS configuration. Use a TLSOptions configuration object which is created via static functions. - "TLSOptions.client": uses the standard CA and common name verification. - "TLSOptions.client_unsafe": uses optional CA verification (i.e. if specified) - "TLSOptions.server": is the standard server configuration (chain + key) This will allow us to expand the TLS configuration options to include e.g. mutual authentication without bloating the classes that uses StreamPeerTLS and PacketPeerDTLS as underlying peers. --- .../doc_classes/WebSocketMultiplayerPeer.xml | 10 ++++---- modules/websocket/doc_classes/WebSocketPeer.xml | 5 ++-- modules/websocket/emws_peer.cpp | 6 ++--- modules/websocket/emws_peer.h | 2 +- modules/websocket/websocket_multiplayer_peer.cpp | 27 +++++++++------------- modules/websocket/websocket_multiplayer_peer.h | 8 +++---- modules/websocket/websocket_peer.cpp | 2 +- modules/websocket/websocket_peer.h | 2 +- modules/websocket/wsl_peer.cpp | 14 +++++++---- modules/websocket/wsl_peer.h | 5 ++-- 10 files changed, 37 insertions(+), 44 deletions(-) (limited to 'modules/websocket') diff --git a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml index 7e896a0ca3..aaeb2025ee 100644 --- a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml +++ b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml @@ -13,10 +13,9 @@ - - + - Starts a new multiplayer client connecting to the given [param url]. If [param verify_tls] is [code]false[/code] certificate validation will be disabled. If specified, the [param tls_certificate] will be used to verify the TLS host. + Starts a new multiplayer client connecting to the given [param url]. TLS certificates will be verified against the hostname when connecting using the [code]wss://[/code] protocol. You can pass the optional [param tls_client_options] parameter to customize the trusted certification authorities, or disable the common name verification. See [method TLSOptions.client] and [method TLSOptions.client_unsafe]. [b]Note[/b]: It is recommended to specify the scheme part of the URL, i.e. the [param url] should start with either [code]ws://[/code] or [code]wss://[/code]. @@ -24,10 +23,9 @@ - - + - Starts a new multiplayer server listening on the given [param port]. You can optionally specify a [param bind_address], and provide a [param tls_key] and [param tls_certificate] to use TLS. + Starts a new multiplayer server listening on the given [param port]. You can optionally specify a [param bind_address], and provide valiid [param tls_server_options] to use TLS. See [method TLSOptions.server]. diff --git a/modules/websocket/doc_classes/WebSocketPeer.xml b/modules/websocket/doc_classes/WebSocketPeer.xml index 41d166a0f5..0f8c27c4cc 100644 --- a/modules/websocket/doc_classes/WebSocketPeer.xml +++ b/modules/websocket/doc_classes/WebSocketPeer.xml @@ -58,10 +58,9 @@ - - + - Connects to the given URL. If [param verify_tls] is [code]false[/code] certificate validation will be disabled. If specified, the [param trusted_tls_certificate] will be the only one accepted when connecting to a TLS host. + Connects to the given URL. TLS certificates will be verified against the hostname when connecting using the [code]wss://[/code] protocol. You can pass the optional [param tls_client_options] parameter to customize the trusted certification authorities, or disable the common name verification. See [method TLSOptions.client] and [method TLSOptions.client_unsafe]. [b]Note:[/b] To avoid mixed content warnings or errors in Web, you may have to use a [code]url[/code] that starts with [code]wss://[/code] (secure) instead of [code]ws://[/code]. When doing so, make sure to use the fully qualified domain name that matches the one defined in the server's TLS certificate. Do not connect directly via the IP address for [code]wss://[/code] connections, as it won't match with the TLS certificate. diff --git a/modules/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp index 1ec557427f..7b14a3a61d 100644 --- a/modules/websocket/emws_peer.cpp +++ b/modules/websocket/emws_peer.cpp @@ -58,7 +58,8 @@ void EMWSPeer::_esws_on_close(void *p_obj, int p_code, const char *p_reason, int peer->ready_state = STATE_CLOSED; } -Error EMWSPeer::connect_to_url(const String &p_url, bool p_verify_tls, Ref p_tls_certificate) { +Error EMWSPeer::connect_to_url(const String &p_url, Ref p_tls_options) { + ERR_FAIL_COND_V(p_tls_options.is_valid() && p_tls_options->is_server(), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(ready_state != STATE_CLOSED, ERR_ALREADY_IN_USE); _clear(); @@ -85,9 +86,6 @@ Error EMWSPeer::connect_to_url(const String &p_url, bool p_verify_tls, Ref p_cert = Ref()) override; + virtual Error connect_to_url(const String &p_url, Ref p_tls_client_options) override; virtual Error accept_stream(Ref p_stream) override; virtual void close(int p_code = 1000, String p_reason = "") override; virtual void poll() override; diff --git a/modules/websocket/websocket_multiplayer_peer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp index 36b4215f8c..389d8c56ad 100644 --- a/modules/websocket/websocket_multiplayer_peer.cpp +++ b/modules/websocket/websocket_multiplayer_peer.cpp @@ -54,11 +54,9 @@ void WebSocketMultiplayerPeer::_clear() { connection_status = CONNECTION_DISCONNECTED; unique_id = 0; peers_map.clear(); - use_tls = false; tcp_server.unref(); pending_peers.clear(); - tls_certificate.unref(); - tls_key.unref(); + tls_server_options.unref(); if (current_packet.data != nullptr) { memfree(current_packet.data); current_packet.data = nullptr; @@ -73,8 +71,8 @@ void WebSocketMultiplayerPeer::_clear() { } void WebSocketMultiplayerPeer::_bind_methods() { - ClassDB::bind_method(D_METHOD("create_client", "url", "verify_tls", "tls_certificate"), &WebSocketMultiplayerPeer::create_client, DEFVAL(true), DEFVAL(Ref())); - ClassDB::bind_method(D_METHOD("create_server", "port", "bind_address", "tls_key", "tls_certificate"), &WebSocketMultiplayerPeer::create_server, DEFVAL("*"), DEFVAL(Ref()), DEFVAL(Ref())); + ClassDB::bind_method(D_METHOD("create_client", "url", "tls_client_options"), &WebSocketMultiplayerPeer::create_client, DEFVAL(Ref())); + ClassDB::bind_method(D_METHOD("create_server", "port", "bind_address", "tls_server_options"), &WebSocketMultiplayerPeer::create_server, DEFVAL("*"), DEFVAL(Ref())); ClassDB::bind_method(D_METHOD("get_peer", "peer_id"), &WebSocketMultiplayerPeer::get_peer); ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &WebSocketMultiplayerPeer::get_peer_address); @@ -179,8 +177,9 @@ int WebSocketMultiplayerPeer::get_max_packet_size() const { return get_outbound_buffer_size() - PROTO_SIZE; } -Error WebSocketMultiplayerPeer::create_server(int p_port, IPAddress p_bind_ip, Ref p_tls_key, Ref p_tls_certificate) { +Error WebSocketMultiplayerPeer::create_server(int p_port, IPAddress p_bind_ip, Ref p_options) { ERR_FAIL_COND_V(get_connection_status() != CONNECTION_DISCONNECTED, ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(p_options.is_valid() && !p_options->is_server(), ERR_INVALID_PARAMETER); _clear(); tcp_server.instantiate(); Error err = tcp_server->listen(p_port, p_bind_ip); @@ -190,20 +189,16 @@ Error WebSocketMultiplayerPeer::create_server(int p_port, IPAddress p_bind_ip, R } unique_id = 1; connection_status = CONNECTION_CONNECTED; - // TLS config - tls_key = p_tls_key; - tls_certificate = p_tls_certificate; - if (tls_key.is_valid() && tls_certificate.is_valid()) { - use_tls = true; - } + tls_server_options = p_options; return OK; } -Error WebSocketMultiplayerPeer::create_client(const String &p_url, bool p_verify_tls, Ref p_tls_certificate) { +Error WebSocketMultiplayerPeer::create_client(const String &p_url, Ref p_options) { ERR_FAIL_COND_V(get_connection_status() != CONNECTION_DISCONNECTED, ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(p_options.is_valid() && p_options->is_server(), ERR_INVALID_PARAMETER); _clear(); Ref peer = _create_peer(); - Error err = peer->connect_to_url(p_url, p_verify_tls, p_tls_certificate); + Error err = peer->connect_to_url(p_url, p_options); if (err != OK) { return err; } @@ -334,14 +329,14 @@ void WebSocketMultiplayerPeer::_poll_server() { to_remove.insert(id); // Error. continue; } - if (!use_tls) { + if (tls_server_options.is_null()) { peer.ws = _create_peer(); peer.ws->accept_stream(peer.tcp); continue; } else { if (peer.connection == peer.tcp) { Ref tls = Ref(StreamPeerTLS::create()); - Error err = tls->accept_stream(peer.tcp, tls_key, tls_certificate); + Error err = tls->accept_stream(peer.tcp, tls_server_options); if (err != OK) { to_remove.insert(id); continue; diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h index ea10e8799f..22f1bc939b 100644 --- a/modules/websocket/websocket_multiplayer_peer.h +++ b/modules/websocket/websocket_multiplayer_peer.h @@ -71,9 +71,7 @@ protected: Ref peer_config; HashMap pending_peers; Ref tcp_server; - bool use_tls = false; - Ref tls_certificate; - Ref tls_key; + Ref tls_server_options; ConnectionStatus connection_status = CONNECTION_DISCONNECTED; @@ -115,8 +113,8 @@ public: /* WebSocketPeer */ virtual Ref get_peer(int p_peer_id) const; - Error create_client(const String &p_url, bool p_verify_tls, Ref p_tls_certificate); - Error create_server(int p_port, IPAddress p_bind_ip, Ref p_tls_key, Ref p_tls_certificate); + Error create_client(const String &p_url, Ref p_options); + Error create_server(int p_port, IPAddress p_bind_ip, Ref p_options); void set_supported_protocols(const Vector &p_protocols); Vector get_supported_protocols() const; diff --git a/modules/websocket/websocket_peer.cpp b/modules/websocket/websocket_peer.cpp index d10315f64c..3c0d316bc9 100644 --- a/modules/websocket/websocket_peer.cpp +++ b/modules/websocket/websocket_peer.cpp @@ -39,7 +39,7 @@ WebSocketPeer::~WebSocketPeer() { } void WebSocketPeer::_bind_methods() { - ClassDB::bind_method(D_METHOD("connect_to_url", "url", "verify_tls", "trusted_tls_certificate"), &WebSocketPeer::connect_to_url, DEFVAL(true), DEFVAL(Ref())); + ClassDB::bind_method(D_METHOD("connect_to_url", "url", "tls_client_options"), &WebSocketPeer::connect_to_url, DEFVAL(Ref())); ClassDB::bind_method(D_METHOD("accept_stream", "stream"), &WebSocketPeer::accept_stream); ClassDB::bind_method(D_METHOD("send", "message", "write_mode"), &WebSocketPeer::_send_bind, DEFVAL(WRITE_MODE_BINARY)); ClassDB::bind_method(D_METHOD("send_text", "message"), &WebSocketPeer::send_text); diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index 3a1527b769..3110e87071 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -81,7 +81,7 @@ public: return _create(); } - virtual Error connect_to_url(const String &p_url, bool p_verify_tls = true, Ref p_cert = Ref()) { return ERR_UNAVAILABLE; }; + virtual Error connect_to_url(const String &p_url, Ref p_options = Ref()) = 0; virtual Error accept_stream(Ref p_stream) = 0; virtual Error send(const uint8_t *p_buffer, int p_buffer_size, WriteMode p_mode) = 0; diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp index 9ba286d5ee..6240f2eaea 100644 --- a/modules/websocket/wsl_peer.cpp +++ b/modules/websocket/wsl_peer.cpp @@ -334,7 +334,7 @@ void WSLPeer::_do_client_handshake() { tls = Ref(StreamPeerTLS::create()); ERR_FAIL_COND_MSG(tls.is_null(), "SSL is not available in this build."); tls->set_blocking_handshake_enabled(false); - if (tls->connect_to_stream(tcp, verify_tls, requested_host, tls_cert) != OK) { + if (tls->connect_to_stream(tcp, requested_host, tls_options) != OK) { close(-1); return; // Error. } @@ -476,9 +476,10 @@ bool WSLPeer::_verify_server_response() { return true; } -Error WSLPeer::connect_to_url(const String &p_url, bool p_verify_tls, Ref p_cert) { +Error WSLPeer::connect_to_url(const String &p_url, Ref p_options) { ERR_FAIL_COND_V(wsl_ctx || tcp.is_valid(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(p_url.is_empty(), ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(p_options.is_valid() && p_options->is_server(), ERR_INVALID_PARAMETER); _clear(); @@ -506,8 +507,13 @@ Error WSLPeer::connect_to_url(const String &p_url, bool p_verify_tls, Ref tls_cert; + Ref tls_options; // Packet buffers. Vector packet_buffer; @@ -132,7 +131,7 @@ public: // WebSocketPeer virtual Error send(const uint8_t *p_buffer, int p_buffer_size, WriteMode p_mode) override; - virtual Error connect_to_url(const String &p_url, bool p_verify_tls = true, Ref p_cert = Ref()) override; + virtual Error connect_to_url(const String &p_url, Ref p_options = Ref()) override; virtual Error accept_stream(Ref p_stream) override; virtual void close(int p_code = 1000, String p_reason = "") override; virtual void poll() override; -- cgit v1.2.3