Fix for 'bad encrypted message' errors.

1) There was a regression in the outgoing multipart transport
   logic, such that the same 'identifier' byte would be used
   for all messages (0).  This now works correctly.

2) Added some additional heuristics on the receiving side.
   Now mutlipart containers are only valid for 1hr, and are
   considered invalid if the container size is different from
   the multipart message size.
pull/1/head
Moxie Marlinspike 11 years ago
parent 4281df7a28
commit 7d07d56fc3

@ -0,0 +1,32 @@
package org.thoughtcrime.securesms.sms;
import java.util.HashMap;
public class MultipartSmsIdentifier {
private static final MultipartSmsIdentifier instance = new MultipartSmsIdentifier();
public static MultipartSmsIdentifier getInstance() {
return instance;
}
private final HashMap<String, Integer> idMap = new HashMap<String, Integer>();
public synchronized byte getIdForRecipient(String recipient) {
Integer currentId;
if (idMap.containsKey(recipient)) {
currentId = idMap.get(recipient);
idMap.remove(recipient);
} else {
currentId = 0;
}
byte id = currentId.byteValue();
idMap.put(recipient, (currentId + 1) % 255);
return id;
}
}

@ -29,13 +29,17 @@ public class MultipartSmsMessageHandler {
private final HashMap<String, MultipartSmsTransportMessageFragments> partialMessages =
new HashMap<String, MultipartSmsTransportMessageFragments>();
private final HashMap<String, Integer> idMap = new HashMap<String, Integer>();
private IncomingTextMessage processMultipartMessage(MultipartSmsTransportMessage message) {
Log.w("MultipartSmsMessageHandler", "Processing multipart message...");
Log.w("MultipartSmsMessageHandler", "Multipart Count: " + message.getMultipartCount());
Log.w("MultipartSmsMessageHandler", "Multipart ID: " + message.getIdentifier());
Log.w("MultipartSmsMessageHandler", "Multipart Key: " + message.getKey());
MultipartSmsTransportMessageFragments container = partialMessages.get(message.getKey());
if (container == null) {
Log.w("MultipartSmsMessageHandler", "Found multipart container: " + container);
if (container == null || container.getSize() != message.getMultipartCount() || container.isExpired()) {
Log.w("MultipartSmsMessageHandler", "Constructing new container...");
container = new MultipartSmsTransportMessageFragments(message.getMultipartCount());
partialMessages.put(message.getKey(), container);
}
@ -81,24 +85,9 @@ public class MultipartSmsMessageHandler {
}
}
private byte getIdForRecipient(String recipient) {
Integer currentId;
if (idMap.containsKey(recipient)) {
currentId = idMap.get(recipient);
idMap.remove(recipient);
} else {
currentId = 0;
}
byte id = currentId.byteValue();
idMap.put(recipient, (currentId + 1) % 255);
return id;
}
public ArrayList<String> divideMessage(OutgoingTextMessage message) {
byte identifier = getIdForRecipient(message.getRecipients().getPrimaryRecipient().getNumber());
String number = message.getRecipients().getPrimaryRecipient().getNumber();
byte identifier = MultipartSmsIdentifier.getInstance().getIdForRecipient(number);
return MultipartSmsTransportMessage.getEncoded(message, identifier);
}
}

@ -2,16 +2,28 @@ package org.thoughtcrime.securesms.sms;
public class MultipartSmsTransportMessageFragments {
private static final long VALID_TIME = 60 * 60 * 1000; // 1 Hour
private final byte[][] fragments;
private final long initializedTime;
public MultipartSmsTransportMessageFragments(int count) {
this.fragments = new byte[count][];
this.fragments = new byte[count][];
this.initializedTime = System.currentTimeMillis();
}
public void add(MultipartSmsTransportMessage fragment) {
this.fragments[fragment.getMultipartIndex()] = fragment.getStrippedMessage();
}
public int getSize() {
return this.fragments.length;
}
public boolean isExpired() {
return (System.currentTimeMillis() - initializedTime) >= VALID_TIME;
}
public boolean isComplete() {
for (int i=0;i<fragments.length;i++)
if (fragments[i] == null) return false;
@ -37,4 +49,9 @@ public class MultipartSmsTransportMessageFragments {
return totalMessage;
}
@Override
public String toString() {
return String.format("[Size: %d, Initialized: %d, Exipired: %s, Complete: %s]",
fragments.length, initializedTime, isExpired()+"", isComplete()+"");
}
}

Loading…
Cancel
Save