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 792 : 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 792 : : AccountManager(accountId, path, nameServer)
50 792 : , onExportConfig_(std::move(onExportConfig))
51 792 : , onSyncData_(std::move(onSyncData))
52 1584 : , archivePath_(std::move(archivePath))
53 792 : {}
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&, const OnDeviceAnnouncedCb& dcb = {}, bool publishPresence = true) override;
70 :
71 : bool changePassword(const std::string& password_old, const std::string& password_new) override;
72 : virtual std::vector<uint8_t> getPasswordKey(const std::string& /*password*/) override;
73 :
74 : void syncDevices() override;
75 :
76 : int32_t addDevice(const std::string& uri, std::string_view auth_scheme, AuthChannelHandler*) override;
77 : bool cancelAddDevice(uint32_t token) override;
78 : bool confirmAddDevice(uint32_t token) override;
79 :
80 : bool revokeDevice(const std::string& device,
81 : std::string_view scheme,
82 : const std::string& password,
83 : RevokeDeviceCallback) override;
84 : bool exportArchive(const std::string& destinationPath, std::string_view scheme, const std::string& password);
85 : bool isPasswordValid(const std::string& password) override;
86 :
87 : bool provideAccountAuthentication(const std::string& credentialsFromUser, const std::string& scheme);
88 :
89 : void registerName(const std::string& name,
90 : std::string_view scheme,
91 : const std::string& password,
92 : RegistrationCallback cb) override;
93 :
94 : /**
95 : * Change the validity of a certificate. If hash is empty, update all certificates
96 : */
97 : bool setValidity(std::string_view scheme,
98 : const std::string& password,
99 : dht::crypto::Identity& device,
100 : const dht::InfoHash& id,
101 : int64_t validity);
102 :
103 : // for linking devices
104 : void onAuthReady(const std::string& deviceId, std::shared_ptr<dhtnet::ChannelSocket> channel);
105 :
106 : private:
107 : struct DeviceContextBase;
108 : struct AddDeviceContext;
109 : struct LinkDeviceContext;
110 : struct AuthContext
111 : {
112 : std::mutex mutex;
113 : std::string accountId;
114 : uint32_t token;
115 : PrivateKey key;
116 : CertRequest request;
117 : std::string deviceName;
118 : std::unique_ptr<ArchiveAccountCredentials> credentials;
119 : std::shared_ptr<LinkDeviceContext> linkDevCtx; // New device
120 : std::unique_ptr<AddDeviceContext> addDeviceCtx; // Source device
121 : AuthSuccessCallback onSuccess;
122 : AuthFailureCallback onFailure;
123 : std::unique_ptr<asio::steady_timer> timeout;
124 : bool canceled {false};
125 : };
126 : struct AuthMsg;
127 : struct DeviceAuthInfo;
128 : std::shared_ptr<AuthContext> authCtx_;
129 :
130 : void createAccount(AuthContext& ctx);
131 : void migrateAccount(AuthContext& ctx);
132 :
133 : std::pair<std::string, std::shared_ptr<dht::Value>> makeReceipt(const dht::crypto::Identity& id,
134 : const dht::crypto::Certificate& device,
135 : const std::string& ethAccount);
136 : void updateArchive(AccountArchive& content /*, const ContactList& syncData*/) const;
137 : void saveArchive(AccountArchive& content, std::string_view scheme, const std::string& pwd);
138 : AccountArchive readArchive(std::string_view scheme, const std::string& password) const;
139 : static std::pair<std::vector<uint8_t>, dht::InfoHash> computeKeys(const std::string& password,
140 : const std::string& pin,
141 : bool previous = false);
142 : bool updateCertificates(AccountArchive& archive, dht::crypto::Identity& device);
143 : static bool needsMigration(const std::string& accountId, const dht::crypto::Identity& id);
144 :
145 : void loadFromFile(AuthContext& ctx);
146 :
147 : // for linking devices
148 : void startLoadArchiveFromDevice(const std::shared_ptr<AuthContext>& ctx);
149 :
150 : bool doAddDevice(std::string_view scheme,
151 : const std::shared_ptr<AuthContext>& ctx,
152 : std::shared_ptr<dhtnet::ChannelSocket> channel);
153 :
154 : void onArchiveLoaded(AuthContext& ctx, AccountArchive&& a, bool isLinkDevProtocol);
155 :
156 796 : inline std::weak_ptr<ArchiveAccountManager> weak()
157 : {
158 796 : return std::static_pointer_cast<ArchiveAccountManager>(shared_from_this());
159 : }
160 :
161 : OnExportConfig onExportConfig_;
162 : OnSyncData onSyncData_;
163 : std::string archivePath_;
164 : };
165 :
166 : } // namespace jami
|