X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/063fb95dca87b6b57996c7379b958ae05e2e5ad9..d7f7c84e6c023e96064efcfcc29a78440866218a:/src/main/java/org/asamk/signal/manager/Manager.java diff --git a/src/main/java/org/asamk/signal/manager/Manager.java b/src/main/java/org/asamk/signal/manager/Manager.java index 8d0d46c8..69e45102 100644 --- a/src/main/java/org/asamk/signal/manager/Manager.java +++ b/src/main/java/org/asamk/signal/manager/Manager.java @@ -41,6 +41,8 @@ import org.signal.libsignal.metadata.ProtocolLegacyMessageException; import org.signal.libsignal.metadata.ProtocolNoSessionException; import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException; import org.signal.libsignal.metadata.SelfSendException; +import org.signal.zkgroup.InvalidInputException; +import org.signal.zkgroup.profiles.ProfileKey; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.InvalidKeyException; @@ -84,6 +86,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage; import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage; import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage; +import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.ContactTokenDetails; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; @@ -126,6 +129,8 @@ import java.util.concurrent.TimeoutException; public class Manager implements Signal { + private static final SignalServiceProfile.Capabilities capabilities = new SignalServiceProfile.Capabilities(false, false); + private final String settingsPath; private final String dataPath; private final String attachmentsPath; @@ -237,7 +242,7 @@ public class Manager implements Signal { if (username == null) { account = SignalAccount.createTemporaryAccount(identityKey, registrationId); } else { - byte[] profileKey = KeyUtils.createProfileKey(); + ProfileKey profileKey = KeyUtils.createProfileKey(); account = SignalAccount.create(dataPath, username, identityKey, registrationId, profileKey); account.save(); } @@ -255,9 +260,9 @@ public class Manager implements Signal { accountManager = getSignalServiceAccountManager(); if (voiceVerification) { - accountManager.requestVoiceVerificationCode(Locale.getDefault(), Optional.absent(), Optional.absent()); + accountManager.requestVoiceVerificationCode(Locale.getDefault(), Optional.absent(), Optional.absent()); } else { - accountManager.requestSmsVerificationCode(false, Optional.absent(), Optional.absent()); + accountManager.requestSmsVerificationCode(false, Optional.absent(), Optional.absent()); } account.setRegistered(false); @@ -265,7 +270,7 @@ public class Manager implements Signal { } public void updateAccountAttributes() throws IOException { - accountManager.setAccountAttributes(account.getSignalingKey(), account.getSignalProtocolStore().getLocalRegistrationId(), true, account.getRegistrationLockPin(), account.getRegistrationLock(), getSelfUnidentifiedAccessKey(), false); + accountManager.setAccountAttributes(account.getSignalingKey(), account.getSignalProtocolStore().getLocalRegistrationId(), true, account.getRegistrationLockPin(), account.getRegistrationLock(), getSelfUnidentifiedAccessKey(), false, capabilities); } public void setProfileName(String name) throws IOException { @@ -286,7 +291,7 @@ public class Manager implements Signal { // When setting an empty GCM id, the Signal-Server also sets the fetchesMessages property to false. // If this is the master device, other users can't send messages to this number anymore. // If this is a linked device, other users can still send messages, but this device doesn't receive them anymore. - accountManager.setGcmId(Optional.absent()); + accountManager.setGcmId(Optional.absent()); account.setRegistered(false); account.save(); @@ -314,9 +319,16 @@ public class Manager implements Signal { } // Create new account with the synced identity - byte[] profileKey = ret.getProfileKey(); - if (profileKey == null) { + byte[] profileKeyBytes = ret.getProfileKey(); + ProfileKey profileKey; + if (profileKeyBytes == null) { profileKey = KeyUtils.createProfileKey(); + } else { + try { + profileKey = new ProfileKey(profileKeyBytes); + } catch (InvalidInputException e) { + throw new IOException("Received invalid profileKey", e); + } } account = SignalAccount.createLinkedAccount(dataPath, username, account.getPassword(), ret.getDeviceId(), ret.getIdentity(), account.getSignalProtocolStore().getLocalRegistrationId(), account.getSignalingKey(), profileKey); @@ -354,7 +366,7 @@ public class Manager implements Signal { IdentityKeyPair identityKeyPair = account.getSignalProtocolStore().getIdentityKeyPair(); String verificationCode = accountManager.getNewDeviceVerificationCode(); - accountManager.addDevice(deviceIdentifier, deviceKey, identityKeyPair, Optional.of(account.getProfileKey()), verificationCode); + accountManager.addDevice(deviceIdentifier, deviceKey, identityKeyPair, Optional.of(account.getProfileKey().serialize()), verificationCode); account.setMultiDevice(true); account.save(); } @@ -396,7 +408,7 @@ public class Manager implements Signal { verificationCode = verificationCode.replace("-", ""); account.setSignalingKey(KeyUtils.createSignalingKey()); // TODO make unrestricted unidentified access configurable - accountManager.verifyAccountWithCode(verificationCode, account.getSignalingKey(), account.getSignalProtocolStore().getLocalRegistrationId(), true, pin, null, getSelfUnidentifiedAccessKey(), false); + accountManager.verifyAccountWithCode(verificationCode, account.getSignalingKey(), account.getSignalProtocolStore().getLocalRegistrationId(), true, pin, null, getSelfUnidentifiedAccessKey(), false, capabilities); //accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID))); account.setRegistered(true); @@ -431,7 +443,7 @@ public class Manager implements Signal { private SignalServiceMessageSender getMessageSender() { return new SignalServiceMessageSender(BaseConfig.serviceConfiguration, null, username, account.getPassword(), - account.getDeviceId(), account.getSignalProtocolStore(), BaseConfig.USER_AGENT, account.isMultiDevice(), Optional.fromNullable(messagePipe), Optional.fromNullable(unidentifiedMessagePipe), Optional.absent()); + account.getDeviceId(), account.getSignalProtocolStore(), BaseConfig.USER_AGENT, account.isMultiDevice(), Optional.fromNullable(messagePipe), Optional.fromNullable(unidentifiedMessagePipe), Optional.absent()); } private Optional createGroupAvatarAttachment(byte[] groupId) throws IOException { @@ -502,7 +514,7 @@ public class Manager implements Signal { SignalServiceDataMessage.Reaction reaction = new SignalServiceDataMessage.Reaction(emoji, remove, targetAuthor, targetSentTimestamp); final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() .withReaction(reaction) - .withProfileKey(account.getProfileKey()); + .withProfileKey(account.getProfileKey().serialize()); if (groupId != null) { SignalServiceGroup group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.DELIVER) .withId(groupId) @@ -685,7 +697,7 @@ public class Manager implements Signal { messageBuilder.withAttachments(attachmentPointers); } - messageBuilder.withProfileKey(account.getProfileKey()); + messageBuilder.withProfileKey(account.getProfileKey().serialize()); sendMessageLegacy(messageBuilder, recipients); } @@ -695,7 +707,7 @@ public class Manager implements Signal { SignalServiceDataMessage.Reaction reaction = new SignalServiceDataMessage.Reaction(emoji, remove, targetAuthor, targetSentTimestamp); final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() .withReaction(reaction) - .withProfileKey(account.getProfileKey()); + .withProfileKey(account.getProfileKey().serialize()); sendMessageLegacy(messageBuilder, recipients); } @@ -879,7 +891,7 @@ public class Manager implements Signal { private List> getAccessFor(Collection recipients) { List> result = new ArrayList<>(recipients.size()); for (SignalServiceAddress recipient : recipients) { - result.add(Optional.absent()); + result.add(Optional.absent()); } return result; } @@ -1117,7 +1129,10 @@ public class Manager implements Signal { } if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) { if (source.equals(username)) { - this.account.setProfileKey(message.getProfileKey().get()); + try { + this.account.setProfileKey(new ProfileKey(message.getProfileKey().get())); + } catch (InvalidInputException ignored) { + } } ContactInfo contact = account.getContactStore().getContact(source); if (contact == null) { @@ -1202,16 +1217,13 @@ public class Manager implements Signal { Exception exception = null; final long now = new Date().getTime(); try { - envelope = messagePipe.read(timeout, unit, new SignalServiceMessagePipe.MessagePipeCallback() { - @Override - public void onMessage(SignalServiceEnvelope envelope) { - // store message on disk, before acknowledging receipt to the server - try { - File cacheFile = getMessageCacheFile(envelope.getSourceE164().get(), now, envelope.getTimestamp()); - Utils.storeEnvelope(envelope, cacheFile); - } catch (IOException e) { - System.err.println("Failed to store encrypted message in disk cache, ignoring: " + e.getMessage()); - } + envelope = messagePipe.read(timeout, unit, envelope1 -> { + // store message on disk, before acknowledging receipt to the server + try { + File cacheFile = getMessageCacheFile(envelope1.getSourceE164().get(), now, envelope1.getTimestamp()); + Utils.storeEnvelope(envelope1, cacheFile); + } catch (IOException e) { + System.err.println("Failed to store encrypted message in disk cache, ignoring: " + e.getMessage()); } }); } catch (TimeoutException e) { @@ -1413,7 +1425,7 @@ public class Manager implements Signal { contact.color = c.getColor().get(); } if (c.getProfileKey().isPresent()) { - contact.profileKey = Base64.encodeBytes(c.getProfileKey().get()); + contact.profileKey = Base64.encodeBytes(c.getProfileKey().get().serialize()); } if (c.getVerified().isPresent()) { final VerifiedMessage verifiedMessage = c.getVerified().get(); @@ -1603,7 +1615,11 @@ public class Manager implements Signal { } } - byte[] profileKey = record.profileKey == null ? null : Base64.decode(record.profileKey); + ProfileKey profileKey = null; + try { + profileKey = record.profileKey == null ? null : new ProfileKey(Base64.decode(record.profileKey)); + } catch (InvalidInputException ignored) { + } out.write(new DeviceContact(record.getAddress(), Optional.fromNullable(record.name), createContactAvatarAttachment(record.number), Optional.fromNullable(record.color), Optional.fromNullable(verifiedMessage), Optional.fromNullable(profileKey), record.blocked, @@ -1614,10 +1630,10 @@ public class Manager implements Signal { if (account.getProfileKey() != null) { // Send our own profile key as well out.write(new DeviceContact(account.getSelfAddress(), - Optional.absent(), Optional.absent(), - Optional.absent(), Optional.absent(), + Optional.absent(), Optional.absent(), + Optional.absent(), Optional.absent(), Optional.of(account.getProfileKey()), - false, Optional.absent(), Optional.absent(), false)); + false, Optional.absent(), Optional.absent(), false)); } }