tools: add certification check

If the server disable the anonymous connection option, it accept a client only if the CA of the client matches the CA of the server.
Else (anonymous connection option enabled), the server accept any request.

Change-Id: I6ff6ec72d6f6452ce50fd8aa35896ff7117be6c0
diff --git a/tools/dsh/dsh.cpp b/tools/dsh/dsh.cpp
index ca4e99d..4e7507d 100644
--- a/tools/dsh/dsh.cpp
+++ b/tools/dsh/dsh.cpp
@@ -91,13 +91,14 @@
                  const std::string& turn_host,
                  const std::string& turn_user,
                  const std::string& turn_pass,
-                 const std::string& turn_realm)
+                 const std::string& turn_realm,
+                 bool anonymous)
     :logger(dht::log::getStdLogger())
     , ioContext(std::make_shared<asio::io_context>()),
-    iceFactory(std::make_shared<IceTransportFactory>(logger))
+    iceFactory(std::make_shared<IceTransportFactory>(logger)),
+    certStore(std::make_shared<tls::CertificateStore>(path / "certstore", logger)),
+    trustStore(std::make_shared<tls::TrustStore>(*certStore))
 {
-    auto certStore = std::make_shared<tls::CertificateStore>(path / "certstore", logger);
-
     ioContext = std::make_shared<asio::io_context>();
     ioContextRunner = std::thread([context = ioContext, logger = logger] {
         try {
@@ -108,6 +109,8 @@
                 logger->error("Error in ioContextRunner: {}", ex.what());
         }
     });
+    auto ca = identity.second->issuer;
+    trustStore->setCertificateStatus(ca->getId().toString(), tls::TrustStore::PermissionStatus::ALLOWED);
     // Build a server
     auto config = connectionManagerConfig(path,
                                           identity,
@@ -120,10 +123,8 @@
     connectionManager = std::make_unique<ConnectionManager>(std::move(config));
 
     connectionManager->onDhtConnected(identity.first->getPublicKey());
-    connectionManager->onICERequest([this](const dht::Hash<32>&) { // handle ICE request
-        if (logger)
-            logger->debug("ICE request received");
-        return true;
+    connectionManager->onICERequest([this,identity,anonymous](const DeviceId& deviceId ) { // handle ICE request
+        return trustStore->isAllowed(*certStore->getCertificate(deviceId.toString()), anonymous);
     });
 
     std::mutex mtx;
@@ -228,7 +229,7 @@
                  const std::string& turn_user,
                  const std::string& turn_pass,
                  const std::string& turn_realm)
-    : Dsh(path, identity, bootstrap, turn_host, turn_user, turn_pass, turn_realm)
+    : Dsh(path, identity, bootstrap, turn_host, turn_user, turn_pass, turn_realm, false)
 {
     // Build a client
     std::condition_variable cv;
diff --git a/tools/dsh/dsh.h b/tools/dsh/dsh.h
index 3bdc934..dd6a4ea 100644
--- a/tools/dsh/dsh.h
+++ b/tools/dsh/dsh.h
@@ -33,7 +33,8 @@
         const std::string& turn_host,
         const std::string& turn_user,
         const std::string& turn_pass,
-        const std::string& turn_realm);
+        const std::string& turn_realm,
+        const bool anonymous);
     // Build a client
     Dsh(const std::filesystem::path& path,
         dht::crypto::Identity identity,
@@ -54,6 +55,8 @@
     std::shared_ptr<dhtnet::IceTransportFactory> iceFactory {nullptr};
     std::shared_ptr<asio::io_context> ioContext;
     std::thread ioContextRunner;
+    std::shared_ptr<tls::TrustStore> trustStore;
+
 };
 
 } // namespace dhtnet
diff --git a/tools/dsh/dsh.yaml b/tools/dsh/dsh.yaml
index 54e13ab..a023aa3 100644
--- a/tools/dsh/dsh.yaml
+++ b/tools/dsh/dsh.yaml
@@ -6,3 +6,4 @@
 turn_realm: "ring"
 binary: "bash"
 CA: HOME/.dhtnet # Change this to the path of the CA directory
+anonymous: false
diff --git a/tools/dsh/main.cpp b/tools/dsh/main.cpp
index 7c5e006..19ff4e5 100644
--- a/tools/dsh/main.cpp
+++ b/tools/dsh/main.cpp
@@ -46,6 +46,7 @@
     std::string turn_pass {};
     std::string turn_realm {};
     std::string dsh_configuration {};
+    bool anonymous_cnx {false};
 };
 
 static const constexpr struct option long_options[]
@@ -61,6 +62,7 @@
        {"turn_pass", required_argument, nullptr, 'w'},
        {"turn_realm", required_argument, nullptr, 'r'},
        {"dsh_configuration", required_argument, nullptr, 'd'},
+       {"anonymous", no_argument, nullptr, 'a'},
        {nullptr, 0, nullptr, 0}};
 
 dhtsh_params
@@ -105,6 +107,10 @@
             break;
         case 'd':
             params.dsh_configuration = optarg;
+            break;
+        case 'a':
+            params.anonymous_cnx = true;
+            break;
         default:
             std::cerr << "Invalid option" << std::endl;
             exit(EXIT_FAILURE);
@@ -154,6 +160,10 @@
             if (config["binary"] && params.binary.empty()) {
                 params.binary = config["binary"].as<std::string>();
             }
+            if (config["anonymous"] && !params.anonymous_cnx) {
+                params.anonymous_cnx = config["anonymous"].as<bool>();
+            }
+
         }
     }
     return params;
@@ -211,14 +221,15 @@
 
     std::unique_ptr<dhtnet::Dsh> dhtsh;
     if (params.listen) {
-        // create dnc instance
+        // create dsh instance
         dhtsh = std::make_unique<dhtnet::Dsh>(params.path,
                                               identity,
                                               params.bootstrap,
                                               params.turn_host,
                                               params.turn_user,
                                               params.turn_pass,
-                                              params.turn_realm);
+                                              params.turn_realm,
+                                              params.anonymous_cnx);
     } else {
         dhtsh = std::make_unique<dhtnet::Dsh>(params.path,
                                               identity,