Commit c1969661 authored by Moxie Marlinspike's avatar Moxie Marlinspike
Browse files

Make fingerprint changes optionally non-blocking

Also complete the rename from "identity" to "safety numbers."

// FREEBIE
parent 89b0129f
...@@ -2,10 +2,11 @@ buildscript { ...@@ -2,10 +2,11 @@ buildscript {
repositories { repositories {
maven { maven {
url "https://repo1.maven.org/maven2" url "https://repo1.maven.org/maven2"
jcenter()
} }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:1.2.3' classpath 'com.android.tools.build:gradle:2.1.3'
classpath files('libs/gradle-witness.jar') classpath files('libs/gradle-witness.jar')
} }
} }
...@@ -156,9 +157,10 @@ dependencyVerification { ...@@ -156,9 +157,10 @@ dependencyVerification {
] ]
} }
android { android {
compileSdkVersion 22 compileSdkVersion 22
buildToolsVersion '22.0.1' buildToolsVersion '23.0.2'
dexOptions { dexOptions {
javaMaxHeapSize "4g" javaMaxHeapSize "4g"
......
#Wed Jul 22 14:31:11 PDT 2015 #Sun Aug 28 20:14:40 PDT 2016
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
No preview for this file type
res/drawable-hdpi/ic_security_white_24dp.png

428 Bytes

res/drawable-mdpi/ic_security_white_24dp.png

288 Bytes

res/drawable-xhdpi/ic_security_white_24dp.png

507 Bytes

res/drawable-xxhdpi/ic_security_white_24dp.png

702 Bytes

res/drawable-xxxhdpi/ic_security_white_24dp.png

913 Bytes

...@@ -139,7 +139,8 @@ ...@@ -139,7 +139,8 @@
</TableRow> </TableRow>
</TableLayout> </TableLayout>
<TextView android:layout_width="match_parent" <TextView android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="25dp" android:layout_marginTop="25dp"
android:textSize="17sp" android:textSize="17sp"
......
...@@ -72,12 +72,11 @@ ...@@ -72,12 +72,11 @@
<!-- ConfirmIdentityDialog --> <!-- ConfirmIdentityDialog -->
<string name="ConfirmIdentityDialog_the_signature_on_this_key_exchange_is_different">The <string name="ConfirmIdentityDialog_the_signature_on_this_key_exchange_is_different">The
identifying key material for %1$s has changed. This could either mean that someone is trying to safety numbers for %1$s have changed. This could either mean that someone is trying to
intercept your communication, or that %2$s simply re-installed Signal and now has a new intercept your communication, or that %2$s simply re-installed Signal.
identity key.
</string> </string>
<string name="ConfirmIdentityDialog_you_may_wish_to_verify_this_contact">You may wish to verify <string name="ConfirmIdentityDialog_you_may_wish_to_verify_this_contact">You may wish to verify
this contact. safety numbers for this contact.
</string> </string>
<string name="ConfirmIdentityDialog_accept">Accept</string> <string name="ConfirmIdentityDialog_accept">Accept</string>
...@@ -350,7 +349,7 @@ ...@@ -350,7 +349,7 @@
<!-- MessageDetailsRecipient --> <!-- MessageDetailsRecipient -->
<string name="MessageDetailsRecipient_failed_to_send">Failed to send</string> <string name="MessageDetailsRecipient_failed_to_send">Failed to send</string>
<string name="MessageDetailsRecipient_new_identity">New identity</string> <string name="MessageDetailsRecipient_new_safety_numbers">New safety numbers</string>
<!-- MmsDownloader --> <!-- MmsDownloader -->
<string name="MmsDownloader_error_storing_mms">Error storing MMS!</string> <string name="MmsDownloader_error_storing_mms">Error storing MMS!</string>
...@@ -530,8 +529,7 @@ ...@@ -530,8 +529,7 @@
<string name="SmsMessageRecord_received_key_exchange_message_for_invalid_protocol_version"> <string name="SmsMessageRecord_received_key_exchange_message_for_invalid_protocol_version">
Received key exchange message for invalid protocol version. Received key exchange message for invalid protocol version.
</string> </string>
<string name="SmsMessageRecord_received_message_with_unknown_identity_key_tap_to_process">Received message with unknown identity key. Tap to process and display.</string> <string name="SmsMessageRecord_received_message_with_new_safety_numbers_tap_to_process">Received message with new safety numbers. Tap to process and display.</string>
<string name="SmsMessageRecord_received_updated_but_unknown_identity_information">Received updated but unknown identity information. Tap to validate identity.</string>
<string name="SmsMessageRecord_secure_session_reset">Secure session reset.</string> <string name="SmsMessageRecord_secure_session_reset">Secure session reset.</string>
<string name="SmsMessageRecord_duplicate_message">Duplicate message.</string> <string name="SmsMessageRecord_duplicate_message">Duplicate message.</string>
...@@ -551,17 +549,6 @@ ...@@ -551,17 +549,6 @@
<string name="VerifyIdentityActivity_you_re_attempting_to_verify_security_numbers_with">You\'re attempting to verify security numbers with %1$s, but scanned %2$s instead.</string> <string name="VerifyIdentityActivity_you_re_attempting_to_verify_security_numbers_with">You\'re attempting to verify security numbers with %1$s, but scanned %2$s instead.</string>
<string name="VerifyIdentityActivity_the_scanned_qr_code_is_not_a_correctly_formatted_security_number">The scanned QR code is not a correctly formatted security number verification code. Please try scanning again.</string> <string name="VerifyIdentityActivity_the_scanned_qr_code_is_not_a_correctly_formatted_security_number">The scanned QR code is not a correctly formatted security number verification code. Please try scanning again.</string>
<!-- ViewIdentityActivity -->
<string name="ViewIdentityActivity_you_do_not_have_an_identity_key">You do not have an identity key.</string>
<string name="ViewIdentityActivity_scan_contacts_qr_code">Scan contact\'s QR code</string>
<string name="ViewIdentityActivity_display_your_qr_code">Display your QR code</string>
<string name="ViewIdentityActivity_warning_the_scanned_key_does_not_match_exclamation">WARNING, the scanned key DOES NOT match!</string>
<string name="ViewIdentityActivity_not_verified_exclamation">NOT verified!</string>
<string name="ViewIdentityActivity_the_scanned_key_matches_exclamation">The scanned key matches!</string>
<string name="ViewIdentityActivity_verified_exclamation">Verified!</string>
<string name="ViewIdentityActivity_your_identity_fingerprint">Your identity fingerprint</string>
<!-- KeyExchangeInitiator --> <!-- KeyExchangeInitiator -->
<string name="KeyExchangeInitiator_initiate_despite_existing_request_question">Initiate despite existing request?</string> <string name="KeyExchangeInitiator_initiate_despite_existing_request_question">Initiate despite existing request?</string>
<string name="KeyExchangeInitiator_send">Send</string> <string name="KeyExchangeInitiator_send">Send</string>
...@@ -825,7 +812,7 @@ ...@@ -825,7 +812,7 @@
<string name="recipient_preferences__block">Block</string> <string name="recipient_preferences__block">Block</string>
<string name="recipient_preferences__color">Color</string> <string name="recipient_preferences__color">Color</string>
<string name="recipient_preferences__color_for_this_contact">Color for this contact</string> <string name="recipient_preferences__color_for_this_contact">Color for this contact</string>
<string name="recipient_preferences__verify_identity">Verify identity</string> <string name="recipient_preferences__verify_safety_numbers">Verify safety numbers</string>
<!--- redphone_call_controls --> <!--- redphone_call_controls -->
<string name="redphone_call_card__signal_call">Signal Call</string> <string name="redphone_call_card__signal_call">Signal Call</string>
...@@ -922,7 +909,7 @@ ...@@ -922,7 +909,7 @@
<string name="recipients_panel__add_member">Add member</string> <string name="recipients_panel__add_member">Add member</string>
<!-- verify_display_fragment --> <!-- verify_display_fragment -->
<string name="verify_display_fragment__scan_the_code_on_your_contact_s_phone_or_ask_them_to_scan_your_code_to_verify_that_your_messages_are_end_to_end_encrypted_you_can_alternately_compare_the_number_above">Scan the code on your contact\'s phone, or ask them to scan your code, to verify that your messages are end-to-end encrypted. You can alternately compare the number above.</string> <string name="verify_display_fragment__scan_the_code_on_your_contact_s_phone_or_ask_them_to_scan_your_code_to_verify_that_your_messages_are_end_to_end_encrypted_you_can_alternately_compare_the_number_above">If you wish to verify the security of your end-to-end encryption with %s, compare the numbers above with the numbers on their device. Alternately, you can scan the code on their phone, or ask them to scan your code.</string>
<string name="verify_display_fragment__tap_to_scan">Tap to scan</string> <string name="verify_display_fragment__tap_to_scan">Tap to scan</string>
<!-- message_details_header --> <!-- message_details_header -->
...@@ -939,9 +926,8 @@ ...@@ -939,9 +926,8 @@
<string name="AndroidManifest__enter_passphrase">Enter passphrase</string> <string name="AndroidManifest__enter_passphrase">Enter passphrase</string>
<string name="AndroidManifest__select_contacts">Select contacts</string> <string name="AndroidManifest__select_contacts">Select contacts</string>
<string name="AndroidManifest__signal_detected">Signal detected</string> <string name="AndroidManifest__signal_detected">Signal detected</string>
<string name="AndroidManifest__public_identity_key">Public identity key</string>
<string name="AndroidManifest__change_passphrase">Change passphrase</string> <string name="AndroidManifest__change_passphrase">Change passphrase</string>
<string name="AndroidManifest__verify_identity">Verify identity</string> <string name="AndroidManifest__verify_safety_numbers">Verify safety numbers</string>
<string name="AndroidManifest__log_submit">Submit debug log</string> <string name="AndroidManifest__log_submit">Submit debug log</string>
<string name="AndroidManifest__media_preview">Media preview</string> <string name="AndroidManifest__media_preview">Media preview</string>
<string name="AndroidManifest__media_overview">All images</string> <string name="AndroidManifest__media_overview">All images</string>
...@@ -953,7 +939,6 @@ ...@@ -953,7 +939,6 @@
<!-- arrays.xml --> <!-- arrays.xml -->
<string name="arrays__import_export">Import / export</string> <string name="arrays__import_export">Import / export</string>
<string name="arrays__your_identity_key">Your identity key</string>
<string name="arrays__use_default">Use default</string> <string name="arrays__use_default">Use default</string>
<string name="arrays__use_custom">Use custom</string> <string name="arrays__use_custom">Use custom</string>
...@@ -1076,6 +1061,8 @@ ...@@ -1076,6 +1061,8 @@
<string name="preferences__support_wifi_calling">\'WiFi Calling\' compatibility mode</string> <string name="preferences__support_wifi_calling">\'WiFi Calling\' compatibility mode</string>
<string name="preferences__enable_if_your_device_supports_sms_mms_delivery_over_wifi">Enable if your device uses SMS/MMS delivery over WiFi (only enable when \'WiFi Calling\' is enabled on your device)</string> <string name="preferences__enable_if_your_device_supports_sms_mms_delivery_over_wifi">Enable if your device uses SMS/MMS delivery over WiFi (only enable when \'WiFi Calling\' is enabled on your device)</string>
<string name="preferences_app_protection__blocked_contacts">Blocked contacts</string> <string name="preferences_app_protection__blocked_contacts">Blocked contacts</string>
<string name="preferences_app_protection__safety_numbers_approval">Safety numbers approval</string>
<string name="preferences_app_protecting__require_approval_of_new_safety_numbers_when_they_change">Require approval of new safety numbers when they change</string>
<string name="preferences_notifications__display_in_notifications">Display in notifications</string> <string name="preferences_notifications__display_in_notifications">Display in notifications</string>
<string name="preferences_chats__when_using_mobile_data">When using mobile data</string> <string name="preferences_chats__when_using_mobile_data">When using mobile data</string>
<string name="preferences_chats__when_using_wifi">When using Wi-Fi</string> <string name="preferences_chats__when_using_wifi">When using Wi-Fi</string>
...@@ -1148,8 +1135,6 @@ ...@@ -1148,8 +1135,6 @@
<string name="conversation_list_fragment__fab_content_description">New conversation</string> <string name="conversation_list_fragment__fab_content_description">New conversation</string>
<!-- conversation_secure_verified --> <!-- conversation_secure_verified -->
<string name="conversation_secure_verified__menu_security">Security</string>
<string name="conversation_secure_verified__menu_verify_identity">Verify identity</string>
<string name="conversation_secure_verified__menu_reset_secure_session">Reset secure session</string> <string name="conversation_secure_verified__menu_reset_secure_session">Reset secure session</string>
<!-- conversation_muted --> <!-- conversation_muted -->
......
...@@ -28,6 +28,12 @@ ...@@ -28,6 +28,12 @@
android:title="@string/preferences__screen_security" android:title="@string/preferences__screen_security"
android:summary="@string/preferences__disable_screen_security_to_allow_screen_shots" /> android:summary="@string/preferences__disable_screen_security_to_allow_screen_shots" />
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_blocking_identity_changes"
android:title="@string/preferences_app_protection__safety_numbers_approval"
android:summary="@string/preferences_app_protecting__require_approval_of_new_safety_numbers_when_they_change"/>
<Preference android:key="preference_category_blocked" <Preference android:key="preference_category_blocked"
android:title="@string/preferences_app_protection__blocked_contacts" /> android:title="@string/preferences_app_protection__blocked_contacts" />
</PreferenceScreen> </PreferenceScreen>
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
app:numColumns="5" /> app:numColumns="5" />
<Preference android:key="pref_key_recipient_identity" <Preference android:key="pref_key_recipient_identity"
android:title="@string/recipient_preferences__verify_identity" android:title="@string/recipient_preferences__verify_safety_numbers"
android:persistent="false" android:persistent="false"
android:enabled="false"/> android:enabled="false"/>
......
...@@ -195,7 +195,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem> ...@@ -195,7 +195,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
String type = cursor.getString(cursor.getColumnIndexOrThrow(MmsSmsDatabase.TRANSPORT)); String type = cursor.getString(cursor.getColumnIndexOrThrow(MmsSmsDatabase.TRANSPORT));
MessageRecord messageRecord = getMessageRecord(id, cursor, type); MessageRecord messageRecord = getMessageRecord(id, cursor, type);
if (messageRecord.isGroupAction() || messageRecord.isCallLog() || messageRecord.isJoined() || messageRecord.isExpirationTimerUpdate()) { if (messageRecord.isGroupAction() || messageRecord.isCallLog() || messageRecord.isJoined() || messageRecord.isExpirationTimerUpdate() || messageRecord.isIdentityUpdate()) {
return MESSAGE_TYPE_UPDATE; return MESSAGE_TYPE_UPDATE;
} else if (messageRecord.isOutgoing()) { } else if (messageRecord.isOutgoing()) {
return MESSAGE_TYPE_OUTGOING; return MESSAGE_TYPE_OUTGOING;
......
...@@ -180,7 +180,8 @@ public class ConversationFragment extends Fragment ...@@ -180,7 +180,8 @@ public class ConversationFragment extends Fragment
for (MessageRecord messageRecord : messageRecords) { for (MessageRecord messageRecord : messageRecords) {
if (messageRecord.isGroupAction() || messageRecord.isCallLog() || if (messageRecord.isGroupAction() || messageRecord.isCallLog() ||
messageRecord.isJoined() || messageRecord.isExpirationTimerUpdate()) messageRecord.isJoined() || messageRecord.isExpirationTimerUpdate() ||
messageRecord.isIdentityUpdate())
{ {
actionMessage = true; actionMessage = true;
break; break;
......
...@@ -6,28 +6,39 @@ import android.graphics.Color; ...@@ -6,28 +6,39 @@ import android.graphics.Color;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.util.guava.Optional;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException;
public class ConversationUpdateItem extends LinearLayout public class ConversationUpdateItem extends LinearLayout
implements Recipients.RecipientsModifiedListener, Recipient.RecipientModifiedListener, BindableConversationItem, View.OnClickListener implements Recipients.RecipientsModifiedListener, Recipient.RecipientModifiedListener, BindableConversationItem
{ {
private static final String TAG = ConversationUpdateItem.class.getSimpleName(); private static final String TAG = ConversationUpdateItem.class.getSimpleName();
private MasterSecret masterSecret;
private Set<MessageRecord> batchSelected;
private ImageView icon; private ImageView icon;
private TextView body; private TextView body;
private TextView date; private TextView date;
...@@ -51,7 +62,7 @@ public class ConversationUpdateItem extends LinearLayout ...@@ -51,7 +62,7 @@ public class ConversationUpdateItem extends LinearLayout
this.body = (TextView)findViewById(R.id.conversation_update_body); this.body = (TextView)findViewById(R.id.conversation_update_body);
this.date = (TextView)findViewById(R.id.conversation_update_date); this.date = (TextView)findViewById(R.id.conversation_update_date);
setOnClickListener(this); this.setOnClickListener(new InternalClickListener(null));
} }
@Override @Override
...@@ -61,13 +72,10 @@ public class ConversationUpdateItem extends LinearLayout ...@@ -61,13 +72,10 @@ public class ConversationUpdateItem extends LinearLayout
@NonNull Set<MessageRecord> batchSelected, @NonNull Set<MessageRecord> batchSelected,
@NonNull Recipients conversationRecipients) @NonNull Recipients conversationRecipients)
{ {
bind(messageRecord, locale); this.masterSecret = masterSecret;
this.batchSelected = batchSelected;
if (batchSelected.contains(messageRecord)) { bind(messageRecord, locale);
setSelected(true);
} else {
setSelected(false);
}
} }
@Override @Override
...@@ -86,7 +94,11 @@ public class ConversationUpdateItem extends LinearLayout ...@@ -86,7 +94,11 @@ public class ConversationUpdateItem extends LinearLayout
else if (messageRecord.isCallLog()) setCallRecord(messageRecord); else if (messageRecord.isCallLog()) setCallRecord(messageRecord);
else if (messageRecord.isJoined()) setJoinedRecord(messageRecord); else if (messageRecord.isJoined()) setJoinedRecord(messageRecord);
else if (messageRecord.isExpirationTimerUpdate()) setTimerRecord(messageRecord); else if (messageRecord.isExpirationTimerUpdate()) setTimerRecord(messageRecord);
else if (messageRecord.isIdentityUpdate()) setIdentityRecord(messageRecord);
else throw new AssertionError("Neither group nor log nor joined."); else throw new AssertionError("Neither group nor log nor joined.");
if (batchSelected.contains(messageRecord)) setSelected(true);
else setSelected(false);
} }
private void setCallRecord(MessageRecord messageRecord) { private void setCallRecord(MessageRecord messageRecord) {
...@@ -112,6 +124,13 @@ public class ConversationUpdateItem extends LinearLayout ...@@ -112,6 +124,13 @@ public class ConversationUpdateItem extends LinearLayout
date.setVisibility(View.GONE); date.setVisibility(View.GONE);
} }
private void setIdentityRecord(final MessageRecord messageRecord) {
icon.setImageResource(R.drawable.ic_security_white_24dp);
icon.setColorFilter(new PorterDuffColorFilter(Color.parseColor("#757575"), PorterDuff.Mode.MULTIPLY));
body.setText(messageRecord.getDisplayBody());
date.setVisibility(View.GONE);
}
private void setGroupRecord(MessageRecord messageRecord) { private void setGroupRecord(MessageRecord messageRecord) {
icon.setImageResource(R.drawable.ic_group_grey600_24dp); icon.setImageResource(R.drawable.ic_group_grey600_24dp);
icon.clearColorFilter(); icon.clearColorFilter();
...@@ -145,14 +164,8 @@ public class ConversationUpdateItem extends LinearLayout ...@@ -145,14 +164,8 @@ public class ConversationUpdateItem extends LinearLayout
} }
@Override @Override
public void onClick(View v) { public void setOnClickListener(View.OnClickListener l) {
if (messageRecord.isIdentityUpdate()) { super.setOnClickListener(new InternalClickListener(l));
Intent intent = new Intent(getContext(), RecipientPreferenceActivity.class);
intent.putExtra(RecipientPreferenceActivity.RECIPIENTS_EXTRA,
new long[] {messageRecord.getIndividualRecipient().getRecipientId()});
getContext().startActivity(intent);
}
} }
@Override @Override
...@@ -161,4 +174,42 @@ public class ConversationUpdateItem extends LinearLayout ...@@ -161,4 +174,42 @@ public class ConversationUpdateItem extends LinearLayout
sender.removeListener(this); sender.removeListener(this);
} }
} }
private class InternalClickListener implements View.OnClickListener {
@Nullable private final View.OnClickListener parent;
public InternalClickListener(@Nullable View.OnClickListener parent) {
this.parent = parent;
}
@Override
public void onClick(View v) {
if (!messageRecord.isIdentityUpdate() || !batchSelected.isEmpty()) {
if (parent != null) parent.onClick(v);
return;
}
final Recipient sender = ConversationUpdateItem.this.sender;
IdentityUtil.getRemoteIdentityKey(getContext(), masterSecret, sender).addListener(new ListenableFuture.Listener<Optional<IdentityKey>>() {
@Override
public void onSuccess(Optional<IdentityKey> result) {
if (result.isPresent()) {
Intent intent = new Intent(getContext(), VerifyIdentityActivity.class);
intent.putExtra(VerifyIdentityActivity.RECIPIENT_ID, sender.getRecipientId());
intent.putExtra(VerifyIdentityActivity.RECIPIENT_IDENTITY, new IdentityKeyParcelable(result.get()));
getContext().startActivity(intent);
}
}
@Override
public void onFailure(ExecutionException e) {
Log.w(TAG, e);
}
});
}
}
} }
...@@ -44,6 +44,7 @@ import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; ...@@ -44,6 +44,7 @@ import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
import org.thoughtcrime.securesms.jobs.PushDecryptJob; import org.thoughtcrime.securesms.jobs.PushDecryptJob;
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob; import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.VersionTracker; import org.thoughtcrime.securesms.util.VersionTracker;
...@@ -68,6 +69,7 @@ public class DatabaseUpgradeActivity extends BaseActivity { ...@@ -68,6 +69,7 @@ public class DatabaseUpgradeActivity extends BaseActivity {
public static final int CONTACTS_ACCOUNT_VERSION = 136; public static final int CONTACTS_ACCOUNT_VERSION = 136;
public static final int MEDIA_DOWNLOAD_CONTROLS_VERSION = 151; public static final int MEDIA_DOWNLOAD_CONTROLS_VERSION = 151;
public static final int REDPHONE_SUPPORT_VERSION = 157; public static final int REDPHONE_SUPPORT_VERSION = 157;
public static final int FINGERPRINTS_NON_BLOCKING_VESRION = 197;
private static final SortedSet<Integer> UPGRADE_VERSIONS = new TreeSet<Integer>() {{ private static final SortedSet<Integer> UPGRADE_VERSIONS = new TreeSet<Integer>() {{
add(NO_MORE_KEY_EXCHANGE_PREFIX_VERSION); add(NO_MORE_KEY_EXCHANGE_PREFIX_VERSION);
...@@ -81,6 +83,7 @@ public class DatabaseUpgradeActivity extends BaseActivity { ...@@ -81,6 +83,7 @@ public class DatabaseUpgradeActivity extends BaseActivity {
add(MIGRATE_SESSION_PLAINTEXT); add(MIGRATE_SESSION_PLAINTEXT);
add(MEDIA_DOWNLOAD_CONTROLS_VERSION); add(MEDIA_DOWNLOAD_CONTROLS_VERSION);
add(REDPHONE_SUPPORT_VERSION); add(REDPHONE_SUPPORT_VERSION);
add(FINGERPRINTS_NON_BLOCKING_VESRION);
}}; }};
private MasterSecret masterSecret; private MasterSecret masterSecret;
...@@ -231,6 +234,10 @@ public class DatabaseUpgradeActivity extends BaseActivity { ...@@ -231,6 +234,10 @@ public class DatabaseUpgradeActivity extends BaseActivity {
.add(new DirectoryRefreshJob(getApplicationContext())); .add(new DirectoryRefreshJob(getApplicationContext()));
} }
if (params[0] < FINGERPRINTS_NON_BLOCKING_VESRION) {
TextSecurePreferences.setBlockingIdentityUpdates(getApplicationContext(), true);
}
return null; return null;
} }
......
...@@ -99,7 +99,7 @@ public class MessageRecipientListItem extends RelativeLayout ...@@ -99,7 +99,7 @@ public class MessageRecipientListItem extends RelativeLayout
resendButton.setVisibility(View.GONE); resendButton.setVisibility(View.GONE);
conflictButton.setVisibility(View.VISIBLE); conflictButton.setVisibility(View.VISIBLE);
errorText = getContext().getString(R.string.MessageDetailsRecipient_new_identity); errorText = getContext().getString(R.string.MessageDetailsRecipient_new_safety_numbers);
conflictButton.setOnClickListener(new OnClickListener() { conflictButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
......
...@@ -31,26 +31,20 @@ import org.thoughtcrime.securesms.color.MaterialColors; ...@@ -31,26 +31,20 @@ import org.thoughtcrime.securesms.color.MaterialColors;
import org.thoughtcrime.securesms.components.AvatarImageView; import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable; import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.VibrateState; import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.VibrateState;
import org.thoughtcrime.securesms.preferences.AdvancedRingtonePreference; import org.thoughtcrime.securesms.preferences.AdvancedRingtonePreference;
import org.thoughtcrime.securesms.preferences.ColorPreference; import org.thoughtcrime.securesms.preferences.ColorPreference;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.SignalProtocolAddress;
import org.whispersystems.libsignal.state.SessionRecord;
import org.whispersystems.libsignal.state.SessionStore;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
...@@ -294,7 +288,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi ...@@ -294,7 +288,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
if (recipients.isBlocked()) blockPreference.setTitle(R.string.RecipientPreferenceActivity_unblock); if (recipients.isBlocked()) blockPreference.setTitle(R.string.RecipientPreferenceActivity_unblock);
else blockPreference.setTitle(R.string.RecipientPreferenceActivity_block); else blockPreference.setTitle(R.string.RecipientPreferenceActivity_block);
getRemoteIdentityKey(getActivity(), masterSecret, recipients.getPrimaryRecipient()).addListener(new ListenableFuture.Listener<Optional<IdentityKey>>() { IdentityUtil.getRemoteIdentityKey(getActivity(), masterSecret, recipients.getPrimaryRecipient()).addListener(new ListenableFuture.Listener<Optional<IdentityKey>>() {
@Override @Override
public void onSuccess(Optional<IdentityKey> result) { public void onSuccess(Optional<IdentityKey> result) {
if (result.isPresent()) { if (result.isPresent()) {
...@@ -323,36 +317,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi ...@@ -323,36 +317,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
}); });
} }
private ListenableFuture<Optional<IdentityKey>> getRemoteIdentityKey(final Context context,
final MasterSecret masterSecret,
final Recipient recipient)
{
final SettableFuture<Optional<IdentityKey>> future = new SettableFuture<>();
new AsyncTask<Recipient, Void, Optional<IdentityKey>>() {
@Override
protected Optional<IdentityKey> doInBackground(Recipient... recipient) {
SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret);
SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(recipient[0].getNumber(), SignalServiceAddress.DEFAULT_DEVICE_ID);
SessionRecord record = sessionStore.loadSession(axolotlAddress);
if (record == null) {
return Optional.absent();
}
return Optional.fromNullable(record.getSessionState().getRemoteIdentityKey());
}
@Override
protected void onPostExecute(Optional<IdentityKey> result) {
future.set(result);
}
}.execute(recipient);
return future;
}
private class RingtoneChangeListener implements Preference.OnPreferenceChangeListener { private class RingtoneChangeListener implements Preference.OnPreferenceChangeListener {
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
......
...@@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.qr.ScanListener; ...@@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.qr.ScanListener;
import org.thoughtcrime.securesms.qr.ScanningThread; import org.thoughtcrime.securesms.qr.ScanningThread;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
...@@ -93,7 +94,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity ...@@ -93,7 +94,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
@Override @Override
protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) { protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.AndroidManifest__verify_identity); getSupportActionBar().setTitle(R.string.AndroidManifest__verify_safety_numbers);
Recipient recipient = RecipientFactory.getRecipientForId(this, getIntent().getLongExtra(RECIPIENT_ID, -1), true); Recipient recipient = RecipientFactory.getRecipientForId(this, getIntent().getLongExtra(RECIPIENT_ID, -1), true);
...@@ -146,15 +147,16 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity ...@@ -146,15 +147,16 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
.commit(); .commit();
} }
public static class VerifyDisplayFragment extends Fragment { public static class VerifyDisplayFragment extends Fragment implements Recipients.RecipientsModifiedListener {
public static final String REMOTE_NUMBER = "remote_number"; public static final String REMOTE_NUMBER = "remote_number";
public static final String REMOTE_IDENTITY = "remote_identity"; public static final String REMOTE_IDENTITY = "remote_identity";
public static final String LOCAL_IDENTITY = "local_identity"; public static final String LOCAL_IDENTITY = "local_identity";
public static final String LOCAL_NUMBER = "local_number"; public static final String LOCAL_NUMBER = "local_number";
private String localNumber; private Recipients recipient;
private String remoteNumber; private String localNumber;
private String remoteNumber;
private IdentityKey localIdentity; private IdentityKey localIdentity;
private IdentityKey remoteIdentity; private IdentityKey remoteIdentity;
...@@ -164,6 +166,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity ...@@ -164,6 +166,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
private View container; private View container;
private ImageView qrCode; private ImageView qrCode;
private ImageView qrVerified; private ImageView qrVerified;
private TextView description;
private View.OnClickListener clickListener; private View.OnClickListener clickListener;
private TextView[] codes = new TextView[12]; private TextView[] codes = new TextView[12];
...@@ -172,21 +175,22 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity ...@@ -172,21 +175,22 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) { public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) {
this.container = ViewUtil.inflate(inflater, viewGroup, R.layout.verify_display_fragment); this.container = ViewUtil.inflate(inflater, viewGroup, R.layout.verify_display_fragment);
this.qrCode = ViewUtil.findById(container, R.id.qr_code); this.qrCode = ViewUtil.findById(container, R.id.qr_code);
this.qrVerified = ViewUtil.findById(container, R.id.qr_verified); this.qrVerified = ViewUtil.findById(container, R.id.qr_verified);
this.codes[0] = ViewUtil.findById(container, R.id.code_first); this.description = ViewUtil.findById(container, R.id.description);
this.codes[1] = ViewUtil.findById(container, R.id.code_second); this.codes[0] = ViewUtil.findById(container, R.id.code_first);
this.codes[2] = ViewUtil.findById(container, R.id.code_third); this.codes[1] = ViewUtil.findById(container, R.id.code_second);
this.codes[3] = ViewUtil.findById(container, R.id.code_fourth); this.codes[2] = ViewUtil.findById(container, R.id.code_third);
this.codes[4] = ViewUtil.findById(container, R.id.code_fifth); this.codes[3] = ViewUtil.findById(container, R.id.code_fourth);
this.codes[5] = ViewUtil.findById(container, R.id.code_sixth); this.codes[4] = ViewUtil.findById(container, R.id.code_fifth);
this.codes[6] = ViewUtil.findById(container, R.id.code_seventh); this.codes[5] = ViewUtil.findById(container, R.id.code_sixth);
this.codes[7] = ViewUtil.findById(container, R.id.code_eighth); this.codes[6] = ViewUtil.findById(container, R.id.code_seventh);
this.codes[8] = ViewUtil.findById(container, R.id.code_ninth); this.codes[7] = ViewUtil.findById(container, R.id.code_eighth);
this.codes[9] = ViewUtil.findById(container, R.id.code_tenth); this.codes[8] = ViewUtil.findById(container, R.id.code_ninth);
this.codes[10] = ViewUtil.findById(container, R.id.code_eleventh); this.codes[9] = ViewUtil.findById(container, R.id.code_tenth);
this.codes[11] = ViewUtil.findById(container, R.id.code_twelth); this.codes[10] = ViewUtil.findById(container, R.id.code_eleventh);
this.codes[11] = ViewUtil.findById(container, R.id.code_twelth);
this.qrCode.setOnClickListener(clickListener); this.qrCode.setOnClickListener(clickListener);
...@@ -200,9 +204,17 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity ...@@ -200,9 +204,17 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
this.localNumber = getArguments().getString(LOCAL_NUMBER); this.localNumber = getArguments().getString(LOCAL_NUMBER);
this.localIdentity = ((IdentityKeyParcelable)getArguments().getParcelable(LOCAL_IDENTITY)).get(); this.localIdentity = ((IdentityKeyParcelable)getArguments().getParcelable(LOCAL_IDENTITY)).get();
this.remoteNumber = getArguments().getString(REMOTE_NUMBER); this.remoteNumber = getArguments().getString(REMOTE_NUMBER);
this.recipient = RecipientFactory.getRecipientsFromString(getActivity(), this.remoteNumber, true);
this.remoteIdentity = ((IdentityKeyParcelable)getArguments().getParcelable(REMOTE_IDENTITY)).get(); this.remoteIdentity = ((IdentityKeyParcelable)getArguments().getParcelable(REMOTE_IDENTITY)).get();
this.fingerprint = new NumericFingerprintGenerator(5200).createFor(localNumber, localIdentity, this.fingerprint = new NumericFingerprintGenerator(5200).createFor(localNumber, localIdentity,
remoteNumber, remoteIdentity); remoteNumber, remoteIdentity);
this.recipient.addListener(this);
}
@Override
public void onModified(Recipients recipients) {
setFingerprintViews(fingerprint);
} }
@Override @Override
...@@ -220,6 +232,12 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity ...@@ -220,6 +232,12 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
} }
} }
@Override
public void onDestroy() {
super.onDestroy();
recipient.removeListener(this);
}
public void setScannedFingerprint(String scanned) { public void setScannedFingerprint(String scanned) {
try { try {
if (fingerprint.getScannableFingerprint().compareTo(scanned.getBytes("ISO-8859-1"))) { if (fingerprint.getScannableFingerprint().compareTo(scanned.getBytes("ISO-8859-1"))) {
...@@ -258,6 +276,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity ...@@ -258,6 +276,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
Bitmap qrCodeBitmap = QrCode.create(qrCodeString); Bitmap qrCodeBitmap = QrCode.create(qrCodeString);
qrCode.setImageBitmap(qrCodeBitmap); qrCode.setImageBitmap(qrCodeBitmap);
description.setText(getActivity().getString(R.string.verify_display_fragment__scan_the_code_on_your_contact_s_phone_or_ask_them_to_scan_your_code_to_verify_that_your_messages_are_end_to_end_encrypted_you_can_alternately_compare_the_number_above, recipient.toShortString()));
} }
private Bitmap createVerifiedBitmap(int width, int height, @DrawableRes int id) { private Bitmap createVerifiedBitmap(int width, int height, @DrawableRes int id) {
......
...@@ -2,8 +2,10 @@ package org.thoughtcrime.securesms.crypto.storage; ...@@ -2,8 +2,10 @@ package org.thoughtcrime.securesms.crypto.storage;
import android.content.Context; import android.content.Context;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.jobs.IdentityUpdateJob;
import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKey;
...@@ -36,8 +38,22 @@ public class TextSecureIdentityKeyStore implements IdentityKeyStore { ...@@ -36,8 +38,22 @@ public class TextSecureIdentityKeyStore implements IdentityKeyStore {
@Override @Override
public boolean isTrustedIdentity(String name, IdentityKey identityKey) { public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
long recipientId = RecipientFactory.getRecipientsFromString(context, name, true).getPrimaryRecipient().getRecipientId(); long recipientId = RecipientFactory.getRecipientsFromString(context, name, true).getPrimaryRecipient().getRecipientId();
return DatabaseFactory.getIdentityDatabase(context) boolean trusted = DatabaseFactory.getIdentityDatabase(context)
.isValidIdentity(recipientId, identityKey); .isValidIdentity(recipientId, identityKey);
if (trusted) {
return true;
} else if (!TextSecurePreferences.isBlockingIdentityUpdates(context)) {
saveIdentity(name, identityKey);
ApplicationContext.getInstance(context)
.getJobManager()
.add(new IdentityUpdateJob(context, recipientId));
return true;
} else {
return false;
}
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment