Line data Source code
1 : /* 2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc. 3 : * 4 : * This program is free software: you can redistribute it and/or modify 5 : * it under the terms of the GNU General Public License as published by 6 : * the Free Software Foundation, either version 3 of the License, or 7 : * (at your option) any later version. 8 : * 9 : * This program is distributed in the hope that it will be useful, 10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 : * GNU General Public License for more details. 13 : * 14 : * You should have received a copy of the GNU General Public License 15 : * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 : */ 17 : #pragma once 18 : 19 : #include "jami_contact.h" 20 : 21 : #include <dhtnet/certstore.h> 22 : #include <opendht/infohash.h> 23 : #include <opendht/crypto.h> 24 : 25 : #include <map> 26 : #include <mutex> 27 : #include <chrono> 28 : 29 : namespace jami { 30 : 31 : class ContactList 32 : { 33 : public: 34 : using clock = std::chrono::system_clock; 35 : using time_point = clock::time_point; 36 : using VerifyResult = dht::crypto::TrustList::VerifyResult; 37 : 38 : using OnContactAdded = std::function<void(const std::string&, bool)>; 39 : using OnContactRemoved = std::function<void(const std::string&, bool)>; 40 : using OnIncomingTrustRequest = std::function< 41 : void(const std::string&, const std::string&, const std::vector<uint8_t>&, time_t)>; 42 : using OnAcceptConversation = std::function<void(const std::string&, const std::string&)>; 43 : using OnConfirmation = std::function<void(const std::string&, const std::string&)>; 44 : using OnDevicesChanged = std::function<void(const std::map<dht::PkId, KnownDevice>&)>; 45 : 46 : struct OnChangeCallback 47 : { 48 : OnContactAdded contactAdded; 49 : OnContactRemoved contactRemoved; 50 : OnIncomingTrustRequest trustRequest; 51 : OnDevicesChanged devicesChanged; 52 : OnAcceptConversation acceptConversation; 53 : OnConfirmation onConfirmation; 54 : }; 55 : 56 : ContactList(const std::string& accountId, 57 : const std::shared_ptr<crypto::Certificate>& cert, 58 : const std::filesystem::path& path, 59 : OnChangeCallback cb); 60 : ~ContactList(); 61 : 62 19692 : const std::string& accountId() const { return accountId_; } 63 : 64 : void load(); 65 : void save(); 66 : 67 : /* Contacts */ 68 : std::map<std::string, std::string> getContactDetails(const dht::InfoHash&) const; 69 : bool removeContact(const dht::InfoHash&, bool ban); 70 : bool removeContactConversation(const dht::InfoHash&); 71 : bool addContact(const dht::InfoHash&, 72 : bool confirmed = false, 73 : const std::string& conversationId = ""); 74 : void updateConversation(const dht::InfoHash& h, const std::string& conversationId); 75 : 76 : bool setCertificateStatus(const std::string& cert_id, 77 : const dhtnet::tls::TrustStore::PermissionStatus status); 78 : 79 : bool setCertificateStatus(const std::shared_ptr<crypto::Certificate>& cert, 80 : dhtnet::tls::TrustStore::PermissionStatus status, 81 : bool local = true); 82 : 83 7046 : dhtnet::tls::TrustStore::PermissionStatus getCertificateStatus(const std::string& cert_id) const 84 : { 85 7046 : return trust_->getCertificateStatus(cert_id); 86 : } 87 : 88 0 : std::vector<std::string> getCertificatesByStatus(dhtnet::tls::TrustStore::PermissionStatus status) const 89 : { 90 0 : return trust_->getCertificatesByStatus(status); 91 : } 92 : 93 878 : bool isAllowed(const crypto::Certificate& crt, bool allowPublic) 94 : { 95 878 : return trust_->isAllowed(crt, allowPublic); 96 : } 97 : 98 1056 : VerifyResult isValidAccountDevice(const crypto::Certificate& crt) const 99 : { 100 1056 : return accountTrust_.verify(crt); 101 : } 102 : 103 : const std::map<dht::InfoHash, Contact>& getContacts() const; 104 : void setContacts(const std::map<dht::InfoHash, Contact>&); 105 : void updateContact(const dht::InfoHash&, const Contact&, bool emit = true); 106 : 107 : /** Should be called only after updateContact */ 108 : void saveContacts() const; 109 : 110 : const std::filesystem::path& path() const { return path_; } 111 : 112 : /* Contact requests */ 113 : 114 : /** Inform of a new contact request. Returns true if the request should be immediatly accepted 115 : * (already a contact) */ 116 : bool onTrustRequest(const dht::InfoHash& peer_account, 117 : const std::shared_ptr<dht::crypto::PublicKey>& peer_device, 118 : time_t received, 119 : bool confirm, 120 : const std::string& conversationId, 121 : std::vector<uint8_t>&& payload); 122 : std::vector<std::map<std::string, std::string>> getTrustRequests() const; 123 : std::map<std::string, std::string> getTrustRequest(const dht::InfoHash& from) const; 124 : void acceptConversation(const std::string& convId, const std::string& deviceId = ""); // ToDO this is a bit dirty imho 125 : bool acceptTrustRequest(const dht::InfoHash& from); 126 : bool discardTrustRequest(const dht::InfoHash& from); 127 : 128 : /* Devices */ 129 2048 : const std::map<dht::PkId, KnownDevice>& getKnownDevices() const { return knownDevices_; } 130 : void foundAccountDevice(const dht::PkId& device, 131 : const std::string& name = {}, 132 2000 : const time_point& last_sync = time_point::min()); 133 : bool foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, 134 : const std::string& name = {}, 135 2 : const time_point& last_sync = time_point::min()); 136 : bool removeAccountDevice(const dht::PkId& device); 137 : void setAccountDeviceName(const dht::PkId& device, const std::string& name); 138 : std::string getAccountDeviceName(const dht::PkId& device) const; 139 : 140 : DeviceSync getSyncData() const; 141 : bool syncDevice(const dht::PkId& device, const time_point& syncDate); 142 : 143 : private: 144 : mutable std::mutex mutex_; 145 : std::map<dht::InfoHash, Contact> contacts_; 146 : std::map<dht::InfoHash, TrustRequest> trustRequests_; 147 : std::map<dht::InfoHash, KnownDevice> knownDevicesLegacy_; 148 : 149 : std::map<dht::PkId, KnownDevice> knownDevices_; 150 : 151 : // Trust store with account main certificate as the only CA 152 : dht::crypto::TrustList accountTrust_; 153 : // Trust store for to match peer certificates 154 : std::unique_ptr<dhtnet::tls::TrustStore> trust_; 155 : std::filesystem::path path_; 156 : std::string accountUri_; 157 : 158 : OnChangeCallback callbacks_; 159 : std::string accountId_; 160 : 161 : void loadContacts(); 162 : void loadTrustRequests(); 163 : 164 : void loadKnownDevices(); 165 : void saveKnownDevices() const; 166 : 167 : /** Should be called only after onTrustRequest */ 168 : void saveTrustRequests() const; 169 : }; 170 : 171 : } // namespace jami