]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java
Improve behavior when pin data doesn't exist on the server
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / helper / PinHelper.java
1 package org.asamk.signal.manager.helper;
2
3 import org.asamk.signal.manager.api.IncorrectPinException;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6 import org.whispersystems.signalservice.api.kbs.MasterKey;
7 import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
8 import org.whispersystems.signalservice.internal.push.AuthCredentials;
9 import org.whispersystems.signalservice.internal.push.LockedException;
10
11 import java.io.IOException;
12 import java.util.List;
13
14 public class PinHelper {
15
16 private static final Logger logger = LoggerFactory.getLogger(PinHelper.class);
17
18 private final List<SecureValueRecovery> secureValueRecoveries;
19
20 public PinHelper(final List<SecureValueRecovery> secureValueRecoveries) {
21 this.secureValueRecoveries = secureValueRecoveries;
22 }
23
24 public void setRegistrationLockPin(String pin, MasterKey masterKey) throws IOException {
25 IOException exception = null;
26 for (final var secureValueRecovery : secureValueRecoveries) {
27 try {
28 final var backupResponse = secureValueRecovery.setPin(pin, masterKey).execute();
29 switch (backupResponse) {
30 case SecureValueRecovery.BackupResponse.Success success -> {
31 }
32 case SecureValueRecovery.BackupResponse.ServerRejected serverRejected ->
33 logger.warn("Backup svr failed: ServerRejected");
34 case SecureValueRecovery.BackupResponse.EnclaveNotFound enclaveNotFound ->
35 logger.warn("Backup svr failed: EnclaveNotFound");
36 case SecureValueRecovery.BackupResponse.ExposeFailure exposeFailure ->
37 logger.warn("Backup svr failed: ExposeFailure");
38 case SecureValueRecovery.BackupResponse.ApplicationError error ->
39 throw new IOException(error.getException());
40 case SecureValueRecovery.BackupResponse.NetworkError error -> throw error.getException();
41 case null, default -> throw new AssertionError("Unexpected response");
42 }
43 } catch (IOException e) {
44 exception = e;
45 }
46 }
47 if (exception != null) {
48 throw exception;
49 }
50 }
51
52 public void migrateRegistrationLockPin(String pin, MasterKey masterKey) throws IOException {
53 setRegistrationLockPin(pin, masterKey);
54 }
55
56 public void removeRegistrationLockPin() throws IOException {
57 IOException exception = null;
58 for (final var secureValueRecovery : secureValueRecoveries) {
59 try {
60 final var deleteResponse = secureValueRecovery.deleteData();
61 switch (deleteResponse) {
62 case SecureValueRecovery.DeleteResponse.Success success -> {
63 }
64 case SecureValueRecovery.DeleteResponse.ServerRejected serverRejected ->
65 logger.warn("Delete svr2 failed: ServerRejected");
66 case SecureValueRecovery.DeleteResponse.EnclaveNotFound enclaveNotFound ->
67 logger.warn("Delete svr2 failed: EnclaveNotFound");
68 case SecureValueRecovery.DeleteResponse.ApplicationError error ->
69 throw new IOException(error.getException());
70 case SecureValueRecovery.DeleteResponse.NetworkError error -> throw error.getException();
71 case null, default -> throw new AssertionError("Unexpected response");
72 }
73 } catch (IOException e) {
74 exception = e;
75 }
76 }
77 if (exception != null) {
78 throw exception;
79 }
80 }
81
82 public SecureValueRecovery.RestoreResponse.Success getRegistrationLockData(
83 String pin,
84 LockedException lockedException
85 ) throws IOException, IncorrectPinException {
86 var svr2Credentials = lockedException.getSvr2Credentials();
87 if (svr2Credentials != null) {
88 IOException exception = null;
89 for (final var secureValueRecovery : secureValueRecoveries) {
90 try {
91 final var lockData = getRegistrationLockData(secureValueRecovery, svr2Credentials, pin);
92 if (lockData == null) {
93 continue;
94 }
95 return lockData;
96 } catch (IOException e) {
97 exception = e;
98 }
99 }
100 if (exception != null) {
101 throw exception;
102 }
103 }
104
105 return null;
106 }
107
108 public SecureValueRecovery.RestoreResponse.Success getRegistrationLockData(
109 SecureValueRecovery secureValueRecovery,
110 AuthCredentials authCredentials,
111 String pin
112 ) throws IOException, IncorrectPinException {
113 final var restoreResponse = secureValueRecovery.restoreDataPreRegistration(authCredentials, null, pin);
114
115 switch (restoreResponse) {
116 case SecureValueRecovery.RestoreResponse.Success s -> {
117 return s;
118 }
119 case SecureValueRecovery.RestoreResponse.PinMismatch pinMismatch ->
120 throw new IncorrectPinException(pinMismatch.getTriesRemaining());
121 case SecureValueRecovery.RestoreResponse.ApplicationError error ->
122 throw new IOException(error.getException());
123 case SecureValueRecovery.RestoreResponse.NetworkError error -> throw error.getException();
124 case SecureValueRecovery.RestoreResponse.Missing missing -> {
125 logger.debug("No SVR data stored for the given credentials.");
126 return null;
127 }
128 case null, default ->
129 throw new AssertionError("Unexpected response: " + restoreResponse.getClass().getSimpleName());
130 }
131 }
132 }