]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/SignalDependencies.java
Fix NoSuchElementException in json serialization for messages from an untrusted identity
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / SignalDependencies.java
1 package org.asamk.signal.manager;
2
3 import org.asamk.signal.manager.config.ServiceConfig;
4 import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
5 import org.signal.libsignal.metadata.certificate.CertificateValidator;
6 import org.signal.zkgroup.profiles.ClientZkProfileOperations;
7 import org.whispersystems.libsignal.util.guava.Optional;
8 import org.whispersystems.signalservice.api.KeyBackupService;
9 import org.whispersystems.signalservice.api.SignalServiceAccountManager;
10 import org.whispersystems.signalservice.api.SignalServiceDataStore;
11 import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
12 import org.whispersystems.signalservice.api.SignalServiceMessageSender;
13 import org.whispersystems.signalservice.api.SignalSessionLock;
14 import org.whispersystems.signalservice.api.SignalWebSocket;
15 import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
16 import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
17 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
18 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
19 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
20 import org.whispersystems.signalservice.api.services.ProfileService;
21 import org.whispersystems.signalservice.api.util.CredentialsProvider;
22 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
23 import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
24 import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
25
26 import java.util.concurrent.ExecutorService;
27 import java.util.function.Supplier;
28
29 import static org.asamk.signal.manager.config.ServiceConfig.capabilities;
30
31 public class SignalDependencies {
32
33 private final Object LOCK = new Object();
34
35 private final ServiceEnvironmentConfig serviceEnvironmentConfig;
36 private final String userAgent;
37 private final CredentialsProvider credentialsProvider;
38 private final SignalServiceDataStore dataStore;
39 private final ExecutorService executor;
40 private final SignalSessionLock sessionLock;
41
42 private SignalServiceAccountManager accountManager;
43 private GroupsV2Api groupsV2Api;
44 private GroupsV2Operations groupsV2Operations;
45 private ClientZkOperations clientZkOperations;
46
47 private SignalWebSocket signalWebSocket;
48 private SignalServiceMessageReceiver messageReceiver;
49 private SignalServiceMessageSender messageSender;
50
51 private KeyBackupService keyBackupService;
52 private ProfileService profileService;
53 private SignalServiceCipher cipher;
54
55 SignalDependencies(
56 final ServiceEnvironmentConfig serviceEnvironmentConfig,
57 final String userAgent,
58 final CredentialsProvider credentialsProvider,
59 final SignalServiceDataStore dataStore,
60 final ExecutorService executor,
61 final SignalSessionLock sessionLock
62 ) {
63 this.serviceEnvironmentConfig = serviceEnvironmentConfig;
64 this.userAgent = userAgent;
65 this.credentialsProvider = credentialsProvider;
66 this.dataStore = dataStore;
67 this.executor = executor;
68 this.sessionLock = sessionLock;
69 }
70
71 public void resetAfterAddressChange() {
72 this.messageSender = null;
73 this.cipher = null;
74 }
75
76 public ServiceEnvironmentConfig getServiceEnvironmentConfig() {
77 return serviceEnvironmentConfig;
78 }
79
80 public SignalServiceAccountManager getAccountManager() {
81 return getOrCreate(() -> accountManager,
82 () -> accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
83 credentialsProvider,
84 userAgent,
85 getGroupsV2Operations(),
86 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
87 }
88
89 public SignalServiceAccountManager createUnauthenticatedAccountManager(String number, String password) {
90 return new SignalServiceAccountManager(getServiceEnvironmentConfig().getSignalServiceConfiguration(),
91 null,
92 null,
93 number,
94 SignalServiceAddress.DEFAULT_DEVICE_ID,
95 password,
96 userAgent,
97 ServiceConfig.AUTOMATIC_NETWORK_RETRY);
98 }
99
100 public GroupsV2Api getGroupsV2Api() {
101 return getOrCreate(() -> groupsV2Api, () -> groupsV2Api = getAccountManager().getGroupsV2Api());
102 }
103
104 public GroupsV2Operations getGroupsV2Operations() {
105 return getOrCreate(() -> groupsV2Operations,
106 () -> groupsV2Operations = capabilities.isGv2() ? new GroupsV2Operations(ClientZkOperations.create(
107 serviceEnvironmentConfig.getSignalServiceConfiguration())) : null);
108 }
109
110 private ClientZkOperations getClientZkOperations() {
111 return getOrCreate(() -> clientZkOperations,
112 () -> clientZkOperations = capabilities.isGv2()
113 ? ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration())
114 : null);
115 }
116
117 private ClientZkProfileOperations getClientZkProfileOperations() {
118 final var clientZkOperations = getClientZkOperations();
119 return clientZkOperations == null ? null : clientZkOperations.getProfileOperations();
120 }
121
122 public SignalWebSocket getSignalWebSocket() {
123 return getOrCreate(() -> signalWebSocket, () -> {
124 final var timer = new UptimeSleepTimer();
125 final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
126 final var webSocketFactory = new WebSocketFactory() {
127 @Override
128 public WebSocketConnection createWebSocket() {
129 return new WebSocketConnection("normal",
130 serviceEnvironmentConfig.getSignalServiceConfiguration(),
131 Optional.of(credentialsProvider),
132 userAgent,
133 healthMonitor);
134 }
135
136 @Override
137 public WebSocketConnection createUnidentifiedWebSocket() {
138 return new WebSocketConnection("unidentified",
139 serviceEnvironmentConfig.getSignalServiceConfiguration(),
140 Optional.absent(),
141 userAgent,
142 healthMonitor);
143 }
144 };
145 signalWebSocket = new SignalWebSocket(webSocketFactory);
146 healthMonitor.monitor(signalWebSocket);
147 });
148 }
149
150 public SignalServiceMessageReceiver getMessageReceiver() {
151 return getOrCreate(() -> messageReceiver,
152 () -> messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.getSignalServiceConfiguration(),
153 credentialsProvider,
154 userAgent,
155 getClientZkProfileOperations(),
156 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
157 }
158
159 public SignalServiceMessageSender getMessageSender() {
160 return getOrCreate(() -> messageSender,
161 () -> messageSender = new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
162 credentialsProvider,
163 dataStore,
164 sessionLock,
165 userAgent,
166 getSignalWebSocket(),
167 Optional.absent(),
168 getClientZkProfileOperations(),
169 executor,
170 ServiceConfig.MAX_ENVELOPE_SIZE,
171 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
172 }
173
174 public KeyBackupService getKeyBackupService() {
175 return getOrCreate(() -> keyBackupService,
176 () -> keyBackupService = getAccountManager().getKeyBackupService(ServiceConfig.getIasKeyStore(),
177 serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
178 serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
179 serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
180 10));
181 }
182
183 public ProfileService getProfileService() {
184 return getOrCreate(() -> profileService,
185 () -> profileService = new ProfileService(getClientZkProfileOperations(),
186 getMessageReceiver(),
187 getSignalWebSocket()));
188 }
189
190 public SignalServiceCipher getCipher() {
191 return getOrCreate(() -> cipher, () -> {
192 final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
193 final var address = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
194 final var deviceId = credentialsProvider.getDeviceId();
195 cipher = new SignalServiceCipher(address, deviceId, dataStore.aci(), sessionLock, certificateValidator);
196 });
197 }
198
199 private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
200 var value = supplier.get();
201 if (value != null) {
202 return value;
203 }
204
205 synchronized (LOCK) {
206 value = supplier.get();
207 if (value != null) {
208 return value;
209 }
210 creator.call();
211 return supplier.get();
212 }
213 }
214
215 private interface Callable {
216
217 void call();
218 }
219 }