don't perform dns lookups on domain parts that obviously look like ip addresses

This commit is contained in:
Daniel Gultsch 2015-06-19 16:25:08 +02:00
parent 58201b4408
commit 5a48afdd4d
2 changed files with 68 additions and 54 deletions

View file

@ -20,11 +20,19 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Random; import java.util.Random;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.regex.Pattern;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
public class DNSHelper { public class DNSHelper {
public static final Pattern PATTERN_IPV4 = Pattern.compile("\\A(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z");
public static final Pattern PATTERN_IPV6_HEX4DECCOMPRESSED = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::((?:[0-9A-Fa-f]{1,4}:)*)(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z");
public static final Pattern PATTERN_IPV6_6HEX4DEC = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}:){6,6})(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z");
public static final Pattern PATTERN_IPV6_HEXCOMPRESSED = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)\\z");
public static final Pattern PATTERN_IPV6 = Pattern.compile("\\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\z");
protected static Client client = new Client(); protected static Client client = new Client();
public static Bundle getSRVRecord(final Jid jid) throws IOException { public static Bundle getSRVRecord(final Jid jid) throws IOException {
@ -160,15 +168,11 @@ public class DNSHelper {
return namePort; return namePort;
} }
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static boolean isIp(final String server) {
return PATTERN_IPV4.matcher(server).matches()
public static String bytesToHex(byte[] bytes) { || PATTERN_IPV6.matcher(server).matches()
char[] hexChars = new char[bytes.length * 2]; || PATTERN_IPV6_6HEX4DEC.matcher(server).matches()
for (int j = 0; j < bytes.length; j++) { || PATTERN_IPV6_HEX4DECCOMPRESSED.matcher(server).matches()
int v = bytes[j] & 0xFF; || PATTERN_IPV6_HEXCOMPRESSED.matcher(server).matches();
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
} }
} }

View file

@ -26,6 +26,7 @@ import java.net.IDN;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -155,53 +156,62 @@ public class XmppConnection implements Runnable {
tagWriter = new TagWriter(); tagWriter = new TagWriter();
packetCallbacks.clear(); packetCallbacks.clear();
this.changeStatus(Account.State.CONNECTING); this.changeStatus(Account.State.CONNECTING);
final Bundle result = DNSHelper.getSRVRecord(account.getServer()); if (DNSHelper.isIp(account.getServer().toString())) {
final ArrayList<Parcelable> values = result.getParcelableArrayList("values"); socket = new Socket();
if ("timeout".equals(result.getString("error"))) { try {
throw new IOException("timeout in dns"); socket.connect(new InetSocketAddress(account.getServer().toString(), 5222), Config.SOCKET_TIMEOUT * 1000);
} else if (values != null) { } catch (IOException e) {
int i = 0;
boolean socketError = true;
while (socketError && values.size() > i) {
final Bundle namePort = (Bundle) values.get(i);
try {
String srvRecordServer;
try {
srvRecordServer = IDN.toASCII(namePort.getString("name"));
} catch (final IllegalArgumentException e) {
// TODO: Handle me?`
srvRecordServer = "";
}
final int srvRecordPort = namePort.getInt("port");
final String srvIpServer = namePort.getString("ip");
final InetSocketAddress addr;
if (srvIpServer != null) {
addr = new InetSocketAddress(srvIpServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
+ ": using values from dns " + srvRecordServer
+ "[" + srvIpServer + "]:" + srvRecordPort);
} else {
addr = new InetSocketAddress(srvRecordServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
+ ": using values from dns "
+ srvRecordServer + ":" + srvRecordPort);
}
socket = new Socket();
socket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
socketError = false;
} catch (final UnknownHostException e) {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
i++;
} catch (final IOException e) {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
i++;
}
}
if (socketError) {
throw new UnknownHostException(); throw new UnknownHostException();
} }
} else { } else {
throw new IOException("unhandled exception in DNS resolver"); final Bundle result = DNSHelper.getSRVRecord(account.getServer());
final ArrayList<Parcelable> values = result.getParcelableArrayList("values");
if ("timeout".equals(result.getString("error"))) {
throw new IOException("timeout in dns");
} else if (values != null) {
int i = 0;
boolean socketError = true;
while (socketError && values.size() > i) {
final Bundle namePort = (Bundle) values.get(i);
try {
String srvRecordServer;
try {
srvRecordServer = IDN.toASCII(namePort.getString("name"));
} catch (final IllegalArgumentException e) {
// TODO: Handle me?`
srvRecordServer = "";
}
final int srvRecordPort = namePort.getInt("port");
final String srvIpServer = namePort.getString("ip");
final InetSocketAddress addr;
if (srvIpServer != null) {
addr = new InetSocketAddress(srvIpServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
+ ": using values from dns " + srvRecordServer
+ "[" + srvIpServer + "]:" + srvRecordPort);
} else {
addr = new InetSocketAddress(srvRecordServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
+ ": using values from dns "
+ srvRecordServer + ":" + srvRecordPort);
}
socket = new Socket();
socket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
socketError = false;
} catch (final UnknownHostException e) {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
i++;
} catch (final IOException e) {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
i++;
}
}
if (socketError) {
throw new UnknownHostException();
}
} else {
throw new IOException("unhandled exception in DNS resolver");
}
} }
final OutputStream out = socket.getOutputStream(); final OutputStream out = socket.getOutputStream();
tagWriter.setOutputStream(out); tagWriter.setOutputStream(out);