From fbb662365a064889da25ce2c705568ca31f27af1 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Wed, 24 Jan 2018 14:04:32 +0300 Subject: xmpp: SASL EXTERNAL --- .../java/com/juick/server/xmpp/s2s/Connection.java | 19 +++++++++++++++ .../com/juick/server/xmpp/s2s/ConnectionIn.java | 27 ++++++++++++++++++---- .../com/juick/server/xmpp/s2s/ConnectionOut.java | 25 ++++++++++++++++++-- 3 files changed, 64 insertions(+), 7 deletions(-) (limited to 'juick-server/src/main/java/com/juick/server/xmpp') diff --git a/juick-server/src/main/java/com/juick/server/xmpp/s2s/Connection.java b/juick-server/src/main/java/com/juick/server/xmpp/s2s/Connection.java index 6bf61169..4fa8e741 100644 --- a/juick-server/src/main/java/com/juick/server/xmpp/s2s/Connection.java +++ b/juick-server/src/main/java/com/juick/server/xmpp/s2s/Connection.java @@ -50,11 +50,14 @@ public class Connection { private Socket socket; public static final String NS_DB = "jabber:server:dialback"; public static final String NS_TLS = "urn:ietf:params:xml:ns:xmpp-tls"; + public static final String NS_SASL = "urn:ietf:params:xml:ns:xmpp-sasl"; public static final String NS_STREAM = "http://etherx.jabber.org/streams"; XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newPullParser(); OutputStreamWriter writer; private boolean secured = false; + private boolean authenticated = false; + private boolean trusted = false; @@ -136,4 +139,20 @@ public class Connection { public void setSocket(Socket socket) { this.socket = socket; } + + public boolean isAuthenticated() { + return authenticated; + } + + public void setAuthenticated(boolean authenticated) { + this.authenticated = authenticated; + } + + public boolean isTrusted() { + return trusted; + } + + public void setTrusted(boolean trusted) { + this.trusted = trusted; + } } diff --git a/juick-server/src/main/java/com/juick/server/xmpp/s2s/ConnectionIn.java b/juick-server/src/main/java/com/juick/server/xmpp/s2s/ConnectionIn.java index 9ee81d4d..414c6d8b 100644 --- a/juick-server/src/main/java/com/juick/server/xmpp/s2s/ConnectionIn.java +++ b/juick-server/src/main/java/com/juick/server/xmpp/s2s/ConnectionIn.java @@ -34,6 +34,7 @@ import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; /** * @author ugnich @@ -118,11 +119,12 @@ public class ConnectionIn extends Connection implements Runnable { if (valid[0]) { sendStanza(""); logger.debug("stream from {} {} dialback verify valid", vfrom, streamID); + setAuthenticated(true); } else { sendStanza(""); logger.warn("stream from {} {} dialback verify invalid", vfrom, streamID); } - } else if (tag.equals("presence") && checkFromTo(parser)) { + } else if (tag.equals("presence") && checkFromTo(parser) && isAuthenticated()) { String xml = XmlUtils.parseToString(parser, false); logger.debug("stream {} presence: {}", streamID, xml); xmpp.onStanzaReceived(xml); @@ -132,7 +134,7 @@ public class ConnectionIn extends Connection implements Runnable { logger.debug("stream {} message: {}", streamID, xml); xmpp.onStanzaReceived(xml); - } else if (tag.equals("iq") && checkFromTo(parser)) { + } else if (tag.equals("iq") && checkFromTo(parser) && isAuthenticated()) { updateTsRemoteData(); String type = parser.getAttributeValue(null, "type"); String xml = XmlUtils.parseToString(parser, false); @@ -140,10 +142,18 @@ public class ConnectionIn extends Connection implements Runnable { logger.debug("stream {} iq: {}", streamID, xml); xmpp.onStanzaReceived(xml); } - } else if (!isSecured() && tag.equals("starttls")) { + } else if (!isSecured() && tag.equals("starttls") && !isAuthenticated()) { listener.starttls(this); } else if (isSecured() && tag.equals("stream") && parser.getNamespace().equals(NS_STREAM)) { sendOpenStream(null, true); + } else if (isSecured() && tag.equals("auth") && parser.getNamespace().equals(NS_SASL) + && parser.getAttributeValue(null, "mechanism").equals("EXTERNAL") + && !isAuthenticated() && isTrusted()) { + sendStanza(""); + logger.info("stream {} authenticated externally", streamID); + this.from.add(Jid.of(from)); + setAuthenticated(true); + restartParser(); } else if (tag.equals("error")) { StreamError streamError = StreamError.parse(parser); logger.debug("Stream error from {}: {}", streamID, streamError.getCondition()); @@ -178,8 +188,14 @@ public class ConnectionIn extends Connection implements Runnable { xmpp.getJid().toEscapedString() + "' id='" + streamID + "' version='1.0'>"; if (xmppversionnew) { openStream += ""; - if (listener != null && listener.isTlsAvailable() && !isSecured() && !Arrays.asList(xmpp.brokenSSLhosts).contains(from)) { - openStream += ""; + if (listener != null && listener.isTlsAvailable() && !Arrays.asList(xmpp.brokenSSLhosts).contains(from)) { + if (!isSecured()) { + openStream += ""; + } else if (!isAuthenticated() && isTrusted()) { + openStream += "" + + "EXTERNAL" + + ""; + } } openStream += ""; } @@ -205,6 +221,7 @@ public class ConnectionIn extends Connection implements Runnable { } } } + logger.warn("rejected from {}, to {}, stream {}", cfrom, cto, from.stream().collect(Collectors.joining(","))); return false; } public void setListener(ConnectionListener listener) { diff --git a/juick-server/src/main/java/com/juick/server/xmpp/s2s/ConnectionOut.java b/juick-server/src/main/java/com/juick/server/xmpp/s2s/ConnectionOut.java index e3bd53e9..0c991553 100644 --- a/juick-server/src/main/java/com/juick/server/xmpp/s2s/ConnectionOut.java +++ b/juick-server/src/main/java/com/juick/server/xmpp/s2s/ConnectionOut.java @@ -22,6 +22,8 @@ import com.juick.xmpp.Stream; import com.juick.xmpp.extensions.StreamError; import com.juick.xmpp.extensions.StreamFeatures; import com.juick.xmpp.utils.XmlUtils; +import org.apache.commons.codec.Charsets; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.text.RandomStringGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +37,8 @@ import java.io.OutputStream; import java.net.SocketException; import java.util.UUID; +import static com.juick.server.xmpp.s2s.Connection.NS_SASL; + /** * @author ugnich */ @@ -43,7 +47,7 @@ public class ConnectionOut extends Stream { public static final String NS_TLS = "urn:ietf:params:xml:ns:xmpp-tls"; public static final String NS_DB = "jabber:server:dialback"; private boolean secured = false; - + private boolean trusted = false; public boolean streamReady = false; String checkSID = null; String dbKey = null; @@ -122,18 +126,27 @@ public class ConnectionOut extends Stream { && listener.securing(this)) { logger.debug("stream to {} {} securing", to.toEscapedString(), streamID); send(""); + } else if (secured && features.EXTERNAL >=0) { + String authid = Base64.encodeBase64String(from.toEscapedString().getBytes(Charsets.UTF_8)); + send(String.format("%s", authid)); + } else if (secured && streamReady) { + listener.ready(this); } else { processDialback(); } } else if (tag.equals("proceed") && parser.getNamespace().equals(NS_TLS)) { listener.proceed(this); + } else if (tag.equals("success") && parser.getNamespace().equals(NS_SASL)) { + streamReady = true; + restartStream(); + sendOpenStream(); } else if (secured && tag.equals("stream") && parser.getNamespace().equals(NS_STREAM)) { streamID = parser.getAttributeValue(null, "id"); } else if (tag.equals("error")) { StreamError streamError = StreamError.parse(parser); listener.dialbackError(this, streamError); } else { - String unhandledStanza = XmlUtils.parseToString(parser, true); + String unhandledStanza = XmlUtils.parseToString(parser, false); logger.warn("Unhandled stanza from {} {} : {}", to, streamID, unhandledStanza); } } @@ -164,4 +177,12 @@ public class ConnectionOut extends Stream { public void setSecured(boolean secured) { this.secured = secured; } + + public boolean isTrusted() { + return trusted; + } + + public void setTrusted(boolean trusted) { + this.trusted = trusted; + } } -- cgit v1.2.3