Correctly update MMS security status.

This commit is contained in:
Moxie Marlinspike 2013-11-19 10:13:24 -08:00
parent 7e926d08ac
commit 4380b46a35
6 changed files with 64 additions and 16 deletions

View File

@ -262,6 +262,10 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
} }
public void markAsSecure(long messageId) {
updateMailboxBitmask(messageId, 0, Types.SECURE_MESSAGE_BIT);
}
public void markAsDecryptFailed(long messageId, long threadId) { public void markAsDecryptFailed(long messageId, long threadId) {
updateMailboxBitmask(messageId, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_FAILED_BIT); updateMailboxBitmask(messageId, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_FAILED_BIT);
notifyConversationListeners(threadId); notifyConversationListeners(threadId);

View File

@ -0,0 +1,27 @@
package org.thoughtcrime.securesms.mms;
public class MmsSendResult {
private final byte[] messageId;
private final int responseStatus;
private final boolean upgradedSecure;
public MmsSendResult(byte[] messageId, int responseStatus, boolean upgradedSecure) {
this.messageId = messageId;
this.responseStatus = responseStatus;
this.upgradedSecure = upgradedSecure;
}
public boolean isUpgradedSecure() {
return upgradedSecure;
}
public int getResponseStatus() {
return responseStatus;
}
public byte[] getMessageId() {
return messageId;
}
}

View File

@ -24,6 +24,7 @@ import android.util.Pair;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.mms.MmsSendResult;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.SendReceiveService.ToastHandler; import org.thoughtcrime.securesms.service.SendReceiveService.ToastHandler;
@ -64,8 +65,14 @@ public class MmsSender {
try { try {
Log.w("MmsSender", "Passing to MMS transport: " + message.getDatabaseMessageId()); Log.w("MmsSender", "Passing to MMS transport: " + message.getDatabaseMessageId());
database.markAsSending(message.getDatabaseMessageId()); database.markAsSending(message.getDatabaseMessageId());
Pair<byte[], Integer> result = transport.deliver(message, threadId); MmsSendResult result = transport.deliver(message, threadId);
database.markAsSent(message.getDatabaseMessageId(), result.first, result.second);
if (result.isUpgradedSecure()) {
database.markAsSecure(message.getDatabaseMessageId());
}
database.markAsSent(message.getDatabaseMessageId(), result.getMessageId(),
result.getResponseStatus());
} catch (UndeliverableMessageException e) { } catch (UndeliverableMessageException e) {
Log.w("MmsSender", e); Log.w("MmsSender", e);
database.markAsSentFailed(message.getDatabaseMessageId()); database.markAsSentFailed(message.getDatabaseMessageId());

View File

@ -16,6 +16,7 @@ import org.whispersystems.textsecure.crypto.AttachmentCipherInputStream;
import org.whispersystems.textsecure.crypto.InvalidMessageException; import org.whispersystems.textsecure.crypto.InvalidMessageException;
import org.whispersystems.textsecure.crypto.MasterCipher; import org.whispersystems.textsecure.crypto.MasterCipher;
import org.whispersystems.textsecure.crypto.MasterSecret; import org.whispersystems.textsecure.crypto.MasterSecret;
import org.whispersystems.textsecure.push.NotFoundException;
import org.whispersystems.textsecure.push.PushServiceSocket; import org.whispersystems.textsecure.push.PushServiceSocket;
import org.whispersystems.textsecure.util.Base64; import org.whispersystems.textsecure.util.Base64;
@ -79,6 +80,13 @@ public class PushDownloader {
InputStream attachmentInput = new AttachmentCipherInputStream(attachmentFile, key); InputStream attachmentInput = new AttachmentCipherInputStream(attachmentFile, key);
database.updateDownloadedPart(messageId, partId, part, attachmentInput); database.updateDownloadedPart(messageId, partId, part, attachmentInput);
} catch (NotFoundException e) {
Log.w("PushDownloader", e);
try {
database.updateFailedDownloadedPart(messageId, partId, part);
} catch (MmsException mme) {
Log.w("PushDownloader", mme);
}
} catch (InvalidMessageException e) { } catch (InvalidMessageException e) {
Log.w("PushDownloader", e); Log.w("PushDownloader", e);
try { try {

View File

@ -20,21 +20,20 @@ package org.thoughtcrime.securesms.transport;
import android.content.Context; import android.content.Context;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.whispersystems.textsecure.crypto.IdentityKeyPair;
import org.whispersystems.textsecure.crypto.MasterSecret;
import org.whispersystems.textsecure.crypto.MessageCipher;
import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.mms.MmsRadio; import org.thoughtcrime.securesms.mms.MmsRadio;
import org.thoughtcrime.securesms.mms.MmsRadioException; import org.thoughtcrime.securesms.mms.MmsRadioException;
import org.thoughtcrime.securesms.mms.MmsSendHelper; import org.thoughtcrime.securesms.mms.MmsSendHelper;
import org.thoughtcrime.securesms.mms.MmsSendResult;
import org.thoughtcrime.securesms.mms.TextTransport; import org.thoughtcrime.securesms.mms.TextTransport;
import org.thoughtcrime.securesms.protocol.WirePrefix; import org.thoughtcrime.securesms.protocol.WirePrefix;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.textsecure.crypto.IdentityKeyPair;
import org.whispersystems.textsecure.crypto.MasterSecret;
import org.whispersystems.textsecure.crypto.MessageCipher;
import org.whispersystems.textsecure.crypto.ecc.Curve; import org.whispersystems.textsecure.crypto.ecc.Curve;
import org.whispersystems.textsecure.crypto.ecc.ECPublicKey;
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage; import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
import org.whispersystems.textsecure.util.Hex; import org.whispersystems.textsecure.util.Hex;
@ -62,7 +61,7 @@ public class MmsTransport {
this.radio = MmsRadio.getInstance(context); this.radio = MmsRadio.getInstance(context);
} }
public Pair<byte[], Integer> deliver(SendReq message) throws UndeliverableMessageException { public MmsSendResult deliver(SendReq message) throws UndeliverableMessageException {
try { try {
if (isCdmaDevice()) { if (isCdmaDevice()) {
Log.w("MmsTransport", "Sending MMS directly without radio change..."); Log.w("MmsTransport", "Sending MMS directly without radio change...");
@ -77,7 +76,7 @@ public class MmsTransport {
radio.connect(); radio.connect();
try { try {
Pair<byte[], Integer> result = sendMms(message, true, false); MmsSendResult result = sendMms(message, true, false);
radio.disconnect(); radio.disconnect();
return result; return result;
} catch (IOException e) { } catch (IOException e) {
@ -87,7 +86,7 @@ public class MmsTransport {
Log.w("MmsTransport", "Sending MMS with radio change and proxy..."); Log.w("MmsTransport", "Sending MMS with radio change and proxy...");
try { try {
Pair<byte[], Integer> result = sendMms(message, true, true); MmsSendResult result = sendMms(message, true, true);
radio.disconnect(); radio.disconnect();
return result; return result;
} catch (IOException ioe) { } catch (IOException ioe) {
@ -102,13 +101,15 @@ public class MmsTransport {
} }
} }
private Pair<byte[], Integer> sendMms(SendReq message, boolean usingMmsRadio, boolean useProxy) private MmsSendResult sendMms(SendReq message, boolean usingMmsRadio, boolean useProxy)
throws IOException, UndeliverableMessageException throws IOException, UndeliverableMessageException
{ {
String number = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number(); String number = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number();
boolean upgradedSecure = false;
if (MmsDatabase.Types.isSecureType(message.getDatabaseMessageBox())) { if (MmsDatabase.Types.isSecureType(message.getDatabaseMessageBox())) {
message = getEncryptedMessage(message); message = getEncryptedMessage(message);
upgradedSecure = true;
} }
if (number != null && number.trim().length() != 0) { if (number != null && number.trim().length() != 0) {
@ -129,7 +130,7 @@ public class MmsTransport {
} else if (isInconsistentResponse(message, conf)) { } else if (isInconsistentResponse(message, conf)) {
throw new UndeliverableMessageException("Mismatched response!"); throw new UndeliverableMessageException("Mismatched response!");
} else { } else {
return new Pair<byte[], Integer>(conf.getMessageId(), conf.getResponseStatus()); return new MmsSendResult(conf.getMessageId(), conf.getResponseStatus(), upgradedSecure);
} }
} }

View File

@ -21,6 +21,7 @@ import android.util.Log;
import android.util.Pair; import android.util.Pair;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord; import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.mms.MmsSendResult;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.TextSecurePushCredentials; import org.thoughtcrime.securesms.util.TextSecurePushCredentials;
@ -76,7 +77,7 @@ public class UniversalTransport {
} }
} }
public Pair<byte[], Integer> deliver(SendReq mediaMessage, long threadId) public MmsSendResult deliver(SendReq mediaMessage, long threadId)
throws UndeliverableMessageException throws UndeliverableMessageException
{ {
if (!TextSecurePreferences.isPushRegistered(context)) { if (!TextSecurePreferences.isPushRegistered(context)) {
@ -89,7 +90,7 @@ public class UniversalTransport {
try { try {
Log.w("UniversalTransport", "Delivering media message with GCM..."); Log.w("UniversalTransport", "Delivering media message with GCM...");
pushTransport.deliver(mediaMessage, destinations, threadId); pushTransport.deliver(mediaMessage, destinations, threadId);
return new Pair<byte[], Integer>("push".getBytes("UTF-8"), 0); return new MmsSendResult("push".getBytes("UTF-8"), 0, true);
} catch (IOException ioe) { } catch (IOException ioe) {
Log.w("UniversalTransport", ioe); Log.w("UniversalTransport", ioe);
return mmsTransport.deliver(mediaMessage); return mmsTransport.deliver(mediaMessage);