X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/c72aeed8bba4d5ca873b36b4edb2b8eda9c24ec7..HEAD:/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java diff --git a/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java b/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java index 506948ba..5f4f4463 100644 --- a/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java +++ b/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java @@ -1,194 +1,30 @@ -/* - Copyright (C) 2015-2021 AsamK and contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ package org.asamk.signal.manager; -import org.asamk.signal.manager.helper.PinHelper; -import org.asamk.signal.manager.storage.SignalAccount; -import org.asamk.signal.manager.util.KeyUtils; -import org.signal.zkgroup.profiles.ProfileKey; -import org.whispersystems.libsignal.IdentityKeyPair; -import org.whispersystems.libsignal.util.KeyHelper; -import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.KbsPinData; -import org.whispersystems.signalservice.api.KeyBackupService; -import org.whispersystems.signalservice.api.KeyBackupServicePinException; -import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException; -import org.whispersystems.signalservice.api.SignalServiceAccountManager; -import org.whispersystems.signalservice.api.push.SignalServiceAddress; -import org.whispersystems.signalservice.api.util.SleepTimer; -import org.whispersystems.signalservice.api.util.UptimeSleepTimer; -import org.whispersystems.signalservice.api.util.UuidUtil; -import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; -import org.whispersystems.signalservice.internal.push.LockedException; -import org.whispersystems.signalservice.internal.push.VerifyAccountResponse; -import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider; +import org.asamk.signal.manager.api.CaptchaRequiredException; +import org.asamk.signal.manager.api.IncorrectPinException; +import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException; +import org.asamk.signal.manager.api.PinLockMissingException; +import org.asamk.signal.manager.api.PinLockedException; +import org.asamk.signal.manager.api.RateLimitException; +import org.asamk.signal.manager.api.VerificationMethodNotAvailableException; import java.io.Closeable; -import java.io.File; import java.io.IOException; -import java.util.Locale; - -public class RegistrationManager implements Closeable { - - private SignalAccount account; - private final PathConfig pathConfig; - private final SignalServiceConfiguration serviceConfiguration; - private final String userAgent; - - private final SignalServiceAccountManager accountManager; - private final PinHelper pinHelper; - - public RegistrationManager( - SignalAccount account, - PathConfig pathConfig, - SignalServiceConfiguration serviceConfiguration, - String userAgent - ) { - this.account = account; - this.pathConfig = pathConfig; - this.serviceConfiguration = serviceConfiguration; - this.userAgent = userAgent; - - final SleepTimer timer = new UptimeSleepTimer(); - this.accountManager = new SignalServiceAccountManager(serviceConfiguration, new DynamicCredentialsProvider( - // Using empty UUID, because registering doesn't work otherwise - null, - account.getUsername(), - account.getPassword(), - account.getSignalingKey(), - SignalServiceAddress.DEFAULT_DEVICE_ID), userAgent, null, ServiceConfig.AUTOMATIC_NETWORK_RETRY, timer); - final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager); - this.pinHelper = new PinHelper(keyBackupService); - } - - public static RegistrationManager init( - String username, File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent - ) throws IOException { - PathConfig pathConfig = PathConfig.createDefault(settingsPath); - - if (!SignalAccount.userExists(pathConfig.getDataPath(), username)) { - IdentityKeyPair identityKey = KeyUtils.generateIdentityKeyPair(); - int registrationId = KeyHelper.generateRegistrationId(false); - - ProfileKey profileKey = KeyUtils.createProfileKey(); - SignalAccount account = SignalAccount.create(pathConfig.getDataPath(), - username, - identityKey, - registrationId, - profileKey); - account.save(); - - return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent); - } - - SignalAccount account = SignalAccount.load(pathConfig.getDataPath(), username); - - return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent); - } - - public void register(boolean voiceVerification, String captcha) throws IOException { - if (account.getPassword() == null) { - account.setPassword(KeyUtils.createPassword()); - } - - if (voiceVerification) { - accountManager.requestVoiceVerificationCode(Locale.getDefault(), - Optional.fromNullable(captcha), - Optional.absent()); - } else { - accountManager.requestSmsVerificationCode(false, Optional.fromNullable(captcha), Optional.absent()); - } - - account.save(); - } - - public void verifyAccount( - String verificationCode, String pin - ) throws IOException, KeyBackupSystemNoDataException, KeyBackupServicePinException { - verificationCode = verificationCode.replace("-", ""); - if (account.getSignalingKey() == null) { - account.setSignalingKey(KeyUtils.createSignalingKey()); - } - VerifyAccountResponse response; - try { - response = verifyAccountWithCode(verificationCode, pin, null); - account.setPinMasterKey(null); - } catch (LockedException e) { - if (pin == null) { - throw e; - } - - KbsPinData registrationLockData = pinHelper.getRegistrationLockData(pin, e); - if (registrationLockData == null) { - throw e; - } - - String registrationLock = registrationLockData.getMasterKey().deriveRegistrationLock(); - try { - response = verifyAccountWithCode(verificationCode, null, registrationLock); - } catch (LockedException _e) { - throw new AssertionError("KBS Pin appeared to matched but reg lock still failed!"); - } - account.setPinMasterKey(registrationLockData.getMasterKey()); - } - - // TODO response.isStorageCapable() - //accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID))); - - account.setDeviceId(SignalServiceAddress.DEFAULT_DEVICE_ID); - account.setMultiDevice(false); - account.setRegistered(true); - account.setUuid(UuidUtil.parseOrNull(response.getUuid())); - account.setRegistrationLockPin(pin); - account.getSignalProtocolStore() - .saveIdentity(account.getSelfAddress(), - account.getSignalProtocolStore().getIdentityKeyPair().getPublicKey(), - TrustLevel.TRUSTED_VERIFIED); - - try (Manager m = new Manager(account, pathConfig, serviceConfiguration, userAgent)) { - m.refreshPreKeys(); +public interface RegistrationManager extends Closeable { - m.close(false); - } + void register( + boolean voiceVerification, + String captcha, + final boolean forceRegister + ) throws IOException, CaptchaRequiredException, NonNormalizedPhoneNumberException, RateLimitException, VerificationMethodNotAvailableException; - account.save(); - } + void verifyAccount( + String verificationCode, + String pin + ) throws IOException, PinLockedException, IncorrectPinException, PinLockMissingException; - private VerifyAccountResponse verifyAccountWithCode( - final String verificationCode, final String legacyPin, final String registrationLock - ) throws IOException { - return accountManager.verifyAccountWithCode(verificationCode, - account.getSignalingKey(), - account.getSignalProtocolStore().getLocalRegistrationId(), - true, - legacyPin, - registrationLock, - account.getSelfUnidentifiedAccessKey(), - account.isUnrestrictedUnidentifiedAccess(), - ServiceConfig.capabilities, - account.isDiscoverableByPhoneNumber()); - } + void deleteLocalAccountData() throws IOException; - @Override - public void close() throws IOException { - if (account != null) { - account.close(); - account = null; - } - } + boolean isRegistered(); }