Line data Source code
1 : /*
2 : * Copyright (C) 2004-2025 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 "account_manager.h"
20 : #include "jamidht/auth_channel_handler.h"
21 :
22 : #include <dhtnet/multiplexed_socket.h>
23 : #include <memory>
24 :
25 : namespace jami {
26 :
27 : // used for status codes on DeviceAuthStateChanged
28 : enum class DeviceAuthState : uint8_t {
29 : INIT = 0,
30 : TOKEN_AVAILABLE = 1,
31 : CONNECTING = 2,
32 : AUTHENTICATING = 3,
33 : IN_PROGRESS = 4,
34 : DONE = 5,
35 : };
36 :
37 : class ArchiveAccountManager : public AccountManager
38 : {
39 : public:
40 : using OnExportConfig = std::function<std::map<std::string, std::string>()>;
41 : using OnSyncData = std::function<void(DeviceSync&&)>;
42 :
43 647 : ArchiveAccountManager(const std::string& accountId,
44 : const std::filesystem::path& path,
45 : OnExportConfig&& onExportConfig,
46 : OnSyncData&& onSyncData,
47 : std::string archivePath,
48 : const std::string& nameServer)
49 647 : : AccountManager(accountId, path, nameServer)
50 647 : , onExportConfig_(std::move(onExportConfig))
51 647 : , onSyncData_(std::move(onSyncData))
52 1294 : , archivePath_(std::move(archivePath))
53 647 : {}
54 :
55 : struct ArchiveAccountCredentials : AccountCredentials
56 : {
57 : in_port_t dhtPort;
58 : std::vector<std::string> dhtBootstrap;
59 : dht::crypto::Identity updateIdentity;
60 : };
61 :
62 : void initAuthentication(PrivateKey request,
63 : std::string deviceName,
64 : std::unique_ptr<AccountCredentials> credentials,
65 : AuthSuccessCallback onSuccess,
66 : AuthFailureCallback onFailure,
67 : const OnChangeCallback& onChange) override;
68 :
69 : void startSync(const OnNewDeviceCb&,
70 : const OnDeviceAnnouncedCb& dcb = {},
71 : bool publishPresence = true) override;
72 :
73 : bool changePassword(const std::string& password_old, const std::string& password_new) override;
74 : virtual std::vector<uint8_t> getPasswordKey(const std::string& /*password*/) override;
75 :
76 : void syncDevices() override;
77 :
78 : int32_t addDevice(const std::string& uri,
79 : std::string_view auth_scheme,
80 : AuthChannelHandler*) override;
81 : bool cancelAddDevice(uint32_t token) override;
82 : bool confirmAddDevice(uint32_t token) override;
83 :
84 : bool revokeDevice(const std::string& device,
85 : std::string_view scheme,
86 : const std::string& password,
87 : RevokeDeviceCallback) override;
88 : bool exportArchive(const std::string& destinationPath,
89 : std::string_view scheme,
90 : const std::string& password);
91 : bool isPasswordValid(const std::string& password) override;
92 :
93 : bool provideAccountAuthentication(const std::string& credentialsFromUser,
94 : const std::string& scheme);
95 :
96 : #ifdef ENABLE_NAMESERVER
97 : void registerName(const std::string& name,
98 : std::string_view scheme,
99 : const std::string& password,
100 : RegistrationCallback cb) override;
101 : #endif
102 :
103 : /**
104 : * Change the validity of a certificate. If hash is empty, update all certificates
105 : */
106 : bool setValidity(std::string_view scheme,
107 : const std::string& password,
108 : dht::crypto::Identity& device,
109 : const dht::InfoHash& id,
110 : int64_t validity);
111 :
112 : // for linking devices
113 : void onAuthReady(const std::string& deviceId, std::shared_ptr<dhtnet::ChannelSocket> channel);
114 :
115 : private:
116 : struct DeviceContextBase;
117 : struct AddDeviceContext;
118 : struct LinkDeviceContext;
119 : struct AuthContext {
120 : std::mutex mutex;
121 : std::string accountId;
122 : uint32_t token;
123 : PrivateKey key;
124 : CertRequest request;
125 : std::string deviceName;
126 : std::unique_ptr<ArchiveAccountCredentials> credentials;
127 : std::shared_ptr<LinkDeviceContext> linkDevCtx; // New device
128 : std::unique_ptr<AddDeviceContext> addDeviceCtx; // Source device
129 : AuthSuccessCallback onSuccess;
130 : AuthFailureCallback onFailure;
131 : std::unique_ptr<asio::steady_timer> timeout;
132 : bool canceled {false};
133 : };
134 : struct DecodingContext;
135 : struct AuthMsg;
136 : struct DeviceAuthInfo;
137 : std::shared_ptr<AuthContext> authCtx_;
138 :
139 : void createAccount(AuthContext& ctx);
140 : void migrateAccount(AuthContext& ctx);
141 :
142 : std::pair<std::string, std::shared_ptr<dht::Value>> makeReceipt(
143 : const dht::crypto::Identity& id,
144 : const dht::crypto::Certificate& device,
145 : const std::string& ethAccount);
146 : void updateArchive(AccountArchive& content /*, const ContactList& syncData*/) const;
147 : void saveArchive(AccountArchive& content, std::string_view scheme, const std::string& pwd);
148 : AccountArchive readArchive(std::string_view scheme, const std::string& password) const;
149 : static std::pair<std::vector<uint8_t>, dht::InfoHash> computeKeys(const std::string& password,
150 : const std::string& pin,
151 : bool previous = false);
152 : bool updateCertificates(AccountArchive& archive, dht::crypto::Identity& device);
153 : static bool needsMigration(const std::string& accountId, const dht::crypto::Identity& id);
154 :
155 : void loadFromFile(AuthContext& ctx);
156 :
157 : // for linking devices
158 : void startLoadArchiveFromDevice(const std::shared_ptr<AuthContext>& ctx);
159 :
160 : bool doAddDevice(std::string_view scheme,
161 : const std::shared_ptr<AuthContext>& ctx,
162 : const std::shared_ptr<dhtnet::ChannelSocket>& channel);
163 :
164 : void onArchiveLoaded(AuthContext& ctx, AccountArchive&& a, bool isLinkDevProtocol);
165 :
166 654 : inline std::weak_ptr<ArchiveAccountManager> weak()
167 : {
168 654 : return std::static_pointer_cast<ArchiveAccountManager>(shared_from_this());
169 : }
170 :
171 : OnExportConfig onExportConfig_;
172 : OnSyncData onSyncData_;
173 : std::string archivePath_;
174 : };
175 :
176 : } // namespace jami
|