mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
Verify identity keys on outgoing messages.
If PreKeyEntity identity key doesn't match local DB, fail outgoing message and queue "incoming" identity key update message for manual user approval.
This commit is contained in:
parent
e2989373cd
commit
e7e5bc0884
@ -264,6 +264,7 @@
|
||||
<string name="SmsMessageRecord_received_message_with_unknown_identity_key_click_to_process">
|
||||
Received message with unknown identity key. Click 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>
|
||||
|
||||
|
||||
<!-- VerifyIdentityActivity -->
|
||||
|
@ -358,6 +358,7 @@ public class ConversationItem extends LinearLayout {
|
||||
intent.putExtra("thread_id", messageRecord.getThreadId());
|
||||
intent.putExtra("message_id", messageRecord.getId());
|
||||
intent.putExtra("is_bundle", messageRecord.isBundleKeyExchange());
|
||||
intent.putExtra("is_identity_update", messageRecord.isIdentityUpdate());
|
||||
intent.putExtra("master_secret", masterSecret);
|
||||
intent.putExtra("sent", messageRecord.isOutgoing());
|
||||
context.startActivity(intent);
|
||||
|
@ -47,6 +47,7 @@ import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.crypto.protocol.PreKeyWhisperMessage;
|
||||
import org.whispersystems.textsecure.storage.InvalidKeyIdException;
|
||||
import org.whispersystems.textsecure.storage.RecipientDevice;
|
||||
import org.whispersystems.textsecure.util.Base64;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -71,6 +72,7 @@ public class ReceiveKeyActivity extends Activity {
|
||||
private MasterSecret masterSecret;
|
||||
private PreKeyWhisperMessage keyExchangeMessageBundle;
|
||||
private KeyExchangeMessage keyExchangeMessage;
|
||||
private IdentityKey identityUpdateMessage;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle state) {
|
||||
@ -99,8 +101,11 @@ public class ReceiveKeyActivity extends Activity {
|
||||
}
|
||||
|
||||
private void initializeText() {
|
||||
if (isTrusted(keyExchangeMessage, keyExchangeMessageBundle)) initializeTrustedText();
|
||||
else initializeUntrustedText();
|
||||
if (isTrusted(keyExchangeMessage, keyExchangeMessageBundle, identityUpdateMessage)) {
|
||||
initializeTrustedText();
|
||||
} else {
|
||||
initializeUntrustedText();
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeTrustedText() {
|
||||
@ -113,12 +118,16 @@ public class ReceiveKeyActivity extends Activity {
|
||||
spannableString.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
IdentityKey remoteIdentity;
|
||||
|
||||
if (identityUpdateMessage != null) remoteIdentity = identityUpdateMessage;
|
||||
else if (keyExchangeMessageBundle != null) remoteIdentity = keyExchangeMessageBundle.getIdentityKey();
|
||||
else remoteIdentity = keyExchangeMessage.getIdentityKey();
|
||||
|
||||
Intent intent = new Intent(ReceiveKeyActivity.this, VerifyIdentityActivity.class);
|
||||
intent.putExtra("recipient", recipient);
|
||||
intent.putExtra("master_secret", masterSecret);
|
||||
intent.putExtra("remote_identity",
|
||||
keyExchangeMessage == null ?
|
||||
keyExchangeMessageBundle.getIdentityKey() : keyExchangeMessage.getIdentityKey());
|
||||
intent.putExtra("remote_identity", remoteIdentity);
|
||||
startActivity(intent);
|
||||
}
|
||||
}, getString(R.string.ReceiveKeyActivity_the_signature_on_this_key_exchange_is_different).length() +1,
|
||||
@ -128,7 +137,7 @@ public class ReceiveKeyActivity extends Activity {
|
||||
descriptionText.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
private boolean isTrusted(KeyExchangeMessage message, PreKeyWhisperMessage messageBundle) {
|
||||
private boolean isTrusted(KeyExchangeMessage message, PreKeyWhisperMessage messageBundle, IdentityKey identityUpdateMessage) {
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), recipientDeviceId);
|
||||
|
||||
if (message != null) {
|
||||
@ -138,6 +147,9 @@ public class ReceiveKeyActivity extends Activity {
|
||||
} else if (messageBundle != null) {
|
||||
KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(this, masterSecret, recipientDevice);
|
||||
return processor.isTrusted(messageBundle);
|
||||
} else if (identityUpdateMessage != null) {
|
||||
KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(this, masterSecret, recipientDevice);
|
||||
return processor.isTrusted(identityUpdateMessage);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -154,6 +166,8 @@ public class ReceiveKeyActivity extends Activity {
|
||||
byte[] body = transportDetails.getDecodedMessage(messageBody.getBytes());
|
||||
|
||||
this.keyExchangeMessageBundle = new PreKeyWhisperMessage(body);
|
||||
} else if (getIntent().getBooleanExtra("is_identity_update", false)) {
|
||||
this.identityUpdateMessage = new IdentityKey(Base64.decodeWithoutPadding(messageBody), 0);
|
||||
} else {
|
||||
this.keyExchangeMessage = KeyExchangeMessage.createFor(messageBody);
|
||||
}
|
||||
@ -232,6 +246,11 @@ public class ReceiveKeyActivity extends Activity {
|
||||
DatabaseFactory.getEncryptingSmsDatabase(ReceiveKeyActivity.this)
|
||||
.markAsCorruptKeyExchange(messageId);
|
||||
}
|
||||
} else if (identityUpdateMessage != null) {
|
||||
DatabaseFactory.getIdentityDatabase(ReceiveKeyActivity.this)
|
||||
.saveIdentity(masterSecret, recipient.getRecipientId(), identityUpdateMessage);
|
||||
|
||||
DatabaseFactory.getSmsDatabase(ReceiveKeyActivity.this).markAsProcessedKeyExchange(messageId);
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,6 +55,10 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
return isTrusted(message.getIdentityKey());
|
||||
}
|
||||
|
||||
public boolean isTrusted(PreKeyEntity entity) {
|
||||
return isTrusted(entity.getIdentityKey());
|
||||
}
|
||||
|
||||
public boolean isTrusted(KeyExchangeMessage message) {
|
||||
return message.hasIdentityKey() && isTrusted(message.getIdentityKey());
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ public interface MmsSmsColumns {
|
||||
protected static final long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000;
|
||||
protected static final long KEY_EXCHANGE_INVALID_VERSION_BIT = 0x800;
|
||||
protected static final long KEY_EXCHANGE_BUNDLE_BIT = 0x400;
|
||||
protected static final long KEY_EXCHANGE_IDENTITY_UPDATE_BIT = 0x200;
|
||||
|
||||
// Secure Message Information
|
||||
protected static final long SECURE_MESSAGE_BIT = 0x800000;
|
||||
@ -98,6 +99,10 @@ public interface MmsSmsColumns {
|
||||
return (type & KEY_EXCHANGE_BUNDLE_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isIdentityUpdate(long type) {
|
||||
return (type & KEY_EXCHANGE_IDENTITY_UPDATE_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isSymmetricEncryption(long type) {
|
||||
return (type & ENCRYPTION_SYMMETRIC_BIT) != 0;
|
||||
}
|
||||
|
@ -252,6 +252,7 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
|
||||
else if (((IncomingKeyExchangeMessage)message).isCorrupted()) type |= Types.KEY_EXCHANGE_CORRUPTED_BIT;
|
||||
else if (((IncomingKeyExchangeMessage)message).isInvalidVersion()) type |= Types.KEY_EXCHANGE_INVALID_VERSION_BIT;
|
||||
else if (((IncomingKeyExchangeMessage)message).isPreKeyBundle()) type |= Types.KEY_EXCHANGE_BUNDLE_BIT;
|
||||
else if (((IncomingKeyExchangeMessage)message).isIdentityUpdate()) type |= Types.KEY_EXCHANGE_IDENTITY_UPDATE_BIT;
|
||||
} else if (message.isSecureMessage()) {
|
||||
type |= Types.SECURE_MESSAGE_BIT;
|
||||
type |= Types.ENCRYPTION_REMOTE_BIT;
|
||||
|
@ -111,6 +111,10 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return SmsDatabase.Types.isBundleKeyExchange(type);
|
||||
}
|
||||
|
||||
public boolean isIdentityUpdate() {
|
||||
return SmsDatabase.Types.isIdentityUpdate(type);
|
||||
}
|
||||
|
||||
public boolean isCorruptedKeyExchange() {
|
||||
return SmsDatabase.Types.isCorruptedKeyExchange(type);
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ public class SmsMessageRecord extends MessageRecord {
|
||||
return emphasisAdded(context.getString(R.string.SmsMessageRecord_received_key_exchange_message_for_invalid_protocol_version));
|
||||
} else if (isBundleKeyExchange()) {
|
||||
return emphasisAdded(context.getString(R.string.SmsMessageRecord_received_message_with_unknown_identity_key_click_to_process));
|
||||
} else if (isIdentityUpdate()) {
|
||||
return emphasisAdded(context.getString(R.string.SmsMessageRecord_received_updated_but_unknown_identity_information));
|
||||
} else if (isKeyExchange() && isOutgoing()) {
|
||||
return new SpannableString("");
|
||||
} else if (isKeyExchange() && !isOutgoing()) {
|
||||
|
@ -30,10 +30,14 @@ import org.thoughtcrime.securesms.mms.MmsSendResult;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.SendReceiveService.ToastHandler;
|
||||
import org.thoughtcrime.securesms.sms.IncomingIdentityUpdateMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
import org.thoughtcrime.securesms.transport.UniversalTransport;
|
||||
import org.thoughtcrime.securesms.transport.UntrustedIdentityException;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.util.Base64;
|
||||
|
||||
import ws.com.google.android.mms.MmsException;
|
||||
import ws.com.google.android.mms.pdu.SendReq;
|
||||
@ -87,6 +91,11 @@ public class MmsSender {
|
||||
database.markAsSentFailed(message.getDatabaseMessageId());
|
||||
Recipients recipients = threads.getRecipientsForThreadId(threadId);
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipients, threadId);
|
||||
} catch (UntrustedIdentityException uie) {
|
||||
IncomingTextMessage base = new IncomingTextMessage(message);
|
||||
IncomingIdentityUpdateMessage identityUpdateMessage = new IncomingIdentityUpdateMessage(base, Base64.encodeBytesWithoutPadding(uie.getIdentityKey().serialize()));
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).insertMessageInbox(masterSecret, identityUpdateMessage);
|
||||
database.markAsSentFailed(messageId);
|
||||
} catch (RetryLaterException e) {
|
||||
Log.w("MmsSender", e);
|
||||
database.markAsOutbox(message.getDatabaseMessageId());
|
||||
|
@ -30,9 +30,13 @@ import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.SendReceiveService.ToastHandler;
|
||||
import org.thoughtcrime.securesms.sms.IncomingIdentityUpdateMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
import org.thoughtcrime.securesms.transport.UniversalTransport;
|
||||
import org.thoughtcrime.securesms.transport.UntrustedIdentityException;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.util.Base64;
|
||||
|
||||
public class SmsSender {
|
||||
|
||||
@ -71,12 +75,21 @@ public class SmsSender {
|
||||
else reader = database.getOutgoingMessages(masterSecret);
|
||||
|
||||
while (reader != null && (record = reader.getNext()) != null) {
|
||||
database.markAsSending(record.getId());
|
||||
transport.deliver(record);
|
||||
try {
|
||||
database.markAsSending(record.getId());
|
||||
|
||||
transport.deliver(record);
|
||||
} catch (UntrustedIdentityException e) {
|
||||
Log.w("SmsSender", e);
|
||||
IncomingTextMessage base = new IncomingTextMessage(record);
|
||||
IncomingIdentityUpdateMessage identityUpdateMessage = new IncomingIdentityUpdateMessage(base, Base64.encodeBytesWithoutPadding(e.getIdentityKey().serialize()));
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).insertMessageInbox(masterSecret, identityUpdateMessage);
|
||||
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
|
||||
} catch (UndeliverableMessageException ude) {
|
||||
Log.w("SmsSender", ude);
|
||||
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
|
||||
}
|
||||
}
|
||||
} catch (UndeliverableMessageException ude) {
|
||||
Log.w("SmsSender", ude);
|
||||
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
|
||||
} finally {
|
||||
if (reader != null)
|
||||
reader.close();
|
||||
|
@ -0,0 +1,18 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
public class IncomingIdentityUpdateMessage extends IncomingKeyExchangeMessage {
|
||||
|
||||
public IncomingIdentityUpdateMessage(IncomingTextMessage base, String newBody) {
|
||||
super(base, newBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IncomingIdentityUpdateMessage withMessageBody(String messageBody) {
|
||||
return new IncomingIdentityUpdateMessage(this, messageBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentityUpdate() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import org.whispersystems.textsecure.push.IncomingPushMessage;
|
||||
|
||||
public class IncomingPreKeyBundleMessage extends IncomingKeyExchangeMessage {
|
||||
|
||||
public IncomingPreKeyBundleMessage(IncomingTextMessage base, String newBody) {
|
||||
|
@ -4,12 +4,15 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.telephony.SmsMessage;
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.textsecure.push.IncomingPushMessage;
|
||||
import org.whispersystems.textsecure.storage.RecipientDevice;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ws.com.google.android.mms.pdu.SendReq;
|
||||
|
||||
import static org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent.GroupContext;
|
||||
|
||||
public class IncomingTextMessage implements Parcelable {
|
||||
@ -121,6 +124,34 @@ public class IncomingTextMessage implements Parcelable {
|
||||
this.groupActionArgument = fragments.get(0).getGroupActionArgument();
|
||||
}
|
||||
|
||||
public IncomingTextMessage(SendReq record) {
|
||||
this.message = "";
|
||||
this.sender = record.getTo()[0].getString();
|
||||
this.senderDeviceId = RecipientDevice.DEFAULT_DEVICE_ID;
|
||||
this.protocol = 31338;
|
||||
this.serviceCenterAddress = "Outgoing";
|
||||
this.replyPathPresent = true;
|
||||
this.pseudoSubject = "";
|
||||
this.sentTimestampMillis = System.currentTimeMillis();
|
||||
this.groupId = null;
|
||||
this.groupAction = -1;
|
||||
this.groupActionArgument = null;
|
||||
}
|
||||
|
||||
public IncomingTextMessage(SmsMessageRecord record) {
|
||||
this.message = record.getBody().getBody();
|
||||
this.sender = record.getIndividualRecipient().getNumber();
|
||||
this.senderDeviceId = RecipientDevice.DEFAULT_DEVICE_ID;
|
||||
this.protocol = 31338;
|
||||
this.serviceCenterAddress = "Outgoing";
|
||||
this.replyPathPresent = true;
|
||||
this.pseudoSubject = "";
|
||||
this.sentTimestampMillis = System.currentTimeMillis();
|
||||
this.groupId = null;
|
||||
this.groupAction = -1;
|
||||
this.groupActionArgument = null;
|
||||
}
|
||||
|
||||
public long getSentTimestampMillis() {
|
||||
return sentTimestampMillis;
|
||||
}
|
||||
@ -169,6 +200,10 @@ public class IncomingTextMessage implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdentityUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
@ -73,7 +73,9 @@ public class PushTransport extends BaseTransport {
|
||||
this.masterSecret = masterSecret;
|
||||
}
|
||||
|
||||
public void deliver(SmsMessageRecord message) throws IOException {
|
||||
public void deliver(SmsMessageRecord message)
|
||||
throws IOException, UntrustedIdentityException
|
||||
{
|
||||
try {
|
||||
Recipient recipient = message.getIndividualRecipient();
|
||||
long threadId = message.getThreadId();
|
||||
@ -97,7 +99,9 @@ public class PushTransport extends BaseTransport {
|
||||
}
|
||||
}
|
||||
|
||||
public void deliver(SendReq message, long threadId) throws IOException {
|
||||
public void deliver(SendReq message, long threadId)
|
||||
throws IOException, UntrustedIdentityException
|
||||
{
|
||||
PushServiceSocket socket = PushServiceSocketFactory.create(context);
|
||||
byte[] plaintext = getPlaintextMessage(socket, message);
|
||||
String destination = message.getTo()[0].getString();
|
||||
@ -147,6 +151,9 @@ public class PushTransport extends BaseTransport {
|
||||
} catch (IOException e) {
|
||||
Log.w("PushTransport", e);
|
||||
failures.add(recipient);
|
||||
} catch (UntrustedIdentityException e) {
|
||||
Log.w("PushTransport", e);
|
||||
failures.add(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +172,7 @@ public class PushTransport extends BaseTransport {
|
||||
}
|
||||
|
||||
private void deliver(PushServiceSocket socket, Recipient recipient, long threadId, byte[] plaintext)
|
||||
throws IOException, InvalidNumberException
|
||||
throws IOException, InvalidNumberException, UntrustedIdentityException
|
||||
{
|
||||
for (int i=0;i<3;i++) {
|
||||
try {
|
||||
@ -274,7 +281,7 @@ public class PushTransport extends BaseTransport {
|
||||
|
||||
private OutgoingPushMessageList getEncryptedMessages(PushServiceSocket socket, long threadId,
|
||||
Recipient recipient, byte[] plaintext)
|
||||
throws IOException, InvalidNumberException
|
||||
throws IOException, InvalidNumberException, UntrustedIdentityException
|
||||
{
|
||||
String e164number = Util.canonicalizeNumber(context, recipient.getNumber());
|
||||
long recipientId = recipient.getRecipientId();
|
||||
@ -296,7 +303,7 @@ public class PushTransport extends BaseTransport {
|
||||
|
||||
private PushBody getEncryptedMessage(PushServiceSocket socket, long threadId,
|
||||
PushAddress pushAddress, byte[] plaintext)
|
||||
throws IOException
|
||||
throws IOException, UntrustedIdentityException
|
||||
{
|
||||
if (!SessionRecordV2.hasSession(context, masterSecret, pushAddress)) {
|
||||
try {
|
||||
@ -306,7 +313,11 @@ public class PushTransport extends BaseTransport {
|
||||
PushAddress device = PushAddress.create(context, pushAddress.getRecipientId(), pushAddress.getNumber(), preKey.getDeviceId());
|
||||
KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(context, masterSecret, device);
|
||||
|
||||
processor.processKeyExchangeMessage(preKey, threadId);
|
||||
if (processor.isTrusted(preKey)) {
|
||||
processor.processKeyExchangeMessage(preKey, threadId);
|
||||
} else {
|
||||
throw new UntrustedIdentityException("Untrusted identity key!", preKey.getIdentityKey());
|
||||
}
|
||||
}
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new IOException(e);
|
||||
|
@ -18,7 +18,6 @@ package org.thoughtcrime.securesms.transport;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.mms.MmsSendResult;
|
||||
@ -54,7 +53,9 @@ public class UniversalTransport {
|
||||
this.mmsTransport = new MmsTransport(context, masterSecret);
|
||||
}
|
||||
|
||||
public void deliver(SmsMessageRecord message) throws UndeliverableMessageException {
|
||||
public void deliver(SmsMessageRecord message)
|
||||
throws UndeliverableMessageException, UntrustedIdentityException
|
||||
{
|
||||
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||
smsTransport.deliver(message);
|
||||
return;
|
||||
@ -83,7 +84,7 @@ public class UniversalTransport {
|
||||
}
|
||||
|
||||
public MmsSendResult deliver(SendReq mediaMessage, long threadId)
|
||||
throws UndeliverableMessageException, RetryLaterException
|
||||
throws UndeliverableMessageException, RetryLaterException, UntrustedIdentityException
|
||||
{
|
||||
if (Util.isEmpty(mediaMessage.getTo())) {
|
||||
throw new UndeliverableMessageException("No destination specified");
|
||||
@ -97,14 +98,23 @@ public class UniversalTransport {
|
||||
return mmsTransport.deliver(mediaMessage);
|
||||
}
|
||||
|
||||
if (isPushTransport(mediaMessage.getTo()[0].getString())) {
|
||||
String destination;
|
||||
|
||||
try {
|
||||
destination = Util.canonicalizeNumber(context, mediaMessage.getTo()[0].getString());
|
||||
} catch (InvalidNumberException ine) {
|
||||
Log.w("UniversalTransport", ine);
|
||||
return mmsTransport.deliver(mediaMessage);
|
||||
}
|
||||
|
||||
if (isPushTransport(destination)) {
|
||||
try {
|
||||
Log.w("UniversalTransport", "Delivering media message with GCM...");
|
||||
pushTransport.deliver(mediaMessage, threadId);
|
||||
return new MmsSendResult("push".getBytes("UTF-8"), 0, true);
|
||||
} catch (IOException ioe) {
|
||||
Log.w("UniversalTransport", ioe);
|
||||
if (!GroupUtil.isEncodedGroup(mediaMessage.getTo()[0].getString())) {
|
||||
if (!GroupUtil.isEncodedGroup(destination)) {
|
||||
return mmsTransport.deliver(mediaMessage);
|
||||
} else {
|
||||
throw new RetryLaterException();
|
||||
|
@ -0,0 +1,17 @@
|
||||
package org.thoughtcrime.securesms.transport;
|
||||
|
||||
import org.whispersystems.textsecure.crypto.IdentityKey;
|
||||
|
||||
public class UntrustedIdentityException extends Exception {
|
||||
|
||||
private final IdentityKey identityKey;
|
||||
|
||||
public UntrustedIdentityException(String s, IdentityKey identityKey) {
|
||||
super(s);
|
||||
this.identityKey = identityKey;
|
||||
}
|
||||
|
||||
public IdentityKey getIdentityKey() {
|
||||
return identityKey;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user