summaryrefslogtreecommitdiff
path: root/modules/websocket
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2023-01-30 13:28:31 +0100
committerRémi Verschelde <rverschelde@gmail.com>2023-01-30 13:28:31 +0100
commitbde3310f02196c5a0962153426fd0209020af5a6 (patch)
tree2bf302ea12ecc3834bdacfde0369437469fcf92e /modules/websocket
parent6c19a619adbcafd33603b6993e7a8b2452269b68 (diff)
parent7cd80e6a6dd48019fb292e49eab10eefff293132 (diff)
Merge pull request #71995 from Faless/net/4.x_tls_verify
[NET] Refactor TLS configuration.
Diffstat (limited to 'modules/websocket')
-rw-r--r--modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml10
-rw-r--r--modules/websocket/doc_classes/WebSocketPeer.xml5
-rw-r--r--modules/websocket/emws_peer.cpp6
-rw-r--r--modules/websocket/emws_peer.h2
-rw-r--r--modules/websocket/websocket_multiplayer_peer.cpp27
-rw-r--r--modules/websocket/websocket_multiplayer_peer.h8
-rw-r--r--modules/websocket/websocket_peer.cpp2
-rw-r--r--modules/websocket/websocket_peer.h2
-rw-r--r--modules/websocket/wsl_peer.cpp15
-rw-r--r--modules/websocket/wsl_peer.h5
10 files changed, 37 insertions, 45 deletions
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 @@
<method name="create_client">
<return type="int" enum="Error" />
<param index="0" name="url" type="String" />
- <param index="1" name="verify_tls" type="bool" default="true" />
- <param index="2" name="tls_certificate" type="X509Certificate" default="null" />
+ <param index="1" name="tls_client_options" type="TLSOptions" default="null" />
<description>
- 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].
</description>
</method>
@@ -24,10 +23,9 @@
<return type="int" enum="Error" />
<param index="0" name="port" type="int" />
<param index="1" name="bind_address" type="String" default="&quot;*&quot;" />
- <param index="2" name="tls_key" type="CryptoKey" default="null" />
- <param index="3" name="tls_certificate" type="X509Certificate" default="null" />
+ <param index="2" name="tls_server_options" type="TLSOptions" default="null" />
<description>
- 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].
</description>
</method>
<method name="get_peer" qualifiers="const">
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 @@
<method name="connect_to_url">
<return type="int" enum="Error" />
<param index="0" name="url" type="String" />
- <param index="1" name="verify_tls" type="bool" default="true" />
- <param index="2" name="trusted_tls_certificate" type="X509Certificate" default="null" />
+ <param index="1" name="tls_client_options" type="TLSOptions" default="null" />
<description>
- 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.
</description>
</method>
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<X509Certificate> p_tls_certificate) {
+Error EMWSPeer::connect_to_url(const String &p_url, Ref<TLSOptions> 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<X509C
if (handshake_headers.size()) {
WARN_PRINT_ONCE("Custom headers are not supported in Web platform.");
}
- if (p_tls_certificate.is_valid()) {
- WARN_PRINT_ONCE("Custom SSL certificates are not supported in Web platform.");
- }
requested_url = scheme + host;
diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h
index 66c5283d5c..08b2dad977 100644
--- a/modules/websocket/emws_peer.h
+++ b/modules/websocket/emws_peer.h
@@ -86,7 +86,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<X509Certificate> p_cert = Ref<X509Certificate>()) override;
+ virtual Error connect_to_url(const String &p_url, Ref<TLSOptions> p_tls_client_options) override;
virtual Error accept_stream(Ref<StreamPeer> 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<X509Certificate>()));
- ClassDB::bind_method(D_METHOD("create_server", "port", "bind_address", "tls_key", "tls_certificate"), &WebSocketMultiplayerPeer::create_server, DEFVAL("*"), DEFVAL(Ref<CryptoKey>()), DEFVAL(Ref<X509Certificate>()));
+ ClassDB::bind_method(D_METHOD("create_client", "url", "tls_client_options"), &WebSocketMultiplayerPeer::create_client, DEFVAL(Ref<TLSOptions>()));
+ ClassDB::bind_method(D_METHOD("create_server", "port", "bind_address", "tls_server_options"), &WebSocketMultiplayerPeer::create_server, DEFVAL("*"), DEFVAL(Ref<TLSOptions>()));
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<CryptoKey> p_tls_key, Ref<X509Certificate> p_tls_certificate) {
+Error WebSocketMultiplayerPeer::create_server(int p_port, IPAddress p_bind_ip, Ref<TLSOptions> 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<X509Certificate> p_tls_certificate) {
+Error WebSocketMultiplayerPeer::create_client(const String &p_url, Ref<TLSOptions> 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<WebSocketPeer> 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<StreamPeerTLS> tls = Ref<StreamPeerTLS>(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<WebSocketPeer> peer_config;
HashMap<int, PendingPeer> pending_peers;
Ref<TCPServer> tcp_server;
- bool use_tls = false;
- Ref<X509Certificate> tls_certificate;
- Ref<CryptoKey> tls_key;
+ Ref<TLSOptions> tls_server_options;
ConnectionStatus connection_status = CONNECTION_DISCONNECTED;
@@ -115,8 +113,8 @@ public:
/* WebSocketPeer */
virtual Ref<WebSocketPeer> get_peer(int p_peer_id) const;
- Error create_client(const String &p_url, bool p_verify_tls, Ref<X509Certificate> p_tls_certificate);
- Error create_server(int p_port, IPAddress p_bind_ip, Ref<CryptoKey> p_tls_key, Ref<X509Certificate> p_tls_certificate);
+ Error create_client(const String &p_url, Ref<TLSOptions> p_options);
+ Error create_server(int p_port, IPAddress p_bind_ip, Ref<TLSOptions> p_options);
void set_supported_protocols(const Vector<String> &p_protocols);
Vector<String> 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<X509Certificate>()));
+ ClassDB::bind_method(D_METHOD("connect_to_url", "url", "tls_client_options"), &WebSocketPeer::connect_to_url, DEFVAL(Ref<TLSOptions>()));
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<X509Certificate> p_cert = Ref<X509Certificate>()) { return ERR_UNAVAILABLE; };
+ virtual Error connect_to_url(const String &p_url, Ref<TLSOptions> p_options = Ref<TLSOptions>()) = 0;
virtual Error accept_stream(Ref<StreamPeer> 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..8a150c8561 100644
--- a/modules/websocket/wsl_peer.cpp
+++ b/modules/websocket/wsl_peer.cpp
@@ -333,8 +333,7 @@ void WSLPeer::_do_client_handshake() {
// Start SSL handshake
tls = Ref<StreamPeerTLS>(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 +475,10 @@ bool WSLPeer::_verify_server_response() {
return true;
}
-Error WSLPeer::connect_to_url(const String &p_url, bool p_verify_tls, Ref<X509Certificate> p_cert) {
+Error WSLPeer::connect_to_url(const String &p_url, Ref<TLSOptions> 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 +506,13 @@ Error WSLPeer::connect_to_url(const String &p_url, bool p_verify_tls, Ref<X509Ce
requested_url = p_url;
requested_host = host;
- verify_tls = p_verify_tls;
- tls_cert = p_cert;
+
+ if (p_options.is_valid()) {
+ tls_options = p_options;
+ } else {
+ tls_options = TLSOptions::client();
+ }
+
tcp.instantiate();
resolver.start(host, port);
diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h
index fc81d39a37..c06e768b6d 100644
--- a/modules/websocket/wsl_peer.h
+++ b/modules/websocket/wsl_peer.h
@@ -102,8 +102,7 @@ private:
// WebSocket configuration.
bool use_tls = true;
- bool verify_tls = true;
- Ref<X509Certificate> tls_cert;
+ Ref<TLSOptions> tls_options;
// Packet buffers.
Vector<uint8_t> 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<X509Certificate> p_cert = Ref<X509Certificate>()) override;
+ virtual Error connect_to_url(const String &p_url, Ref<TLSOptions> p_options = Ref<TLSOptions>()) override;
virtual Error accept_stream(Ref<StreamPeer> p_stream) override;
virtual void close(int p_code = 1000, String p_reason = "") override;
virtual void poll() override;