From bb3d0fa5fa13ba4c352613c7fe52b209ca10b5cb Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 27 Oct 2021 21:42:58 +1300 Subject: [PATCH] Add secure WebSocket support --- .../resources/describe-settings.json | 8 +++ domain-server/src/DomainServer.cpp | 5 +- .../src/webrtc/WebRTCSignalingServer.cpp | 57 ++++++++++++++++++- .../src/webrtc/WebRTCSignalingServer.h | 3 +- 4 files changed, 68 insertions(+), 5 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 9032d3fbd9..f83a4c47b4 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -84,6 +84,14 @@ "type": "checkbox", "default": false, "advanced": true + }, + { + "name": "enable_webrtc_websocket_ssl", + "label": "Enable WebRTC WebSocket SSL", + "help": "Use secure WebSocket (wss:// protocol) for WebRTC signaling channel. If \"on\", the key, cert, and CA files are expected to be in the local Vircadia app directory, in a /domain-server/ subdirectory with filenames cert.key, cert.crt, and crt-ca.crt.", + "type": "checkbox", + "default": false, + "advanced": true } ] }, diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c93c1f9acf..67f961d36f 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -278,7 +278,10 @@ DomainServer::DomainServer(int argc, char* argv[]) : // The domain server's WebRTC signaling server is used by the domain server and the assignment clients, so disabling it // disables WebRTC for the server as a whole. if (isWebRTCEnabled) { - _webrtcSignalingServer.reset(new WebRTCSignalingServer(this)); + const QString WEBRTC_WSS_ENABLE = "webrtc.enable_webrtc_websocket_ssl"; + bool isWebRTCEnabled = _settingsManager.valueForKeyPath(WEBRTC_WSS_ENABLE).toBool(); + qDebug() << "WebRTC WSS enabled:" << isWebRTCEnabled; + _webrtcSignalingServer.reset(new WebRTCSignalingServer(this, isWebRTCEnabled)); } #endif diff --git a/libraries/networking/src/webrtc/WebRTCSignalingServer.cpp b/libraries/networking/src/webrtc/WebRTCSignalingServer.cpp index b35cd5158b..987bf6b02f 100644 --- a/libraries/networking/src/webrtc/WebRTCSignalingServer.cpp +++ b/libraries/networking/src/webrtc/WebRTCSignalingServer.cpp @@ -10,19 +10,70 @@ #if defined(WEBRTC_DATA_CHANNELS) +#include #include #include +#include +#include + #include "../NetworkLogging.h" #include "../NodeType.h" const int WEBRTC_SOCKET_CHECK_INTERVAL_IN_MS = 30000; -WebRTCSignalingServer::WebRTCSignalingServer(QObject* parent) : - QObject(parent), - _webSocketServer(new QWebSocketServer(QStringLiteral("WebRTC Signaling Server"), QWebSocketServer::NonSecureMode, this)) +WebRTCSignalingServer::WebRTCSignalingServer(QObject* parent, bool isWSSEnabled) : + QObject(parent) { + if (isWSSEnabled) { + _webSocketServer = (new QWebSocketServer(QStringLiteral("WebRTC Signaling Server"), QWebSocketServer::SecureMode, + this)); + + auto dsDirPath = PathUtils::getAppLocalDataPath(); + const QString KEY_FILENAME = "cert.key"; + const QString CRT_FILENAME = "cert.crt"; + const QString CA_CRT_FILENAME = "cert-ca.crt"; + qCDebug(networking_webrtc) << "WebSocket WSS key file:" << dsDirPath + KEY_FILENAME; + qCDebug(networking_webrtc) << "WebSocket WSS cert file:" << dsDirPath + CRT_FILENAME; + qCDebug(networking_webrtc) << "WebSocket WSS CA cert file:" << dsDirPath + CA_CRT_FILENAME; + + QFile sslCaFile(dsDirPath + CA_CRT_FILENAME); + sslCaFile.open(QIODevice::ReadOnly); + QSslCertificate sslCaCertificate(&sslCaFile, QSsl::Pem); + sslCaFile.close(); + + QSslConfiguration sslConfiguration; + QFile sslCrtFile(dsDirPath + CRT_FILENAME); + sslCrtFile.open(QIODevice::ReadOnly); + QSslCertificate sslCertificate(&sslCrtFile, QSsl::Pem); + sslCrtFile.close(); + + QFile sslKeyFile(dsDirPath + KEY_FILENAME); + sslKeyFile.open(QIODevice::ReadOnly); + QSslKey sslKey(&sslKeyFile, QSsl::Rsa, QSsl::Pem); + sslKeyFile.close(); + + if (!sslCaCertificate.isNull() && !sslKey.isNull() && !sslCertificate.isNull()) { + sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone); + sslConfiguration.addCaCertificate(sslCaCertificate); + sslConfiguration.setLocalCertificate(sslCertificate); + sslConfiguration.setPrivateKey(sslKey); + _webSocketServer->setSslConfiguration(sslConfiguration); + qCDebug(networking_webrtc) << "WebSocket SSL mode enabled:" + << (_webSocketServer->secureMode() == QWebSocketServer::SecureMode); + } else { + qCWarning(networking_webrtc) << "Error creating WebSocket SSL key."; + } + + } else { + _webSocketServer = (new QWebSocketServer(QStringLiteral("WebRTC Signaling Server"), QWebSocketServer::NonSecureMode, + this)); + } +#ifdef WEBRTC_DEBUG + qCDebug(networking_webrtc) << "WebRTCSignalingServer mode =" << _webSocketServer->secureMode(); +#endif + connect(_webSocketServer, &QWebSocketServer::newConnection, this, &WebRTCSignalingServer::newWebSocketConnection); // Automatically recover from network interruptions. diff --git a/libraries/networking/src/webrtc/WebRTCSignalingServer.h b/libraries/networking/src/webrtc/WebRTCSignalingServer.h index fb695cc6fc..3a2eebbcef 100644 --- a/libraries/networking/src/webrtc/WebRTCSignalingServer.h +++ b/libraries/networking/src/webrtc/WebRTCSignalingServer.h @@ -61,7 +61,8 @@ public: /// @brief Constructs a new WebRTCSignalingServer object. /// @param parent Qt parent object. - WebRTCSignalingServer(QObject* parent); + /// @param isWSSEnabled Whether the WebSocket used for WebRTC signaling should be secure (WSS protocol). + WebRTCSignalingServer(QObject* parent, bool isWSSEnabled); /// @brief Binds the WebRTC signaling server's WebSocket to an address and port. /// @param address The address to use for the WebSocket.