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