Skip to content

Commit

Permalink
Update registration to allow PIN entry.
Browse files Browse the repository at this point in the history
  • Loading branch information
greyson-signal committed Apr 21, 2020
1 parent 6b37675 commit acbfff8
Show file tree
Hide file tree
Showing 46 changed files with 1,206 additions and 161 deletions.
7 changes: 6 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,12 @@
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />

<service android:enabled="true" android:name="org.thoughtcrime.securesms.service.WebRtcCallService"/>
<activity android:name=".pin.PinRestoreActivity"
android:theme="@style/TextSecure.LightNoActionBar"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />


<service android:enabled="true" android:name="org.thoughtcrime.securesms.service.WebRtcCallService"/>
<service android:enabled="true" android:name=".service.ApplicationMigrationService"/>
<service android:enabled="true" android:exported="false" android:name=".service.KeyCachingService"/>
<service android:enabled="true" android:name=".service.IncomingMessageObserver$ForegroundService"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.migrations.ApplicationMigrationActivity;
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
import org.thoughtcrime.securesms.pin.PinRestoreActivity;
import org.thoughtcrime.securesms.profiles.ProfileName;
import org.thoughtcrime.securesms.profiles.edit.EditProfileActivity;
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
Expand All @@ -32,15 +33,17 @@
public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarActivity implements MasterSecretListener {
private static final String TAG = PassphraseRequiredActionBarActivity.class.getSimpleName();

public static final String LOCALE_EXTRA = "locale_extra";
public static final String LOCALE_EXTRA = "locale_extra";
public static final String NEXT_INTENT_EXTRA = "next_intent";

private static final int STATE_NORMAL = 0;
private static final int STATE_CREATE_PASSPHRASE = 1;
private static final int STATE_PROMPT_PASSPHRASE = 2;
private static final int STATE_UI_BLOCKING_UPGRADE = 3;
private static final int STATE_WELCOME_PUSH_SCREEN = 4;
private static final int STATE_CREATE_PROFILE_NAME = 5;
private static final int STATE_CREATE_KBS_PIN = 6;
private static final int STATE_ENTER_SIGNAL_PIN = 5;
private static final int STATE_CREATE_PROFILE_NAME = 6;
private static final int STATE_CREATE_SIGNAL_PIN = 7;

private SignalServiceNetworkAccess networkAccess;
private BroadcastReceiver clearKeyReceiver;
Expand Down Expand Up @@ -155,7 +158,8 @@ private Intent getIntentForState(int state) {
case STATE_PROMPT_PASSPHRASE: return getPromptPassphraseIntent();
case STATE_UI_BLOCKING_UPGRADE: return getUiBlockingUpgradeIntent();
case STATE_WELCOME_PUSH_SCREEN: return getPushRegistrationIntent();
case STATE_CREATE_KBS_PIN: return getCreateKbsPinIntent();
case STATE_ENTER_SIGNAL_PIN: return getEnterSignalPinIntent();
case STATE_CREATE_SIGNAL_PIN: return getCreateSignalPinIntent();
case STATE_CREATE_PROFILE_NAME: return getCreateProfileNameIntent();
default: return null;
}
Expand All @@ -170,21 +174,23 @@ private int getApplicationState(boolean locked) {
return STATE_UI_BLOCKING_UPGRADE;
} else if (!TextSecurePreferences.hasPromptedPushRegistration(this)) {
return STATE_WELCOME_PUSH_SCREEN;
} else if (SignalStore.storageServiceValues().needsAccountRestore()) {
return STATE_ENTER_SIGNAL_PIN;
} else if (userMustSetProfileName()) {
return STATE_CREATE_PROFILE_NAME;
} else if (userMustSetKbsPin()) {
return STATE_CREATE_KBS_PIN;
} else if (userMustCreateSignalPin()) {
return STATE_CREATE_SIGNAL_PIN;
} else {
return STATE_NORMAL;
}
}

