mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
parent
6dd1a21606
commit
6c3106db5d
10 changed files with 132 additions and 35 deletions
|
@ -43,6 +43,7 @@ import org.asamk.signal.manager.storage.groups.GroupInfo;
|
|||
import org.asamk.signal.manager.storage.groups.GroupInfoV1;
|
||||
import org.asamk.signal.manager.storage.groups.GroupInfoV2;
|
||||
import org.asamk.signal.manager.storage.identities.IdentityInfo;
|
||||
import org.asamk.signal.manager.storage.identities.TrustNewIdentity;
|
||||
import org.asamk.signal.manager.storage.messageCache.CachedMessage;
|
||||
import org.asamk.signal.manager.storage.recipients.Contact;
|
||||
import org.asamk.signal.manager.storage.recipients.Profile;
|
||||
|
@ -270,7 +271,11 @@ public class Manager implements Closeable {
|
|||
}
|
||||
|
||||
public static Manager init(
|
||||
String username, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
|
||||
String username,
|
||||
File settingsPath,
|
||||
ServiceEnvironment serviceEnvironment,
|
||||
String userAgent,
|
||||
final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException, NotRegisteredException {
|
||||
var pathConfig = PathConfig.createDefault(settingsPath);
|
||||
|
||||
|
@ -278,7 +283,7 @@ public class Manager implements Closeable {
|
|||
throw new NotRegisteredException();
|
||||
}
|
||||
|
||||
var account = SignalAccount.load(pathConfig.getDataPath(), username, true);
|
||||
var account = SignalAccount.load(pathConfig.getDataPath(), username, true, trustNewIdentity);
|
||||
|
||||
if (!account.isRegistered()) {
|
||||
throw new NotRegisteredException();
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.asamk.signal.manager.config.ServiceConfig;
|
|||
import org.asamk.signal.manager.config.ServiceEnvironment;
|
||||
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.identities.TrustNewIdentity;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -121,7 +122,8 @@ public class ProvisioningManager {
|
|||
deviceId,
|
||||
ret.getIdentity(),
|
||||
registrationId,
|
||||
profileKey);
|
||||
profileKey,
|
||||
TrustNewIdentity.ON_FIRST_USE);
|
||||
|
||||
Manager m = null;
|
||||
try {
|
||||
|
@ -161,7 +163,7 @@ public class ProvisioningManager {
|
|||
private boolean canRelinkExistingAccount(final String number) throws IOException {
|
||||
final SignalAccount signalAccount;
|
||||
try {
|
||||
signalAccount = SignalAccount.load(pathConfig.getDataPath(), number, false);
|
||||
signalAccount = SignalAccount.load(pathConfig.getDataPath(), number, false, TrustNewIdentity.ON_FIRST_USE);
|
||||
} catch (IOException e) {
|
||||
logger.debug("Account in use or failed to load.", e);
|
||||
return false;
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.asamk.signal.manager.config.ServiceEnvironment;
|
|||
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||
import org.asamk.signal.manager.helper.PinHelper;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.identities.TrustNewIdentity;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -102,12 +103,13 @@ public class RegistrationManager implements Closeable {
|
|||
username,
|
||||
identityKey,
|
||||
registrationId,
|
||||
profileKey);
|
||||
profileKey,
|
||||
TrustNewIdentity.ON_FIRST_USE);
|
||||
|
||||
return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
|
||||
}
|
||||
|
||||
var account = SignalAccount.load(pathConfig.getDataPath(), username, true);
|
||||
var account = SignalAccount.load(pathConfig.getDataPath(), username, true, TrustNewIdentity.ON_FIRST_USE);
|
||||
|
||||
return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.asamk.signal.manager.storage.contacts.LegacyJsonContactsStore;
|
|||
import org.asamk.signal.manager.storage.groups.GroupInfoV1;
|
||||
import org.asamk.signal.manager.storage.groups.GroupStore;
|
||||
import org.asamk.signal.manager.storage.identities.IdentityKeyStore;
|
||||
import org.asamk.signal.manager.storage.identities.TrustNewIdentity;
|
||||
import org.asamk.signal.manager.storage.messageCache.MessageCache;
|
||||
import org.asamk.signal.manager.storage.prekeys.PreKeyStore;
|
||||
import org.asamk.signal.manager.storage.prekeys.SignedPreKeyStore;
|
||||
|
@ -106,12 +107,14 @@ public class SignalAccount implements Closeable {
|
|||
this.lock = lock;
|
||||
}
|
||||
|
||||
public static SignalAccount load(File dataPath, String username, boolean waitForLock) throws IOException {
|
||||
public static SignalAccount load(
|
||||
File dataPath, String username, boolean waitForLock, final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
final var fileName = getFileName(dataPath, username);
|
||||
final var pair = openFileChannel(fileName, waitForLock);
|
||||
try {
|
||||
var account = new SignalAccount(pair.first(), pair.second());
|
||||
account.load(dataPath);
|
||||
account.load(dataPath, trustNewIdentity);
|
||||
account.migrateLegacyConfigs();
|
||||
|
||||
if (!username.equals(account.getUsername())) {
|
||||
|
@ -128,7 +131,12 @@ public class SignalAccount implements Closeable {
|
|||
}
|
||||
|
||||
public static SignalAccount create(
|
||||
File dataPath, String username, IdentityKeyPair identityKey, int registrationId, ProfileKey profileKey
|
||||
File dataPath,
|
||||
String username,
|
||||
IdentityKeyPair identityKey,
|
||||
int registrationId,
|
||||
ProfileKey profileKey,
|
||||
final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
IOUtils.createPrivateDirectories(dataPath);
|
||||
var fileName = getFileName(dataPath, username);
|
||||
|
@ -142,7 +150,7 @@ public class SignalAccount implements Closeable {
|
|||
account.username = username;
|
||||
account.profileKey = profileKey;
|
||||
|
||||
account.initStores(dataPath, identityKey, registrationId);
|
||||
account.initStores(dataPath, identityKey, registrationId, trustNewIdentity);
|
||||
account.groupStore = new GroupStore(getGroupCachePath(dataPath, username),
|
||||
account.recipientStore::resolveRecipient,
|
||||
account::saveGroupStore);
|
||||
|
@ -157,7 +165,10 @@ public class SignalAccount implements Closeable {
|
|||
}
|
||||
|
||||
private void initStores(
|
||||
final File dataPath, final IdentityKeyPair identityKey, final int registrationId
|
||||
final File dataPath,
|
||||
final IdentityKeyPair identityKey,
|
||||
final int registrationId,
|
||||
final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
recipientStore = RecipientStore.load(getRecipientsStoreFile(dataPath, username), this::mergeRecipients);
|
||||
|
||||
|
@ -167,7 +178,8 @@ public class SignalAccount implements Closeable {
|
|||
identityKeyStore = new IdentityKeyStore(getIdentitiesPath(dataPath, username),
|
||||
recipientStore::resolveRecipient,
|
||||
identityKey,
|
||||
registrationId);
|
||||
registrationId,
|
||||
trustNewIdentity);
|
||||
signalProtocolStore = new SignalProtocolStore(preKeyStore,
|
||||
signedPreKeyStore,
|
||||
sessionStore,
|
||||
|
@ -186,7 +198,8 @@ public class SignalAccount implements Closeable {
|
|||
int deviceId,
|
||||
IdentityKeyPair identityKey,
|
||||
int registrationId,
|
||||
ProfileKey profileKey
|
||||
ProfileKey profileKey,
|
||||
final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
IOUtils.createPrivateDirectories(dataPath);
|
||||
var fileName = getFileName(dataPath, username);
|
||||
|
@ -199,10 +212,11 @@ public class SignalAccount implements Closeable {
|
|||
deviceId,
|
||||
identityKey,
|
||||
registrationId,
|
||||
profileKey);
|
||||
profileKey,
|
||||
trustNewIdentity);
|
||||
}
|
||||
|
||||
final var account = load(dataPath, username, true);
|
||||
final var account = load(dataPath, username, true, trustNewIdentity);
|
||||
account.setProvisioningData(username, uuid, password, encryptedDeviceName, deviceId, profileKey);
|
||||
account.recipientStore.resolveRecipientTrusted(account.getSelfAddress());
|
||||
account.sessionStore.archiveAllSessions();
|
||||
|
@ -227,7 +241,8 @@ public class SignalAccount implements Closeable {
|
|||
int deviceId,
|
||||
IdentityKeyPair identityKey,
|
||||
int registrationId,
|
||||
ProfileKey profileKey
|
||||
ProfileKey profileKey,
|
||||
final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
var fileName = getFileName(dataPath, username);
|
||||
IOUtils.createPrivateFile(fileName);
|
||||
|
@ -237,7 +252,7 @@ public class SignalAccount implements Closeable {
|
|||
|
||||
account.setProvisioningData(username, uuid, password, encryptedDeviceName, deviceId, profileKey);
|
||||
|
||||
account.initStores(dataPath, identityKey, registrationId);
|
||||
account.initStores(dataPath, identityKey, registrationId, trustNewIdentity);
|
||||
account.groupStore = new GroupStore(getGroupCachePath(dataPath, username),
|
||||
account.recipientStore::resolveRecipient,
|
||||
account::saveGroupStore);
|
||||
|
@ -339,7 +354,9 @@ public class SignalAccount implements Closeable {
|
|||
return !(!f.exists() || f.isDirectory());
|
||||
}
|
||||
|
||||
private void load(File dataPath) throws IOException {
|
||||
private void load(
|
||||
File dataPath, final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
JsonNode rootNode;
|
||||
synchronized (fileChannel) {
|
||||
fileChannel.position(0);
|
||||
|
@ -428,7 +445,7 @@ public class SignalAccount implements Closeable {
|
|||
migratedLegacyConfig = true;
|
||||
}
|
||||
|
||||
initStores(dataPath, identityKeyPair, registrationId);
|
||||
initStores(dataPath, identityKeyPair, registrationId, trustNewIdentity);
|
||||
|
||||
migratedLegacyConfig = loadLegacyStores(rootNode, legacySignalProtocolStore) || migratedLegacyConfig;
|
||||
|
||||
|
|
|
@ -42,17 +42,20 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden
|
|||
private final RecipientResolver resolver;
|
||||
private final IdentityKeyPair identityKeyPair;
|
||||
private final int localRegistrationId;
|
||||
private final TrustNewIdentity trustNewIdentity;
|
||||
|
||||
public IdentityKeyStore(
|
||||
final File identitiesPath,
|
||||
final RecipientResolver resolver,
|
||||
final IdentityKeyPair identityKeyPair,
|
||||
final int localRegistrationId
|
||||
final int localRegistrationId,
|
||||
final TrustNewIdentity trustNewIdentity
|
||||
) {
|
||||
this.identitiesPath = identitiesPath;
|
||||
this.resolver = resolver;
|
||||
this.identityKeyPair = identityKeyPair;
|
||||
this.localRegistrationId = localRegistrationId;
|
||||
this.trustNewIdentity = trustNewIdentity;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -80,7 +83,10 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden
|
|||
return false;
|
||||
}
|
||||
|
||||
final var trustLevel = identityInfo == null ? TrustLevel.TRUSTED_UNVERIFIED : TrustLevel.UNTRUSTED;
|
||||
final var trustLevel = trustNewIdentity == TrustNewIdentity.ALWAYS || (
|
||||
trustNewIdentity == TrustNewIdentity.ON_FIRST_USE && identityInfo == null
|
||||
) ? TrustLevel.TRUSTED_UNVERIFIED : TrustLevel.UNTRUSTED;
|
||||
logger.debug("Storing new identity for recipient {} with trust {}", recipientId, trustLevel);
|
||||
final var newIdentityInfo = new IdentityInfo(recipientId, identityKey, trustLevel, added);
|
||||
storeIdentityLocked(recipientId, newIdentityInfo);
|
||||
return true;
|
||||
|
@ -108,13 +114,17 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden
|
|||
|
||||
@Override
|
||||
public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
|
||||
if (trustNewIdentity == TrustNewIdentity.ALWAYS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var recipientId = resolveRecipient(address.getName());
|
||||
|
||||
synchronized (cachedIdentities) {
|
||||
final var identityInfo = loadIdentityLocked(recipientId);
|
||||
if (identityInfo == null) {
|
||||
// Identity not found
|
||||
return true;
|
||||
return trustNewIdentity == TrustNewIdentity.ON_FIRST_USE;
|
||||
}
|
||||
|
||||
// TODO implement possibility for different handling of incoming/outgoing trust decisions
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package org.asamk.signal.manager.storage.identities;
|
||||
|
||||
public enum TrustNewIdentity {
|
||||
ALWAYS,
|
||||
ON_FIRST_USE,
|
||||
NEVER
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue