Validate phone numbers when formatting.

This commit is contained in:
Moxie Marlinspike 2013-11-26 12:44:15 -08:00
parent f7b71e5e28
commit ce5f3c5157
7 changed files with 72 additions and 26 deletions

View File

@ -11,6 +11,7 @@ import android.util.Log;
import org.whispersystems.textsecure.push.ContactTokenDetails; import org.whispersystems.textsecure.push.ContactTokenDetails;
import org.whispersystems.textsecure.util.Base64; import org.whispersystems.textsecure.util.Base64;
import org.whispersystems.textsecure.util.InvalidNumberException;
import org.whispersystems.textsecure.util.PhoneNumberFormatter; import org.whispersystems.textsecure.util.PhoneNumberFormatter;
import org.whispersystems.textsecure.util.Util; import org.whispersystems.textsecure.util.Util;
@ -157,8 +158,12 @@ public class Directory {
String rawNumber = cursor.getString(0); String rawNumber = cursor.getString(0);
if (rawNumber != null) { if (rawNumber != null) {
try {
String e164Number = PhoneNumberFormatter.formatNumber(rawNumber, localNumber); String e164Number = PhoneNumberFormatter.formatNumber(rawNumber, localNumber);
results.add(getToken(e164Number)); results.add(getToken(e164Number));
} catch (InvalidNumberException e) {
Log.w("Directory", "Invalid number: " + rawNumber);
}
} }
} }

View File

