Add basic support for receiving messages at your PNI.

We haven't implemented merging yet, so this is still very basic, but it
"works".
This commit is contained in:
Greyson Parrelli
2022-04-13 16:22:22 -04:00
parent 41e417ff0b
commit 35a9fddbb2
14 changed files with 136 additions and 23 deletions

View File

@@ -424,6 +424,14 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
}
)
clickPref(
title = DSLSettingsText.from(R.string.preferences__internal_clear_all_profile_keys),
summary = DSLSettingsText.from(R.string.preferences__internal_clear_all_profile_keys_description),
onClick = {
clearAllProfileKeys()
}
)
dividerPref()
sectionHeaderPref(R.string.ConversationListTabs__stories)
@@ -548,6 +556,7 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
private fun clearAllServiceIds() {
MaterialAlertDialogBuilder(requireContext())
.setTitle("Clear all serviceIds?")
.setMessage("Are you sure? Never do this on a non-test device.")
.setPositiveButton(android.R.string.ok) { _, _ ->
SignalDatabase.recipients.debugClearServiceIds()
@@ -558,4 +567,18 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
}
.show()
}
private fun clearAllProfileKeys() {
MaterialAlertDialogBuilder(requireContext())
.setTitle("Clear all profile keys?")
.setMessage("Are you sure? Never do this on a non-test device.")
.setPositiveButton(android.R.string.ok) { _, _ ->
SignalDatabase.recipients.debugClearServiceIds()
Toast.makeText(context, "Cleared all profile keys.", Toast.LENGTH_SHORT).show()
}
.setNegativeButton(android.R.string.cancel) { d, _ ->
d.dismiss()
}
.show()
}
}

View File

@@ -60,12 +60,27 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
)
if (!recipient.isGroup) {
val serviceId = recipient.serviceId.map(ServiceId::toString).orElse("null")
longClickPref(
title = DSLSettingsText.from("ServiceId"),
summary = DSLSettingsText.from(serviceId),
onLongClick = { copyToClipboard(serviceId) }
)
if (recipient.isSelf) {
val aci: String = SignalStore.account().aci?.toString() ?: "null"
longClickPref(
title = DSLSettingsText.from("ACI"),
summary = DSLSettingsText.from(aci),
onLongClick = { copyToClipboard(aci) }
)
val pni: String = SignalStore.account().pni?.toString() ?: "null"
longClickPref(
title = DSLSettingsText.from("PNI"),
summary = DSLSettingsText.from(pni),
onLongClick = { copyToClipboard(pni) }
)
} else {
val serviceId: String = recipient.serviceId.map(ServiceId::toString).orElse("null")
longClickPref(
title = DSLSettingsText.from("ServiceId"),
summary = DSLSettingsText.from(serviceId),
onLongClick = { copyToClipboard(serviceId) }
)
}
}
if (state.groupId != null) {

View File

@@ -29,7 +29,7 @@ public final class SignalServiceDataStoreImpl implements SignalServiceDataStore
if (accountIdentifier.equals(SignalStore.account().getAci())) {
return aciStore;
} else if (accountIdentifier.equals(SignalStore.account().getPni())) {
throw new AssertionError("Not to be used yet!");
return pniStore;
} else {
throw new IllegalArgumentException("No matching store found for " + accountIdentifier);
}

View File

@@ -93,7 +93,8 @@ public class PushDatabase extends Database {
Util.isEmpty(content) ? null : Base64.decode(content),
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_RECEIVED_TIMESTAMP)),
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_DELIVERED_TIMESTAMP)),
cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID)));
cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID)),
"");
}
} catch (IOException e) {
Log.w(TAG, e);
@@ -178,7 +179,8 @@ public class PushDatabase extends Database {
content != null ? Base64.decode(content) : null,
serverReceivedTimestamp,
serverDeliveredTimestamp,
serverGuid);
serverGuid,
"");
} catch (IOException e) {
throw new AssertionError(e);
}

View File

@@ -2932,6 +2932,21 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
SERVICE_ID to null,
PNI_COLUMN to null
)
.where("$ID != ?", Recipient.self().id)
.run()
}
/**
* Should only be used for debugging! A very destructive action that clears all known profile keys and credentials.
*/
fun debugClearProfileKeys() {
writableDatabase
.update(TABLE_NAME)
.values(
PROFILE_KEY to null,
PROFILE_KEY_CREDENTIAL to null
)
.where("$ID != ?", Recipient.self().id)
.run()
}

View File

@@ -50,6 +50,7 @@ import org.whispersystems.signalservice.api.crypto.ContentHint;
import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException;
@@ -76,8 +77,26 @@ public final class MessageDecryptionUtil {
* caller.
*/
public static @NonNull DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) {
SignalServiceAccountDataStore protocolStore = ApplicationDependencies.getProtocolStore().aci();
SignalServiceAddress localAddress = new SignalServiceAddress(SignalStore.account().requireAci(), Recipient.self().requireE164());
ServiceId aci = SignalStore.account().requireAci();
ServiceId pni = SignalStore.account().requirePni();
ServiceId destination;
if (!FeatureFlags.usePnpCds()) {
destination = aci;
} else if (envelope.hasDestinationUuid()) {
destination = ServiceId.parseOrThrow(envelope.getDestinationUuid());
} else {
Log.w(TAG, "No destinationUuid set! Defaulting to ACI.");
destination = aci;
}
if (!destination.equals(aci) && !destination.equals(pni)) {
Log.w(TAG, "Destination of " + destination + " does not match our ACI (" + aci + ") or PNI (" + pni + ")! Defaulting to ACI.");
destination = aci;
}
SignalServiceAccountDataStore protocolStore = ApplicationDependencies.getProtocolStore().get(destination);
SignalServiceAddress localAddress = new SignalServiceAddress(SignalStore.account().requireAci(), SignalStore.account().getE164());
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), protocolStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
List<Job> jobs = new LinkedList<>();