Browse Source

Websocket client SSL support

Fabio Alessandrelli 7 years ago
parent
commit
2e078142a0

+ 19 - 1
modules/websocket/lws_client.cpp

@@ -31,6 +31,7 @@
 
 #include "lws_client.h"
 #include "core/io/ip.h"
+#include "core/io/stream_peer_ssl.h"
 
 Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocols) {
 
@@ -64,6 +65,9 @@ Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
 	info.uid = -1;
 	//info.ws_ping_pong_interval = 5;
 	info.user = _lws_ref;
+#if defined(LWS_OPENSSL_SUPPORT)
+	info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
+#endif
 	context = lws_create_context(&info);
 
 	if (context == NULL) {
@@ -87,7 +91,14 @@ Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
 	i.host = hbuf;
 	i.path = pbuf;
 	i.port = p_port;
-	i.ssl_connection = p_ssl;
+
+	if (p_ssl) {
+		i.ssl_connection = LCCSCF_USE_SSL;
+		if (!verify_ssl)
+			i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED;
+	} else {
+		i.ssl_connection = 0;
+	}
 
 	lws_client_connect_via_info(&i);
 	return OK;
@@ -104,6 +115,13 @@ int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi
 	LWSPeer::PeerData *peer_data = (LWSPeer::PeerData *)user;
 
 	switch (reason) {
+		case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: {
+			PoolByteArray arr = StreamPeerSSL::get_project_cert_array();
+			if (arr.size() > 0)
+				SSL_CTX_add_client_CA((SSL_CTX *)user, d2i_X509(NULL, &arr.read()[0], arr.size()));
+			else if (verify_ssl)
+				WARN_PRINTS("No CA cert specified in project settings, SSL will not work");
+		} break;
 
 		case LWS_CALLBACK_CLIENT_ESTABLISHED:
 			peer->set_wsi(wsi);

+ 16 - 0
modules/websocket/websocket_client.cpp

@@ -32,6 +32,8 @@
 GDCINULL(WebSocketClient);
 
 WebSocketClient::WebSocketClient() {
+
+	verify_ssl = true;
 }
 
 WebSocketClient::~WebSocketClient() {
@@ -72,6 +74,16 @@ Error WebSocketClient::connect_to_url(String p_url, PoolVector<String> p_protoco
 	return connect_to_host(host, path, port, ssl, p_protocols);
 }
 
+void WebSocketClient::set_verify_ssl_enabled(bool p_verify_ssl) {
+
+	verify_ssl = p_verify_ssl;
+}
+
+bool WebSocketClient::is_verify_ssl_enabled() const {
+
+	return verify_ssl;
+}
+
 bool WebSocketClient::is_server() const {
 
 	return false;
@@ -116,6 +128,10 @@ void WebSocketClient::_on_error() {
 void WebSocketClient::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("connect_to_url", "url", "protocols", "gd_mp_api"), &WebSocketClient::connect_to_url, DEFVAL(PoolVector<String>()), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("disconnect_from_host"), &WebSocketClient::disconnect_from_host);
+	ClassDB::bind_method(D_METHOD("set_verify_ssl_enabled", "enabled"), &WebSocketClient::set_verify_ssl_enabled);
+	ClassDB::bind_method(D_METHOD("is_verify_ssl_enabled"), &WebSocketClient::is_verify_ssl_enabled);
+
+	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "verify_ssl", PROPERTY_HINT_NONE, "", 0), "set_verify_ssl_enabled", "is_verify_ssl_enabled");
 
 	ADD_SIGNAL(MethodInfo("data_received"));
 	ADD_SIGNAL(MethodInfo("connection_established", PropertyInfo(Variant::STRING, "protocol")));

+ 4 - 0
modules/websocket/websocket_client.h

@@ -41,12 +41,16 @@ class WebSocketClient : public WebSocketMultiplayerPeer {
 
 protected:
 	Ref<WebSocketPeer> _peer;
+	bool verify_ssl;
 
 	static void _bind_methods();
 
 public:
 	Error connect_to_url(String p_url, PoolVector<String> p_protocols = PoolVector<String>(), bool gd_mp_api = false);
 
+	void set_verify_ssl_enabled(bool p_verify_ssl);
+	bool is_verify_ssl_enabled() const;
+
 	virtual void poll() = 0;
 	virtual Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocol = PoolVector<String>()) = 0;
 	virtual void disconnect_from_host() = 0;