Resolved a few MMS issues.

1) Fixed the "Unsupported Encoding!" problem.

2) Workaround for the Sprint issue, where the MMSC is adding a single
   extra byte to the end of each encrypted message.

3) Fixed the "large blob of base64 text" on encrypted MMS problem.
This commit is contained in:
Moxie Marlinspike 2013-05-25 13:17:18 -07:00
parent d2a78ea84c
commit 8524cc5598
6 changed files with 38 additions and 19 deletions

View File

@ -190,7 +190,21 @@ public class DecryptingQueue {
synchronized (SessionCipher.CIPHER_LOCK) { synchronized (SessionCipher.CIPHER_LOCK) {
Log.w("DecryptingQueue", "Decrypting: " + Hex.toString(ciphertextPduBytes)); Log.w("DecryptingQueue", "Decrypting: " + Hex.toString(ciphertextPduBytes));
SessionCipher cipher = new SessionCipher(context, masterSecret, recipient, new TextTransport()); SessionCipher cipher = new SessionCipher(context, masterSecret, recipient, new TextTransport());
plaintextPduBytes = cipher.decryptMessage(ciphertextPduBytes); try {
plaintextPduBytes = cipher.decryptMessage(ciphertextPduBytes);
} catch (InvalidMessageException ime) {
// XXX - For some reason, Sprint seems to append a single character to the
// end of message text segments. I don't know why, so here we just try
// truncating the message by one if the MAC fails.
if (ciphertextPduBytes.length > 2) {
Log.w("DecryptingQueue", "Attempting truncated decrypt...");
byte[] truncated = new byte[ciphertextPduBytes.length - 1];
System.arraycopy(ciphertextPduBytes, 0, truncated, 0, truncated.length);
plaintextPduBytes = cipher.decryptMessage(truncated);
} else {
throw ime;
}
}
} }
MultimediaMessagePdu plaintextGenericPdu = (MultimediaMessagePdu)new PduParser(plaintextPduBytes).parse(); MultimediaMessagePdu plaintextGenericPdu = (MultimediaMessagePdu)new PduParser(plaintextPduBytes).parse();

View File

@ -90,7 +90,8 @@ public class KeyExchangeMessage {
this.serialized = messageBody; this.serialized = messageBody;
if (messageVersion > Message.SUPPORTED_VERSION) if (messageVersion > Message.SUPPORTED_VERSION)
throw new InvalidVersionException("Key exchange with version: " + messageVersion + " but we only support: " + Message.SUPPORTED_VERSION); throw new InvalidVersionException("Key exchange with version: " + messageVersion +
" but we only support: " + Message.SUPPORTED_VERSION);
if (messageVersion >= 1) if (messageVersion >= 1)
keyBytes = Base64.decodeWithoutPadding(messageBody); keyBytes = Base64.decodeWithoutPadding(messageBody);

View File

@ -23,16 +23,15 @@ import android.util.Log;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.StatusLine; import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.RetrieveConf;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.RetrieveConf;
public class MmsDownloadHelper extends MmsCommunication { public class MmsDownloadHelper extends MmsCommunication {
private static byte[] makeRequest(Context context, MmsConnectionParameters connectionParameters, String url) private static byte[] makeRequest(Context context, MmsConnectionParameters connectionParameters, String url)

View File

@ -30,13 +30,13 @@ import org.apache.http.entity.ByteArrayEntity;
import org.thoughtcrime.securesms.service.MmscProcessor; import org.thoughtcrime.securesms.service.MmscProcessor;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.SendConf;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.SendConf;
public class MmsSendHelper extends MmsCommunication { public class MmsSendHelper extends MmsCommunication {
private static byte[] makePost(Context context, MmsConnectionParameters parameters, byte[] mms) throws ClientProtocolException, IOException { private static byte[] makePost(Context context, MmsConnectionParameters parameters, byte[] mms) throws ClientProtocolException, IOException {

View File

@ -19,8 +19,12 @@ public class PartParser {
String partText; String partText;
try { try {
partText = new String(body.getPart(i).getData(), String characterSet = CharacterSets.getMimeName(body.getPart(i).getCharset());
CharacterSets.getMimeName(body.getPart(i).getCharset()));
if (characterSet.equals(CharacterSets.MIMENAME_ANY_CHARSET))
characterSet = CharacterSets.MIMENAME_ISO_8859_1;
partText = new String(body.getPart(i).getData(), characterSet);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
Log.w("PartParser", e); Log.w("PartParser", e);
partText = "Unsupported Encoding!"; partText = "Unsupported Encoding!";

View File

@ -209,20 +209,21 @@ public class MmsSender extends MmscProcessor {
EncodedStringValue[] encodedRecipient = pdu.getTo(); EncodedStringValue[] encodedRecipient = pdu.getTo();
String recipient = encodedRecipient[0].getString(); String recipient = encodedRecipient[0].getString();
byte[] pduBytes = new PduComposer(context, pdu).make(); byte[] pduBytes = new PduComposer(context, pdu).make();
byte[] encryptedPdu = getEncryptedPdu(masterSecret, recipient, pduBytes); byte[] encryptedPduBytes = getEncryptedPdu(masterSecret, recipient, pduBytes);
Log.w("MmsSendeR", "Got encrypted bytes: " + encryptedPdu.length);
PduBody body = new PduBody(); PduBody body = new PduBody();
PduPart part = new PduPart(); PduPart part = new PduPart();
SendReq encryptedPdu = new SendReq(pdu.getPduHeaders(), body);
part.setContentId((System.currentTimeMillis()+"").getBytes()); part.setContentId((System.currentTimeMillis()+"").getBytes());
part.setContentType(ContentType.TEXT_PLAIN.getBytes()); part.setContentType(ContentType.TEXT_PLAIN.getBytes());
part.setName((System.currentTimeMillis()+"").getBytes()); part.setName((System.currentTimeMillis()+"").getBytes());
part.setData(encryptedPdu); part.setData(encryptedPduBytes);
body.addPart(part); body.addPart(part);
pdu.setSubject(new EncodedStringValue(WirePrefix.calculateEncryptedMmsSubject())); encryptedPdu.setSubject(new EncodedStringValue(WirePrefix.calculateEncryptedMmsSubject()));
pdu.setBody(body); encryptedPdu.setBody(body);
return pdu; return encryptedPdu;
} }
private void scheduleSendWithMmsRadioAndProxy(SendItem item) { private void scheduleSendWithMmsRadioAndProxy(SendItem item) {