From f4b34e81791bee45c847a77a9bd70db560c3299e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Mon, 16 Oct 2023 12:02:23 -0400
Subject: [PATCH] MultiplexedSocket: refuse channel if id exists

Prevents the peer from hijacking existing channels,
preventing various issues when collisions occur.

Also mark accepted connections as 'answered', allowing
its removal if shutdown by the server.

Change-Id: Ie91d50b0d518cb6621289233bfda2c289deeed5c
---
 src/multiplexed_socket.cpp | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/src/multiplexed_socket.cpp b/src/multiplexed_socket.cpp
index 81a777c..2471256 100644
--- a/src/multiplexed_socket.cpp
+++ b/src/multiplexed_socket.cpp
@@ -128,7 +128,7 @@ public:
 
     std::shared_ptr<ChannelSocket> makeSocket(const std::string& name,
                                               uint16_t channel,
-                                              bool isInitiator = false)
+                                              bool isInitiator)
     {
         auto& channelSocket = sockets[channel];
         if (not channelSocket)
@@ -143,8 +143,8 @@ public:
                 });
         else {
             if (logger_)
-                logger_->warn("A channel is already present on that socket, accepting "
-                      "the request will close the previous one {}", name);
+                logger_->warn("Received request for existing channel {}", channel);
+            return {};
         }
         return channelSocket;
     }
@@ -393,11 +393,23 @@ MultiplexedSocket::Impl::onVersion(int version)
 void
 MultiplexedSocket::Impl::onRequest(const std::string& name, uint16_t channel)
 {
-    auto accept = onRequest_(endpoint->peerCertificate(), channel, name);
+    bool accept;
+    if (channel == CONTROL_CHANNEL || channel == PROTOCOL_CHANNEL) {
+        if (logger_)
+            logger_->warn("Channel {:d} is reserved, refusing request", channel);
+        accept = false;
+    } else
+        accept = onRequest_(endpoint->peerCertificate(), channel, name);
+
     std::shared_ptr<ChannelSocket> channelSocket;
     if (accept) {
         std::lock_guard<std::mutex> lkSockets(socketsMutex);
-        channelSocket = makeSocket(name, channel);
+        channelSocket = makeSocket(name, channel, false);
+        if (not channelSocket) {
+            if (logger_)
+                logger_->error("Channel {:d} already exists, refusing request", channel);
+            accept = false;
+        }
     }
 
     // Answer to ChannelRequest if accepted
@@ -422,6 +434,11 @@ MultiplexedSocket::Impl::onRequest(const std::string& name, uint16_t channel)
     if (accept) {
         onChannelReady_(deviceId, channelSocket);
         channelSocket->ready(true);
+        if (channelSocket->isRemovable()) {
+            std::lock_guard<std::mutex> lkSockets(socketsMutex);
+            sockets.erase(channel);
+        } else
+            channelSocket->answered();
     }
 }
 
-- 
GitLab