@ -3,6 +3,7 @@ package org.whispersystems.textsecure.push;
import android.content.Context; import android.content.Context;
import org.whispersystems.textsecure.directory.Directory; import org.whispersystems.textsecure.directory.Directory;
import org.whispersystems.textsecure.util.InvalidNumberException;
import org.whispersystems.textsecure.util.PhoneNumberFormatter; import org.whispersystems.textsecure.util.PhoneNumberFormatter;
public class PushDestination { public class PushDestination {
@ -26,6 +27,7 @@ public class PushDestination {
public static PushDestination create(Context context, public static PushDestination create(Context context,
PushServiceSocket.PushCredentials credentials, PushServiceSocket.PushCredentials credentials,
String destinationNumber) String destinationNumber)
throws InvalidNumberException
{ {
String e164destination = PhoneNumberFormatter.formatNumber(destinationNumber, credentials.getLocalNumber(context)); String e164destination = PhoneNumberFormatter.formatNumber(destinationNumber, credentials.getLocalNumber(context));
String relay = Directory.getInstance(context).getRelay(e164destination); String relay = Directory.getInstance(context).getRelay(e164destination);

View File

@ -0,0 +1,7 @@
package org.whispersystems.textsecure.util;
public class InvalidNumberException extends Throwable {
public InvalidNumberException(String s) {
super(s);
}
}

View File

@ -21,7 +21,9 @@ public class PhoneNumberFormatter {
return number.matches("^\\+[0-9]{10,}"); return number.matches("^\\+[0-9]{10,}");
} }
private static String impreciseFormatNumber(String number, String localNumber) { private static String impreciseFormatNumber(String number, String localNumber)
throws InvalidNumberException
{
number = number.replaceAll("[^0-9+]", ""); number = number.replaceAll("[^0-9+]", "");
if (number.charAt(0) == '+') if (number.charAt(0) == '+')
@ -49,9 +51,19 @@ public class PhoneNumberFormatter {
} }
} }
public static String formatNumber(String number, String localNumber) { public static String formatNumber(String number, String localNumber)
throws InvalidNumberException
{
if (number.contains("@")) {
throw new InvalidNumberException("Possible attempt to use email address.");
}
number = number.replaceAll("[^0-9+]", ""); number = number.replaceAll("[^0-9+]", "");
if (number.length() == 0) {
throw new InvalidNumberException("No valid characters found.");
}
if (number.charAt(0) == '+') if (number.charAt(0) == '+')
return number; return number;

View File

@ -48,6 +48,7 @@ import org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent;
import org.whispersystems.textsecure.push.PushServiceSocket; import org.whispersystems.textsecure.push.PushServiceSocket;
import org.whispersystems.textsecure.push.RateLimitException; import org.whispersystems.textsecure.push.RateLimitException;
import org.whispersystems.textsecure.storage.SessionRecordV2; import org.whispersystems.textsecure.storage.SessionRecordV2;
import org.whispersystems.textsecure.util.InvalidNumberException;
import java.io.IOException; import java.io.IOException;
import java.util.LinkedList; import java.util.LinkedList;
@ -86,6 +87,9 @@ public class PushTransport extends BaseTransport {
} catch (RateLimitException e) { } catch (RateLimitException e) {
Log.w("PushTransport", e); Log.w("PushTransport", e);
throw new IOException("Rate limit exceeded."); throw new IOException("Rate limit exceeded.");
} catch (InvalidNumberException e) {
Log.w("PushTransport", e);
throw new IOException("Badly formatted number.");
} }
} }

View File

@ -32,6 +32,7 @@ import org.whispersystems.textsecure.directory.NotInDirectoryException;
import org.whispersystems.textsecure.push.ContactTokenDetails; import org.whispersystems.textsecure.push.ContactTokenDetails;
import org.whispersystems.textsecure.push.PushDestination; import org.whispersystems.textsecure.push.PushDestination;
import org.whispersystems.textsecure.push.PushServiceSocket; import org.whispersystems.textsecure.push.PushServiceSocket;
import org.whispersystems.textsecure.util.InvalidNumberException;
import java.io.IOException; import java.io.IOException;
import java.util.LinkedList; import java.util.LinkedList;
@ -60,6 +61,7 @@ public class UniversalTransport {
return; return;
} }
try {
Recipient recipient = message.getIndividualRecipient(); Recipient recipient = message.getIndividualRecipient();
String number = Util.canonicalizeNumber(context, recipient.getNumber()); String number = Util.canonicalizeNumber(context, recipient.getNumber());
@ -75,6 +77,10 @@ public class UniversalTransport {
Log.w("UniversalTransport", "Delivering with SMS..."); Log.w("UniversalTransport", "Delivering with SMS...");
smsTransport.deliver(message); smsTransport.deliver(message);
} }
} catch (InvalidNumberException e) {
Log.w("UniversalTransport", e);
smsTransport.deliver(message);
}
} }
public MmsSendResult deliver(SendReq mediaMessage, long threadId) public MmsSendResult deliver(SendReq mediaMessage, long threadId)
@ -84,6 +90,7 @@ public class UniversalTransport {
return mmsTransport.deliver(mediaMessage); return mmsTransport.deliver(mediaMessage);
} }
try {
List<PushDestination> destinations = getMediaDestinations(mediaMessage); List<PushDestination> destinations = getMediaDestinations(mediaMessage);
if (isPushTransport(destinations)) { if (isPushTransport(destinations)) {
@ -99,9 +106,15 @@ public class UniversalTransport {
Log.w("UniversalTransport", "Delivering media message with MMS..."); Log.w("UniversalTransport", "Delivering media message with MMS...");
return mmsTransport.deliver(mediaMessage); return mmsTransport.deliver(mediaMessage);
} }
} catch (InvalidNumberException e) {
Log.w("UniversalTransport", e);
return mmsTransport.deliver(mediaMessage);
}
} }
private List<PushDestination> getMediaDestinations(SendReq mediaMessage) { private List<PushDestination> getMediaDestinations(SendReq mediaMessage)
throws InvalidNumberException
{
TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance(); TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance();
LinkedList<PushDestination> destinations = new LinkedList<PushDestination>(); LinkedList<PushDestination> destinations = new LinkedList<PushDestination>();

View File

@ -27,6 +27,7 @@ import android.os.Build;
import android.provider.Telephony; import android.provider.Telephony;
import org.thoughtcrime.securesms.mms.MmsRadio; import org.thoughtcrime.securesms.mms.MmsRadio;
import org.whispersystems.textsecure.util.InvalidNumberException;
import org.whispersystems.textsecure.util.PhoneNumberFormatter; import org.whispersystems.textsecure.util.PhoneNumberFormatter;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -122,7 +123,9 @@ public class Util {
} }
} }
public static String canonicalizeNumber(Context context, String number) { public static String canonicalizeNumber(Context context, String number)
throws InvalidNumberException
{
String localNumber = TextSecurePreferences.getLocalNumber(context); String localNumber = TextSecurePreferences.getLocalNumber(context);
return PhoneNumberFormatter.formatNumber(number, localNumber); return PhoneNumberFormatter.formatNumber(number, localNumber);
} }