Use strongly-typed ACIs and PNIs everywhere.

This commit is contained in:
Greyson Parrelli
2023-07-28 12:58:04 -04:00
parent 7ff4a82755
commit 82906aee58
146 changed files with 1416 additions and 1194 deletions

View File

@@ -42,7 +42,7 @@ object CallMessageProcessor {
handleCallHangupMessage(envelope, metadata, hangup, senderRecipient.id, callMessage.hasLegacyHangup())
}
callMessage.hasBusy() -> handleCallBusyMessage(envelope, metadata, callMessage.busy, senderRecipient.id)
callMessage.hasOpaque() -> handleCallOpaqueMessage(envelope, metadata, callMessage.opaque, senderRecipient.requireServiceId(), serverDeliveredTimestamp)
callMessage.hasOpaque() -> handleCallOpaqueMessage(envelope, metadata, callMessage.opaque, senderRecipient.requireAci(), serverDeliveredTimestamp)
}
}
@@ -146,7 +146,7 @@ object CallMessageProcessor {
ApplicationDependencies.getSignalCallManager()
.receivedOpaqueMessage(
OpaqueMessageMetadata(
senderServiceId.uuid(),
senderServiceId.rawUuid,
opaque.data.toByteArray(),
metadata.sourceDeviceId,
messageAgeSeconds

View File

@@ -95,6 +95,7 @@ import org.thoughtcrime.securesms.util.isStory
import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata
import org.whispersystems.signalservice.api.payments.Money
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.api.util.OptionalUtil.asOptional
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.BodyRange
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Content
@@ -992,10 +993,10 @@ object DataMessageProcessor {
return mentionBodyRanges
.filter { it.hasMentionAci() }
.mapNotNull {
val serviceId = ServiceId.parseOrNull(it.mentionAci)
val aci = ACI.parseOrNull(it.mentionAci)
if (serviceId != null && !serviceId.isUnknown) {
val id = Recipient.externalPush(serviceId).id
if (aci != null && !aci.isUnknown) {
val id = Recipient.externalPush(aci).id
Mention(id, it.start, it.length)
} else {
null

View File

@@ -537,7 +537,7 @@ public class MessageContentProcessor {
Optional<GroupRecord> groupRecord = groupDatabase.getGroup(groupId);
if (groupRecord.isPresent() && !groupRecord.get().getMembers().contains(senderRecipient.getId())) {
log(String.valueOf(content.getTimestamp()), "Ignoring GV2 message from member not in group " + groupId + ". Sender: " + senderRecipient.getId() + " | " + senderRecipient.requireServiceId());
log(String.valueOf(content.getTimestamp()), "Ignoring GV2 message from member not in group " + groupId + ". Sender: " + senderRecipient.getId() + " | " + senderRecipient.requireAci());
return true;
}
@@ -739,7 +739,7 @@ public class MessageContentProcessor {
}
ApplicationDependencies.getSignalCallManager()
.receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireServiceId().uuid(),
.receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireAci().getRawUuid(),
message.getOpaque(),
content.getSenderDevice(),
messageAgeSeconds));
@@ -843,7 +843,7 @@ public class MessageContentProcessor {
log(content.getTimestamp(), "Unknown group message.");
warn(content.getTimestamp(), "Received a GV2 message for a group we have no knowledge of -- attempting to fix this state.");
ServiceId authServiceId = ServiceId.parseOrNull(content.getDestinationUuid());
ServiceId authServiceId = ServiceId.parseOrNull(content.getDestinationServiceId());
if (authServiceId == null) {
warn(content.getTimestamp(), "Group message missing destination uuid, defaulting to ACI");
authServiceId = SignalStore.account().requireAci();
@@ -1290,7 +1290,7 @@ public class MessageContentProcessor {
return;
}
ServiceId serviceId = ServiceId.fromByteString(callEvent.getConversationId());
ServiceId serviceId = ServiceId.parseOrThrow(callEvent.getConversationId());
RecipientId recipientId = RecipientId.from(serviceId);
log(envelopeTimestamp, "Synchronize call event call: " + callId);
@@ -3061,7 +3061,7 @@ public class MessageContentProcessor {
ratchetKeyMatches(requester, content.getSenderDevice(), decryptionErrorMessage.getRatchetKey().get()))
{
warn(content.getTimestamp(), "[RetryReceipt-I] Ratchet key matches. Archiving the session.");
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(requester.getId(), content.getSenderDevice());
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(requester.requireServiceId(), content.getSenderDevice());
archivedSession = true;
}

View File

@@ -569,7 +569,7 @@ open class MessageContentProcessorV2(private val context: Context) {
ratchetKeyMatches(requester, metadata.sourceDeviceId, decryptionErrorMessage.ratchetKey.get())
) {
warn(envelope.timestamp, "[RetryReceipt-I] Ratchet key matches. Archiving the session.")
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(requester.id, metadata.sourceDeviceId)
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(requester.requireServiceId(), metadata.sourceDeviceId)
archivedSession = true
}
@@ -604,7 +604,7 @@ open class MessageContentProcessorV2(private val context: Context) {
}
private fun ratchetKeyMatches(recipient: Recipient, deviceId: Int, ratchetKey: ECPublicKey): Boolean {
val address = recipient.resolve().requireServiceId().toProtocolAddress(deviceId)
val address = recipient.resolve().requireAci().toProtocolAddress(deviceId)
val session = ApplicationDependencies.getProtocolStore().aci().loadSession(address)
return session.currentRatchetKeyMatches(ratchetKey)
}

View File

@@ -55,8 +55,9 @@ import org.whispersystems.signalservice.api.crypto.SignalGroupSessionBuilder
import org.whispersystems.signalservice.api.crypto.SignalServiceCipher
import org.whispersystems.signalservice.api.crypto.SignalServiceCipherResult
import org.whispersystems.signalservice.api.messages.EnvelopeContentValidator
import org.whispersystems.signalservice.api.push.PNI
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.api.push.ServiceId.PNI
import org.whispersystems.signalservice.api.push.SignalServiceAddress
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Content
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Envelope
@@ -158,13 +159,17 @@ object MessageDecryptor {
}
if (FeatureFlags.phoneNumberPrivacy() && cipherResult.content.hasPniSignatureMessage()) {
handlePniSignatureMessage(
envelope,
cipherResult.metadata.sourceServiceId,
cipherResult.metadata.sourceE164,
cipherResult.metadata.sourceDeviceId,
cipherResult.content.pniSignatureMessage
)
if (cipherResult.metadata.sourceServiceId is ACI) {
handlePniSignatureMessage(
envelope,
cipherResult.metadata.sourceServiceId as ACI,
cipherResult.metadata.sourceE164,
cipherResult.metadata.sourceDeviceId,
cipherResult.content.pniSignatureMessage
)
} else {
Log.w(TAG, "${logPrefix(envelope)} Ignoring PNI signature because the sourceServiceId isn't an ACI!")
}
} else if (cipherResult.content.hasPniSignatureMessage()) {
Log.w(TAG, "${logPrefix(envelope)} Ignoring PNI signature because the feature flag is disabled!")
}
@@ -295,37 +300,37 @@ object MessageDecryptor {
SignalGroupSessionBuilder(ReentrantSessionLock.INSTANCE, GroupSessionBuilder(senderKeyStore)).process(sender, message)
}
private fun handlePniSignatureMessage(envelope: Envelope, serviceId: ServiceId, e164: String?, deviceId: Int, pniSignatureMessage: PniSignatureMessage) {
Log.i(TAG, "${logPrefix(envelope, serviceId)} Processing PniSignatureMessage")
private fun handlePniSignatureMessage(envelope: Envelope, aci: ACI, e164: String?, deviceId: Int, pniSignatureMessage: PniSignatureMessage) {
Log.i(TAG, "${logPrefix(envelope, aci)} Processing PniSignatureMessage")
val pni: PNI = PNI.parseOrThrow(pniSignatureMessage.pni.toByteArray())
if (SignalDatabase.recipients.isAssociated(serviceId, pni)) {
Log.i(TAG, "${logPrefix(envelope, serviceId)}[handlePniSignatureMessage] ACI ($serviceId) and PNI ($pni) are already associated.")
if (SignalDatabase.recipients.isAssociated(aci, pni)) {
Log.i(TAG, "${logPrefix(envelope, aci)}[handlePniSignatureMessage] ACI ($aci) and PNI ($pni) are already associated.")
return
}
val identityStore = ApplicationDependencies.getProtocolStore().aci().identities()
val aciAddress = SignalProtocolAddress(serviceId.toString(), deviceId)
val aciAddress = SignalProtocolAddress(aci.toString(), deviceId)
val pniAddress = SignalProtocolAddress(pni.toString(), deviceId)
val aciIdentity = identityStore.getIdentity(aciAddress)
val pniIdentity = identityStore.getIdentity(pniAddress)
if (aciIdentity == null) {
Log.w(TAG, "${logPrefix(envelope, serviceId)}[validatePniSignature] No identity found for ACI address $aciAddress")
Log.w(TAG, "${logPrefix(envelope, aci)}[validatePniSignature] No identity found for ACI address $aciAddress")
return
}
if (pniIdentity == null) {
Log.w(TAG, "${logPrefix(envelope, serviceId)}[validatePniSignature] No identity found for PNI address $pniAddress")
Log.w(TAG, "${logPrefix(envelope, aci)}[validatePniSignature] No identity found for PNI address $pniAddress")
return
}
if (pniIdentity.verifyAlternateIdentity(aciIdentity, pniSignatureMessage.signature.toByteArray())) {
Log.i(TAG, "${logPrefix(envelope, serviceId)}[validatePniSignature] PNI signature is valid. Associating ACI ($serviceId) with PNI ($pni)")
SignalDatabase.recipients.getAndPossiblyMergePnpVerified(serviceId, pni, e164)
Log.i(TAG, "${logPrefix(envelope, aci)}[validatePniSignature] PNI signature is valid. Associating ACI ($aci) with PNI ($pni)")
SignalDatabase.recipients.getAndPossiblyMergePnpVerified(aci, pni, e164)
} else {
Log.w(TAG, "${logPrefix(envelope, serviceId)}[validatePniSignature] Invalid PNI signature! Cannot associate ACI ($serviceId) with PNI ($pni)")
Log.w(TAG, "${logPrefix(envelope, aci)}[validatePniSignature] Invalid PNI signature! Cannot associate ACI ($aci) with PNI ($pni)")
}
}

View File

@@ -98,6 +98,7 @@ import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer
import org.whispersystems.signalservice.api.push.DistributionId
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.api.push.SignalServiceAddress
import org.whispersystems.signalservice.api.storage.StorageKey
import org.whispersystems.signalservice.internal.push.SignalServiceProtos
@@ -1227,8 +1228,8 @@ object SyncMessageProcessor {
return
}
val serviceId = ServiceId.fromByteString(callEvent.conversationId)
val recipientId = RecipientId.from(serviceId)
val aci = ACI.parseOrThrow(callEvent.conversationId)
val recipientId = RecipientId.from(aci)
log(envelopeTimestamp, "Synchronize call event call: $callId")