private boolean userMustSetKbsPin() {
private boolean userMustCreateSignalPin() {
return !SignalStore.registrationValues().isRegistrationComplete() && !SignalStore.kbsValues().hasPin();
}

private boolean userMustSetProfileName() {
return !SignalStore.registrationValues().isRegistrationComplete() && Recipient.self().getProfileName() == ProfileName.EMPTY;
return !SignalStore.registrationValues().isRegistrationComplete() && Recipient.self().getProfileName().isEmpty();
}

private Intent getCreatePassphraseIntent() {
Expand All @@ -206,7 +212,11 @@ private Intent getPushRegistrationIntent() {
return RegistrationNavigationActivity.newIntentForNewRegistration(this);
}

private Intent getCreateKbsPinIntent() {
private Intent getEnterSignalPinIntent() {
return getRoutedIntent(PinRestoreActivity.class, getIntent());
}

private Intent getCreateSignalPinIntent() {

final Intent intent;
if (userMustSetProfileName()) {
Expand Down Expand Up @@ -252,4 +262,12 @@ private void removeClearKeyReceiver(Context context) {
clearKeyReceiver = null;
}
}

/**
* Puts an extra in {@code intent} so that {@code nextIntent} will be shown after it.
*/
public static @NonNull Intent chainIntent(@NonNull Intent intent, @NonNull Intent nextIntent) {
intent.putExtra(NEXT_INTENT_EXTRA, nextIntent);
return intent;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.IntentUtils;
import org.thoughtcrime.securesms.util.text.AfterTextChanged;

Expand Down Expand Up @@ -148,19 +149,10 @@ private void submitFormWithDebugLog(@Nullable String debugLog) {
.map(view -> Feeling.getByViewId(view.getId()))
.findFirst().orElse(null);

Spanned body = getEmailBody(debugLog, feeling);

Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{getString(R.string.RegistrationActivity_support_email)});
intent.putExtra(Intent.EXTRA_SUBJECT, getEmailSubject());
intent.putExtra(Intent.EXTRA_TEXT, body.toString());

if (IntentUtils.isResolvable(requireContext(), intent)) {
startActivity(intent);
} else {
Toast.makeText(requireContext(), R.string.HelpFragment__no_email_app_found, Toast.LENGTH_LONG).show();
}
CommunicationActions.openEmail(requireContext(),
getString(R.string.RegistrationActivity_support_email),
getEmailSubject(),
getEmailBody(debugLog, feeling).toString());
}

private String getEmailSubject() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ private RefreshAttributesJob(@NonNull Job.Parameters parameters) {

@Override
public void onRun() throws IOException {
if (!TextSecurePreferences.isPushRegistered(context)) {
Log.w(TAG, "Not yet registered. Skipping.");
return;
}

int registrationId = TextSecurePreferences.getLocalRegistrationId(context);
boolean fetchesMessages = TextSecurePreferences.isFcmDisabled(context);
byte[] unidentifiedAccessKey = UnidentifiedAccess.deriveAccessKeyFrom(ProfileKeyUtil.getSelfProfileKey());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;

import java.util.Map;
import java.util.concurrent.TimeUnit;

public class RemoteConfigRefreshJob extends BaseJob {

private static final String TAG = Log.tag(RemoteConfigRefreshJob.class);

public static final String KEY = "RemoteConfigRefreshJob";

public RemoteConfigRefreshJob() {
Expand Down Expand Up @@ -41,6 +45,11 @@ private RemoteConfigRefreshJob(@NonNull Parameters parameters) {

@Override
protected void onRun() throws Exception {
if (!TextSecurePreferences.isPushRegistered(context)) {
Log.w(TAG, "Not registered. Skipping.");
return;
}

Map<String, Boolean> config = ApplicationDependencies.getSignalServiceAccountManager().getRemoteConfig();
FeatureFlags.update(config);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ public void onAdded() {}

@Override
public void onRun() throws IOException {
if (!TextSecurePreferences.isPushRegistered(context)) {
Log.w(TAG, "Not yet registered. Ignoring.");
return;
}

synchronized (RotateCertificateJob.class) {
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
byte[] certificate = accountManager.getSenderCertificate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log;
Expand Down Expand Up @@ -33,7 +34,7 @@ public class StorageAccountRestoreJob extends BaseJob {

public static String KEY = "StorageAccountRestoreJob";

public static long LIFESPAN = TimeUnit.SECONDS.toMillis(10);
public static long LIFESPAN = TimeUnit.SECONDS.toMillis(20);

private static final String TAG = Log.tag(StorageAccountRestoreJob.class);

Expand Down Expand Up @@ -69,7 +70,8 @@ protected void onRun() throws Exception {
Optional<SignalStorageManifest> manifest = accountManager.getStorageManifest(storageServiceKey);

if (!manifest.isPresent()) {
Log.w(TAG, "Manifest did not exist or was undecryptable (bad key). Not restoring.");
Log.w(TAG, "Manifest did not exist or was undecryptable (bad key). Not restoring. Force-pushing.");
ApplicationDependencies.getJobManager().add(new StorageForcePushJob());
return;
}

Expand Down Expand Up @@ -97,16 +99,13 @@ protected void onRun() throws Exception {
StorageId selfStorageId = StorageId.forAccount(Recipient.self().getStorageServiceId());
StorageSyncHelper.applyAccountStorageSyncUpdates(context, selfStorageId, accountRecord);

JobManager jobManager = ApplicationDependencies.getJobManager();

if (accountRecord.getAvatarUrlPath().isPresent()) {
RetrieveProfileAvatarJob avatarJob = new RetrieveProfileAvatarJob(Recipient.self(), accountRecord.getAvatarUrlPath().get());
try {
avatarJob.setContext(context);
avatarJob.onRun();
} catch (IOException e) {
Log.w(TAG, "Failed to download avatar. Scheduling for later.");
ApplicationDependencies.getJobManager().add(avatarJob);
}
jobManager.runSynchronously(new RetrieveProfileAvatarJob(Recipient.self(), accountRecord.getAvatarUrlPath().get()), LIFESPAN/2);
}

jobManager.runSynchronously(new RefreshAttributesJob(), LIFESPAN/2);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.annimon.stream.Stream;

import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
import org.thoughtcrime.securesms.storage.StorageSyncModels;
Expand All @@ -18,6 +17,7 @@
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.storage.StorageSyncValidations;
import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.InvalidKeyException;
Expand Down Expand Up @@ -78,20 +78,26 @@ protected void onRun() throws IOException, RetryLaterException {
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
StorageKeyDatabase storageKeyDatabase = DatabaseFactory.getStorageKeyDatabase(context);

long currentVersion = accountManager.getStorageManifestVersion();
Map<RecipientId, StorageId> oldStorageKeys = recipientDatabase.getContactStorageSyncIdsMap();
long currentVersion = accountManager.getStorageManifestVersion();
Map<RecipientId, StorageId> oldContactStorageIds = recipientDatabase.getContactStorageSyncIdsMap();

long newVersion = currentVersion + 1;
Map<RecipientId, StorageId> newStorageKeys = generateNewKeys(oldStorageKeys);
Set<RecipientId> archivedRecipients = DatabaseFactory.getThreadDatabase(context).getArchivedRecipients();
List<SignalStorageRecord> inserts = Stream.of(oldStorageKeys.keySet())
.map(recipientDatabase::getRecipientSettings)
.withoutNulls()
.map(s -> StorageSyncModels.localToRemoteRecord(s, Objects.requireNonNull(newStorageKeys.get(s.getId())).getRaw(), archivedRecipients))
.toList();
inserts.add(StorageSyncHelper.buildAccountRecord(context, StorageId.forAccount(Recipient.self().fresh().getStorageServiceId())));
long newVersion = currentVersion + 1;
Map<RecipientId, StorageId> newContactStorageIds = generateContactStorageIds(oldContactStorageIds);
Set<RecipientId> archivedRecipients = DatabaseFactory.getThreadDatabase(context).getArchivedRecipients();
List<SignalStorageRecord> inserts = Stream.of(oldContactStorageIds.keySet())
.map(recipientDatabase::getRecipientSettings)
.withoutNulls()
.map(s -> StorageSyncModels.localToRemoteRecord(s, Objects.requireNonNull(newContactStorageIds.get(s.getId())).getRaw(), archivedRecipients))
.toList();

SignalStorageManifest manifest = new SignalStorageManifest(newVersion, new ArrayList<>(newStorageKeys.values()));
SignalStorageRecord accountRecord = StorageSyncHelper.buildAccountRecord(context, StorageId.forAccount(Recipient.self().fresh().getStorageServiceId()));
List<StorageId> allNewStorageIds = new ArrayList<>(newContactStorageIds.values());

inserts.add(accountRecord);
allNewStorageIds.add(accountRecord.getId());

SignalStorageManifest manifest = new SignalStorageManifest(newVersion, allNewStorageIds);
StorageSyncValidations.validateForcePush(manifest, inserts);

try {
if (newVersion > 1) {
Expand All @@ -114,7 +120,8 @@ protected void onRun() throws IOException, RetryLaterException {

Log.i(TAG, "Force push succeeded. Updating local manifest version to: " + newVersion);
TextSecurePreferences.setStorageManifestVersion(context, newVersion);
recipientDatabase.applyStorageIdUpdates(newStorageKeys);
recipientDatabase.applyStorageIdUpdates(newContactStorageIds);
recipientDatabase.applyStorageIdUpdates(Collections.singletonMap(Recipient.self().getId(), accountRecord.getId()));
storageKeyDatabase.deleteAll();
}

Expand All @@ -127,7 +134,7 @@ protected boolean onShouldRetry(@NonNull Exception e) {
public void onFailure() {
}

private static @NonNull Map<RecipientId, StorageId> generateNewKeys(@NonNull Map<RecipientId, StorageId> oldKeys) {
private static @NonNull Map<RecipientId, StorageId> generateContactStorageIds(@NonNull Map<RecipientId, StorageId> oldKeys) {
Map<RecipientId, StorageId> out = new HashMap<>();

for (Map.Entry<RecipientId, StorageId> entry : oldKeys.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public final class KbsValues {

/**
* Deliberately does not clear the {@link #MASTER_KEY}.
*
* Should only be called by {@link org.thoughtcrime.securesms.pin.PinState}
*/
public void clearRegistrationLockAndPin() {
store.beginWrite()
Expand All @@ -37,6 +39,7 @@ public void clearRegistrationLockAndPin() {
.commit();
}

/** Should only be set by {@link org.thoughtcrime.securesms.pin.PinState}. */
public synchronized void setKbsMasterKey(@NonNull KbsPinData pinData, @NonNull String localPinHash) {
MasterKey masterKey = pinData.getMasterKey();
String tokenResponse;
Expand All @@ -53,6 +56,7 @@ public synchronized void setKbsMasterKey(@NonNull KbsPinData pinData, @NonNull S
.commit();
}

/** Should only be set by {@link org.thoughtcrime.securesms.pin.PinState}. */
public synchronized void setV2RegistrationLockEnabled(boolean enabled) {
store.beginWrite().putBoolean(V2_LOCK_ENABLED, enabled).apply();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public void setKeyboardType(@NonNull PinKeyboardType keyboardType) {
return PinKeyboardType.fromCode(store.getString(KEYBOARD_TYPE, null));
}

/** Should only be set by {@link org.thoughtcrime.securesms.pin.PinState} */
public void setPinState(@NonNull String pinState) {
store.beginWrite().putString(PIN_STATE, pinState).commit();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

public class StorageServiceValues {

private static final String LAST_SYNC_TIME = "storage.last_sync_time";
private static final String LAST_SYNC_TIME = "storage.last_sync_time";
private static final String NEEDS_ACCOUNT_RESTORE = "storage.needs_account_restore";

private final KeyValueStore store;

Expand All @@ -29,4 +30,12 @@ public long getLastSyncTime() {
public void onSyncCompleted() {
store.beginWrite().putLong(LAST_SYNC_TIME, System.currentTimeMillis()).apply();
}

public boolean needsAccountRestore() {
return store.getBoolean(NEEDS_ACCOUNT_RESTORE, false);
}

public void setNeedsAccountRestore(boolean value) {
store.beginWrite().putBoolean(NEEDS_ACCOUNT_RESTORE, value).apply();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ protected void onPreExecute() {
protected Boolean doInBackground(Void... voids) {
try {
Log.i(TAG, "Setting pin on KBS - dialog");
PinState.onCompleteRegistrationLockV1Reminder(context, pinValue);
PinState.onEnableLegacyRegistrationLockPreference(context, pinValue);
Log.i(TAG, "Pin set on KBS");
return true;
} catch (IOException | UnauthenticatedResponseException e) {
Expand Down Expand Up @@ -235,7 +235,7 @@ protected void onPreExecute() {
@Override
protected Boolean doInBackground(Void... voids) {
try {
PinState.onDisableRegistrationLockV1(context);
PinState.onDisableLegacyRegistrationLockPreference(context);
return true;
} catch (IOException | UnauthenticatedResponseException e) {
Log.w(TAG, e);
Expand Down

0 comments on commit acbfff8

Please sign in to comment.