From fdfaae6f59496834e31f2081ce4602b9b31330b1 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Tue, 7 Apr 2020 20:08:25 +0200 Subject: fix resolving IP if SRV violences RFC2782 --- .../java/de/pixart/messenger/utils/Resolver.java | 46 +++++++++++++++++---- .../de/pixart/messenger/xmpp/XmppConnection.java | 48 ++++++++++++++-------- 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 list = resolveNoSrvRecords(DNSName.from(domain), DEFAULT_PORT_XMPP, true); - synchronized (fallbackResults) { - fallbackResults.addAll(list); + try { + final List 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 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 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 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 { -- cgit v1.2.3