Browse Source

Merge pull request #1062 from ilsalvopss/master

WebSocket: allow clients to provide a TLS certificate
Paul-Louis Ageneau 1 year ago
parent
commit
a721f3a298
4 changed files with 26 additions and 6 deletions
  1. 3 0
      include/rtc/websocket.hpp
  2. 6 4
      src/impl/tlstransport.cpp
  3. 15 2
      src/impl/websocket.cpp
  4. 2 0
      src/impl/websocket.hpp

+ 3 - 0
include/rtc/websocket.hpp

@@ -40,6 +40,9 @@ public:
 		optional<std::chrono::milliseconds> pingInterval;      // zero to disable
 		optional<int> maxOutstandingPings;
 		optional<string> caCertificatePemFile;
+		optional<string> certificatePemFile;
+		optional<string> keyPemFile;
+		optional<string> keyPemPass;
 	};
 
 	WebSocket();

+ 6 - 4
src/impl/tlstransport.cpp

@@ -592,14 +592,16 @@ TlsTransport::TlsTransport(variant<shared_ptr<TcpTransport>, shared_ptr<HttpProx
 		SSL_CTX_set_options(mCtx, SSL_OP_SINGLE_ECDH_USE);
 #endif
 
+		if(mIsClient) {
+			if (!SSL_CTX_set_default_verify_paths(mCtx)) {
+				PLOG_WARNING << "SSL root CA certificates unavailable";
+			}
+		}
+
 		if (certificate) {
 			auto [x509, pkey] = certificate->credentials();
 			SSL_CTX_use_certificate(mCtx, x509);
 			SSL_CTX_use_PrivateKey(mCtx, pkey);
-		} else {
-			if (!SSL_CTX_set_default_verify_paths(mCtx)) {
-				PLOG_WARNING << "SSL root CA certificates unavailable";
-			}
 		}
 
 		SSL_CTX_set_options(mCtx, SSL_OP_NO_SSLv3 | SSL_OP_NO_RENEGOTIATION);

+ 15 - 2
src/impl/websocket.cpp

@@ -36,8 +36,8 @@ using std::chrono::milliseconds;
 
 WebSocket::WebSocket(optional<Configuration> optConfig, certificate_ptr certificate)
     : config(optConfig ? std::move(*optConfig) : Configuration()),
-      mCertificate(std::move(certificate)), mIsSecure(mCertificate != nullptr),
-      mRecvQueue(RECV_QUEUE_LIMIT, message_size_func) {
+      mCertificate(certificate ? std::move(certificate) : std::move(loadCertificate(config))),
+      mIsSecure(mCertificate != nullptr), mRecvQueue(RECV_QUEUE_LIMIT, message_size_func) {
 	PLOG_VERBOSE << "Creating WebSocket";
 	if (config.proxyServer) {
 		if (config.proxyServer->type == ProxyServer::Type::Socks5)
@@ -49,6 +49,19 @@ WebSocket::WebSocket(optional<Configuration> optConfig, certificate_ptr certific
 	}
 }
 
+certificate_ptr WebSocket::loadCertificate(const Configuration& config) {
+	if (!config.certificatePemFile)
+		return nullptr;
+
+	if (config.keyPemFile)
+		return std::make_shared<Certificate>(
+			Certificate::FromFile(*config.certificatePemFile, *config.keyPemFile,
+										config.keyPemPass.value_or("")));
+
+	throw std::invalid_argument(
+		"Either none or both certificate and key PEM files must be specified");
+}
+
 WebSocket::~WebSocket() { PLOG_VERBOSE << "Destroying WebSocket"; }
 
 void WebSocket::open(const string &url) {

+ 2 - 0
src/impl/websocket.hpp

@@ -67,6 +67,8 @@ struct WebSocket final : public Channel, public std::enable_shared_from_this<Web
 	std::atomic<State> state = State::Closed;
 
 private:
+	static certificate_ptr loadCertificate(const Configuration& config);
+
 	void scheduleConnectionTimeout();
 
 	const init_token mInitToken = Init::Instance().token();