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