aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schneppe <christian.schneppe@pix-art.de>2020-04-07 20:08:25 +0200
committerChristian Schneppe <christian.schneppe@pix-art.de>2020-04-07 20:08:25 +0200
commitfdfaae6f59496834e31f2081ce4602b9b31330b1 (patch)
tree50db953c76c62f692c61cbfa45156a23a962b4d7
parente2c2ee6507f32f14d82ed147a160f529caa1cd71 (diff)
fix resolving IP if SRV violences RFC2782
-rw-r--r--src/main/java/de/pixart/messenger/utils/Resolver.java46
-rw-r--r--src/main/java/de/pixart/messenger/xmpp/XmppConnection.java48
2 files changed, 69 insertions, 25 deletions
diff --git a/src/main/java/de/pixart/messenger/utils/Resolver.java b/src/main/java/de/pixart/messenger/utils/Resolver.java
index a7c286cc7..aa05043e7 100644
--- a/src/main/java/de/pixart/messenger/utils/Resolver.java
+++ b/src/main/java/de/pixart/messenger/utils/Resolver.java
@@ -128,9 +128,13 @@ public class Resolver {
}
});
threads[2] = new Thread(() -> {
- List<Result> list = resolveNoSrvRecords(DNSName.from(domain), DEFAULT_PORT_XMPP, true);
- synchronized (fallbackResults) {
- fallbackResults.addAll(list);
+ try {
+ final List<Result> list = resolveNoSrvRecords(DNSName.from(domain), DEFAULT_PORT_XMPP, true);
+ synchronized (fallbackResults) {
+ fallbackResults.addAll(list);
+ }
+ } catch (Throwable throwable) {
+ Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": resolving no SRV record (STARTTLS)", throwable);
}
});
for (Thread thread : threads) {
@@ -187,7 +191,7 @@ public class Resolver {
final List<Thread> fallbackThreads = new ArrayList<>();
for (SRV record : result.getAnswersOrEmptySet()) {
- if (record.name.length() == 0) {
+ if (record.name.length() == 0 && record.priority == 0) {
continue;
}
threads.add(new Thread(() -> {
@@ -198,6 +202,11 @@ public class Resolver {
}));
threads.add(new Thread(() -> {
final List<Result> ipv4s = resolveIp(record, A.class, result.isAuthenticData(), directTls);
+ if (ipv4s.size() == 0) {
+ Result resolverResult = Result.fromRecord(record, directTls);
+ resolverResult.authenticated = result.isAuthenticData();
+ ipv4s.add(resolverResult);
+ }
synchronized (results) {
results.addAll(ipv4s);
}
@@ -211,13 +220,13 @@ public class Resolver {
fallbackResults.addAll(ipv6s);
}
final List<Result> ipv4s = resolveIp(record, cname.name, A.class, cnames.isAuthenticData(), directTls);
- synchronized (results) {
+ synchronized (fallbackResults) {
fallbackResults.addAll(ipv4s);
}
}
- Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + "cname in srv (agains RFC2782) - run slow fallback");
+ Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + " cname in srv (against RFC2782) - run slow fallback");
} catch (Throwable throwable) {
- Log.i(Config.LOGTAG, Resolver.class.getSimpleName() + "error resolving srv cname-fallback records", throwable);
+ Log.i(Config.LOGTAG, Resolver.class.getSimpleName() + " error resolving srv cname-fallback records", throwable);
}
}));
}
@@ -285,6 +294,7 @@ public class Resolver {
} catch (Throwable throwable) {
Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + "error resolving fallback records", throwable);
}
+ results.add(Result.createDefault(dnsName, port));
return results;
}
@@ -315,7 +325,7 @@ public class Resolver {
if (r.size() == 0) return null;
Result result;
- if (r.size() == 1) {
+ if (r.size() == 1 && r.get(0).ip != null) {
result = r.get(0);
result.setLogID(logID);
result.connect();
@@ -387,11 +397,27 @@ public class Resolver {
result.timeRequested = System.currentTimeMillis();
result.port = srv.port;
result.hostname = srv.name;
+ try {
+ result.ip = InetAddress.getByName(result.hostname.toString());
+ } catch (UnknownHostException e) {
+ result.ip = null;
+ e.printStackTrace();
+ }
result.directTls = directTls;
result.priority = srv.priority;
return result;
}
+ static Result createDefault(final DNSName hostname, final int port) {
+ InetAddress ip = null;
+ try {
+ ip = InetAddress.getByName(hostname.toString());
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+ return createDefault(hostname, ip, port);
+ }
+
static Result createDefault(final DNSName hostname, final InetAddress ip, final int port) {
Result result = new Result();
result.timeRequested = System.currentTimeMillis();
@@ -464,6 +490,10 @@ public class Resolver {
if (this.socket != null) {
this.disconnect();
}
+ if (this.ip == null || this.port == 0) {
+ Log.d(Config.LOGTAG, "Resolver did not get IP:port (" + this.ip + ":" + this.port + ")");
+ return;
+ }
final InetSocketAddress addr = new InetSocketAddress(this.ip, this.port);
this.socket = new Socket();
try {
diff --git a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
index a41924e08..05b5bc73e 100644
--- a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
+++ b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
@@ -18,7 +18,6 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;
-import java.net.IDN;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
@@ -317,20 +316,35 @@ public class XmppConnection implements Runnable {
}
} else {
final String domain = account.getJid().getDomain();
- final Resolver.Result storedBackupResult = mXmppConnectionService.databaseBackend.findResolverResult(domain);
- Resolver.Result result = null;
+ Resolver.Result results;
final boolean hardcoded = extended && !account.getHostname().isEmpty();
if (hardcoded) {
- result = Resolver.fromHardCoded(account.getHostname(), account.getPort());
- } else if (storedBackupResult != null && !storedBackupResult.isOutdated()) {
- storedBackupResult.connect();
- result = storedBackupResult;
- Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": loaded backup resolver result from db: " + storedBackupResult);
+ results = Resolver.fromHardCoded(account.getHostname(), account.getPort());
+ } else {
+ results = Resolver.resolve(domain);
+ }
+ if (Thread.currentThread().isInterrupted()) {
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": Thread was interrupted");
+ return;
+ }
+ if (results == null) {
+ Log.e(Config.LOGTAG,account.getJid().asBareJid()+": Resolver results were empty");
+ return;
+ }
+ final Resolver.Result storedBackupResult;
+ if (hardcoded) {
+ storedBackupResult = null;
+ } else {
+ storedBackupResult = mXmppConnectionService.databaseBackend.findResolverResult(domain);
+ if (storedBackupResult != null && results != storedBackupResult && !storedBackupResult.isOutdated()) {
+ results = storedBackupResult;
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": loaded backup resolver result from db: " + storedBackupResult);
+ }
}
- if (result == null || result.getSocket() == null) {
- result = Resolver.resolve(domain);
+ if (results == null || results.getSocket() == null) {
+ results = Resolver.resolve(domain);
}
- if (result == null) {
+ if (results == null) {
throw new UnknownHostException();
}
if (Thread.currentThread().isInterrupted()) {
@@ -339,13 +353,13 @@ public class XmppConnection implements Runnable {
}
try {
// if tls is true, encryption is implied and must not be started
- features.encryptionEnabled = result.isDirectTls();
- verifiedHostname = result.isAuthenticated() ? result.getHostname().toString() : null;
+ features.encryptionEnabled = results.isDirectTls();
+ verifiedHostname = results.isAuthenticated() ? results.getHostname().toString() : null;
Log.d(Config.LOGTAG,"verified hostname " + verifiedHostname);
Log.d(Config.LOGTAG, account.getJid().asBareJid().toString()
- + ": using values from resolver " + result.toString());
+ + ": using values from resolver " + results.toString());
- localSocket = result.getSocket();
+ localSocket = results.getSocket();
if (features.encryptionEnabled) {
localSocket = upgradeSocketToTls(localSocket);
@@ -354,8 +368,8 @@ public class XmppConnection implements Runnable {
localSocket.setSoTimeout(Config.SOCKET_TIMEOUT * 1000);
if (startXmpp(localSocket)) {
localSocket.setSoTimeout(0); //reset to 0; once the connection is established we don’t want this
- if (!hardcoded && !result.equals(storedBackupResult)) {
- mXmppConnectionService.databaseBackend.saveResolverResult(domain, result);
+ if (!hardcoded && !results.equals(storedBackupResult)) {
+ mXmppConnectionService.databaseBackend.saveResolverResult(domain, results);
}
// successfully connected to server that speaks xmpp
} else {