From c28f843ef1b9ef070f2bdea15ec79a31287f40a3 Mon Sep 17 00:00:00 2001
From: Pierre Nicolas <pierre.nicolas@savoirfairelinux.com>
Date: Thu, 18 Jul 2024 13:46:16 -0400
Subject: [PATCH] conversation: refuse malformed uri

Second part of this fix: https://review.jami.net/c/jami-daemon/+/28337
GitLab: #1721

Change-Id: Ie428a57d89ac3db4e32660735cb3a5b0bf0f5c94
---
 src/client/conversation_interface.cpp         | 20 +++++++++++++++----
 src/jamidht/conversation_module.cpp           | 20 ++++++++++---------
 src/jamidht/conversation_module.h             |  4 ++--
 test/unitTest/conversation/conversation.cpp   |  2 +-
 .../conversation/conversationMembersEvent.cpp |  6 +++---
 5 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/src/client/conversation_interface.cpp b/src/client/conversation_interface.cpp
index ce751194c5..95ce7a6895 100644
--- a/src/client/conversation_interface.cpp
+++ b/src/client/conversation_interface.cpp
@@ -140,8 +140,14 @@ addConversationMember(const std::string& accountId,
                       const std::string& contactUri)
 {
     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
-        if (auto convModule = acc->convModule(true))
-            convModule->addConversationMember(conversationId, contactUri);
+        if (auto convModule = acc->convModule(true)) {
+            dht::InfoHash h(contactUri);
+            if (not h) {
+                JAMI_ERROR("addConversationMember: invalid contact URI `{}`", contactUri);
+                return;
+            }
+            convModule->addConversationMember(conversationId, h);
+        }
 }
 
 void
@@ -150,8 +156,14 @@ removeConversationMember(const std::string& accountId,
                          const std::string& contactUri)
 {
     if (auto acc = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId))
-        if (auto convModule = acc->convModule(true))
-            convModule->removeConversationMember(conversationId, contactUri);
+        if (auto convModule = acc->convModule(true)) {
+            dht::InfoHash h(contactUri);
+            if (not h) {
+                JAMI_ERROR("removeConversationMember: invalid contact URI `{}`", contactUri);
+                return;
+            }
+            convModule->removeConversationMember(conversationId, h);
+        }
 }
 
 std::vector<std::map<std::string, std::string>>
diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp
index d5582154ec..d389cf777a 100644
--- a/src/jamidht/conversation_module.cpp
+++ b/src/jamidht/conversation_module.cpp
@@ -2596,7 +2596,7 @@ ConversationModule::fetchNewCommits(const std::string& peer,
 
 void
 ConversationModule::addConversationMember(const std::string& conversationId,
-                                          const std::string& contactUri,
+                                          const dht::InfoHash& contactUri,
                                           bool sendRequest)
 {
     auto conv = pimpl_->getConversation(conversationId);
@@ -2606,19 +2606,20 @@ ConversationModule::addConversationMember(const std::string& conversationId,
     }
     std::unique_lock lk(conv->mtx);
 
-    if (conv->conversation->isMember(contactUri, true)) {
-        JAMI_DEBUG("{:s} is already a member of {:s}, resend invite", contactUri, conversationId);
+    auto contactUriStr = contactUri.toString();
+    if (conv->conversation->isMember(contactUriStr, true)) {
+        JAMI_DEBUG("{:s} is already a member of {:s}, resend invite", contactUriStr, conversationId);
         // Note: This should not be necessary, but if for whatever reason the other side didn't
         // join we should not forbid new invites
         auto invite = conv->conversation->generateInvitation();
         lk.unlock();
-        pimpl_->sendMsgCb_(contactUri, {}, std::move(invite), 0);
+        pimpl_->sendMsgCb_(contactUriStr, {}, std::move(invite), 0);
         return;
     }
 
     conv->conversation->addMember(
-        contactUri,
-        [this, conv, conversationId, sendRequest, contactUri](bool ok, const std::string& commitId) {
+            contactUriStr,
+        [this, conv, conversationId, sendRequest, contactUriStr](bool ok, const std::string& commitId) {
             if (ok) {
                 std::unique_lock lk(conv->mtx);
                 pimpl_->sendMessageNotification(*conv->conversation,
@@ -2627,7 +2628,7 @@ ConversationModule::addConversationMember(const std::string& conversationId,
                 if (sendRequest) {
                     auto invite = conv->conversation->generateInvitation();
                     lk.unlock();
-                    pimpl_->sendMsgCb_(contactUri, {}, std::move(invite), 0);
+                    pimpl_->sendMsgCb_(contactUriStr, {}, std::move(invite), 0);
                 }
             }
         });
@@ -2635,14 +2636,15 @@ ConversationModule::addConversationMember(const std::string& conversationId,
 
 void
 ConversationModule::removeConversationMember(const std::string& conversationId,
-                                             const std::string& contactUri,
+                                             const dht::InfoHash& contactUri,
                                              bool isDevice)
 {
+    auto contactUriStr = contactUri.toString();
     if (auto conv = pimpl_->getConversation(conversationId)) {
         std::lock_guard lk(conv->mtx);
         if (conv->conversation)
             return conv->conversation->removeMember(
-                contactUri, isDevice, [this, conversationId](bool ok, const std::string& commitId) {
+                    contactUriStr, isDevice, [this, conversationId](bool ok, const std::string& commitId) {
                     if (ok) {
                         pimpl_->sendMessageNotification(conversationId, true, commitId);
                     }
diff --git a/src/jamidht/conversation_module.h b/src/jamidht/conversation_module.h
index bfbd9462b9..546590b805 100644
--- a/src/jamidht/conversation_module.h
+++ b/src/jamidht/conversation_module.h
@@ -356,7 +356,7 @@ public:
      * @param sendRequest   If we need to inform the peer (used for tests)
      */
     void addConversationMember(const std::string& conversationId,
-                               const std::string& contactUri,
+                               const dht::InfoHash& contactUri,
                                bool sendRequest = true);
     /**
      * Remove a member from a conversation (this will trigger a member event + new message on success)
@@ -365,7 +365,7 @@ public:
      * @param isDevice
      */
     void removeConversationMember(const std::string& conversationId,
-                                  const std::string& contactUri,
+                                  const dht::InfoHash& contactUri,
                                   bool isDevice = false);
     /**
      * Get members
diff --git a/test/unitTest/conversation/conversation.cpp b/test/unitTest/conversation/conversation.cpp
index a9a0baef78..d893aa7581 100644
--- a/test/unitTest/conversation/conversation.cpp
+++ b/test/unitTest/conversation/conversation.cpp
@@ -781,7 +781,7 @@ ConversationTest::testMergeTwoDifferentHeads()
     auto convId = libjami::startConversation(aliceId);
 
     auto msgSize = aliceData.messages.size();
-    aliceAccount->convModule()->addConversationMember(convId, carlaUri, false);
+    aliceAccount->convModule()->addConversationMember(convId, dht::InfoHash(carlaUri), false);
     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceData.messages.size() == msgSize + 1; }));
 
     // Cp conversations & convInfo
diff --git a/test/unitTest/conversation/conversationMembersEvent.cpp b/test/unitTest/conversation/conversationMembersEvent.cpp
index 15405b532e..7865729c6a 100644
--- a/test/unitTest/conversation/conversationMembersEvent.cpp
+++ b/test/unitTest/conversation/conversationMembersEvent.cpp
@@ -1105,7 +1105,7 @@ ConversationMembersEventTest::testMemberJoinsNoBadFile()
     auto convId = libjami::startConversation(aliceId);
 
     auto aliceMsgSize = aliceData.messages.size();
-    aliceAccount->convModule()->addConversationMember(convId, carlaUri, false);
+    aliceAccount->convModule()->addConversationMember(convId, dht::InfoHash(carlaUri), false);
     CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return aliceMsgSize + 1 == aliceData.messages.size(); }));
 
     // Cp conversations & convInfo
@@ -1164,7 +1164,7 @@ ConversationMembersEventTest::testMemberAddedNoCertificate()
     auto convId = libjami::startConversation(aliceId);
 
     auto aliceMsgSize = aliceData.messages.size();
-    aliceAccount->convModule()->addConversationMember(convId, carlaUri, false);
+    aliceAccount->convModule()->addConversationMember(convId, dht::InfoHash(carlaUri), false);
     CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return aliceMsgSize + 1 == aliceData.messages.size(); }));
 
     // Cp conversations & convInfo
@@ -1214,7 +1214,7 @@ ConversationMembersEventTest::testMemberJoinsInviteRemoved()
     auto convId = libjami::startConversation(aliceId);
 
     auto aliceMsgSize = aliceData.messages.size();
-    aliceAccount->convModule()->addConversationMember(convId, carlaUri, false);
+    aliceAccount->convModule()->addConversationMember(convId, dht::InfoHash(carlaUri), false);
     CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return aliceMsgSize + 1 == aliceData.messages.size(); }));
 
     // Cp conversations & convInfo
-- 
GitLab