From 2dab49f0486c267ecc9feb08f75494404fefd4fa Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 25 Mar 2021 09:46:57 +0100 Subject: [PATCH 1/8] Smack 4.4.3-SNAPSHOT --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 1d068c6ec..40d873fca 100644 --- a/version +++ b/version @@ -1 +1 @@ -4.4.2 +4.4.3-SNAPSHOT From 406daa78f79321dcae3c701d6a43952cb06dadb8 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 25 Mar 2021 12:16:04 +0100 Subject: [PATCH 2/8] [javadoc-overview] Use stanza factory in example code --- resources/javadoc-overview.html | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/resources/javadoc-overview.html b/resources/javadoc-overview.html index 1b92b1739..767ba0ea3 100644 --- a/resources/javadoc-overview.html +++ b/resources/javadoc-overview.html @@ -14,7 +14,12 @@ AbstractXMPPConnection connection = new XMPPTCPConnection("mtucker", "password", "jabber.org"); connection.connect().login(); -Message message = new Message("jsmith@igniterealtime.org", "Howdy! How are you?"); +Message message = connection.getStanzaFactory() + .buildMessageStanza() + .to("jsmith@igniterealtime.org") + .setBody("Howdy! How are you?") + .build(); + connection.sendStanza(message); From a39d44ed1ff18bfbe136d0d8b3703adaaa8baf75 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 25 Mar 2021 12:23:19 +0100 Subject: [PATCH 3/8] [javadoc-overview] Improve 'License' section --- resources/javadoc-overview.html | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/resources/javadoc-overview.html b/resources/javadoc-overview.html index 767ba0ea3..79e4c8ce4 100644 --- a/resources/javadoc-overview.html +++ b/resources/javadoc-overview.html @@ -27,7 +27,20 @@ connection.sendStanza(message);

Smack comes with APIs for easy machine-to-machine communication. You can set any number of properties on each message, including properties that are Java objects.

-

Smack is open-source under the Apache License 2.0, which means you can incorporate Smack into your commercial or non-commercial applications.

+

License

+ +

Smack is open-source and most parts are under the Apache License + 2.0, which means you can incorporate Smack into your commercial or + non-commercial applications. Some parts of Smack may be under a + different open-source license. Please refer to the individual + subprojects for their license statement.

+ +

Note that the Apache License 2.0 requires that the contents of a + NOICE text file are shown "…within a display generated by the + Derivative Works, if and wherever such third-party notices normally + appear.". Smack comes with such a NOTICE file. The content of + Smack's NOTICE file can conveniently be retrieved using + {@link org.jivesoftware.smack.Smack#getNoticeStream}.

About XMPP

From 5844bee1c38b38eb7c55fa3e67e8499d519ae84a Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 25 Mar 2021 12:23:39 +0100 Subject: [PATCH 4/8] [javadoc-overview] Disconnect the connection in example code --- resources/javadoc-overview.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/javadoc-overview.html b/resources/javadoc-overview.html index 79e4c8ce4..4f63c64a8 100644 --- a/resources/javadoc-overview.html +++ b/resources/javadoc-overview.html @@ -21,6 +21,8 @@ Message message = connection.getStanzaFactory() .build(); connection.sendStanza(message); + +connection.disconnect();

Smack doesn't force you to code at the protcol level of XMPP. The library provides intelligent higher level constructs, often called {@link org.jivesoftware.smack.Manager}, which let you program more efficiently. Other examples of those constructs are the Chat and Roster classes.

From b58511d624d98f1f3f7b0b87e5b3674f1864d444 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 25 Mar 2021 14:51:25 +0100 Subject: [PATCH 5/8] [core] Also provide incoming Nonzas to SmackDebugger --- .../jivesoftware/smack/AbstractXMPPConnection.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index 92a25b64e..0c2c59a14 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -1406,6 +1406,13 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { return successNonza; } + private void maybeNotifyDebuggerAboutIncoming(TopLevelStreamElement incomingTopLevelStreamElement) { + final SmackDebugger debugger = this.debugger; + if (debugger != null) { + debugger.onIncomingStreamElement(incomingTopLevelStreamElement); + } + } + protected final void parseAndProcessNonza(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException { ParserUtils.assertAtStartTag(parser); @@ -1434,6 +1441,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { Nonza nonza = nonzaProvider.parse(parser, incomingStreamXmlEnvironment); + maybeNotifyDebuggerAboutIncoming(nonza); + for (NonzaCallback nonzaCallback : nonzaCallbacks) { nonzaCallback.onNonzaReceived(nonza); } @@ -1473,10 +1482,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { protected void processStanza(final Stanza stanza) throws InterruptedException { assert stanza != null; - final SmackDebugger debugger = this.debugger; - if (debugger != null) { - debugger.onIncomingStreamElement(stanza); - } + maybeNotifyDebuggerAboutIncoming(stanza); lastStanzaReceived = System.currentTimeMillis(); // Deliver the incoming packet to listeners. From 33d735a42e48dc3b0aa46e9eb4b5995bf639d8af Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 25 Mar 2021 14:58:44 +0100 Subject: [PATCH 6/8] [core] Make Smack.getNoticeStream() more robust Appearently simply calling ClassLoader.getSystemResourceAsStream() works on Java SE but not on Android. But our FileUtils are able to load the resource stream on Android. --- .../java/org/jivesoftware/smack/Smack.java | 18 ++++++++++++++++-- .../org/jivesoftware/smack/util/FileUtils.java | 13 +++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/Smack.java b/smack-core/src/main/java/org/jivesoftware/smack/Smack.java index 690b9bb2d..6608bba4b 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/Smack.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/Smack.java @@ -1,6 +1,6 @@ /** * - * Copyright 2020 Florian Schmaus + * Copyright 2020-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,8 @@ package org.jivesoftware.smack; import java.io.InputStream; import java.util.logging.Logger; +import org.jivesoftware.smack.util.FileUtils; + public class Smack { private static final Logger LOGGER = Logger.getLogger(Smack.class.getName()); @@ -38,8 +40,20 @@ public class Smack { private static final String NOTICE_RESOURCE = SMACK_PACKAGE + "/NOTICE"; + /** + * Get the stream of the NOTICE file of Smack. + *

+ * This license of Smack requires that the contents of this NOTICE text file are shown "…within a display generated by + * the Derivative Works, if and wherever such third-party notices normally appear.". + *

+ * + * @return the stream of the NOTICE file of Smack. + * @since 4.4.0 + */ public static InputStream getNoticeStream() { - return ClassLoader.getSystemResourceAsStream(NOTICE_RESOURCE); + InputStream res = FileUtils.getInputStreamForClasspathFile(NOTICE_RESOURCE); + assert res != null; + return res; } public static void ensureInitialized() { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/FileUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/FileUtils.java index 2cdac90a4..7cb4bd0d9 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/FileUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/FileUtils.java @@ -41,6 +41,19 @@ public final class FileUtils { private static final Logger LOGGER = Logger.getLogger(FileUtils.class.getName()); + public static InputStream getInputStreamForClasspathFile(String path) { + return getInputStreamForClasspathFile(path, null); + } + + public static InputStream getInputStreamForClasspathFile(String path, ClassLoader loader) { + try { + return getStreamForClasspathFile(path, loader); + } catch (IOException e) { + LOGGER.log(Level.FINE, "Suppressed IOException in getInputStreamForClasspathFile", e); + return null; + } + } + public static InputStream getStreamForClasspathFile(String path, ClassLoader loader) throws IOException { // Get an array of class loaders to try loading the providers files from. List classLoaders = getClassLoaders(); From 72e11ebf7167aa24ae3de20eaf87f0e945ae93e0 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 25 Mar 2021 15:00:07 +0100 Subject: [PATCH 7/8] [README] Fix typo; s/NOICE/NOTICE/ --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42a6ebf3c..9d4e4a899 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Instructions on how to use Smack in your Java or Android project are provided in License ------- -Most of Smack is governed by the Apache License 2.0 (SPDX License Identifier: Apache 2.0). This license requires that the contents of a NOICE text file are shown "…within a display generated by the Derivative Works, if and wherever such third-party notices normally appear.". +Most of Smack is governed by the Apache License 2.0 (SPDX License Identifier: Apache 2.0). This license requires that the contents of a NOTICE text file are shown "…within a display generated by the Derivative Works, if and wherever such third-party notices normally appear.". Smack comes which such a NOTICE file. Moreover, since `smack-core` is licensed under the Apache License 2.0, the conditions apply to every project using Smack. The content of Smack's NOTICE file can conveniently be retrieved using `Smack.getNoticeStream()`. From 92f4aadfdc45c144763c2e2a1921c2fa9a6db90b Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 25 Mar 2021 15:01:15 +0100 Subject: [PATCH 8/8] [sasl] Avoid mechanisms that need a password when none is available --- .../smack/SASLAuthentication.java | 38 +++++++++++++------ .../smack/sasl/SASLMechanism.java | 6 ++- .../sasl/javax/SASLExternalMechanism.java | 5 +++ .../sasl/provided/SASLExternalMechanism.java | 4 ++ 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java b/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java index 2e02b5080..6919844f8 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java @@ -42,6 +42,7 @@ import org.jivesoftware.smack.sasl.core.ScramSha1PlusMechanism; import org.jivesoftware.smack.sasl.packet.SaslNonza; import org.jivesoftware.smack.sasl.packet.SaslNonza.SASLFailure; import org.jivesoftware.smack.sasl.packet.SaslNonza.Success; +import org.jivesoftware.smack.util.StringUtils; import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.EntityBareJid; @@ -184,7 +185,7 @@ public final class SASLAuthentication { SASLMechanism authenticate(String username, String password, EntityBareJid authzid, SSLSession sslSession) throws XMPPErrorException, SASLErrorException, IOException, InterruptedException, SmackSaslException, NotConnectedException, NoResponseException { - final SASLMechanism mechanism = selectMechanism(authzid); + final SASLMechanism mechanism = selectMechanism(authzid, password); final CallbackHandler callbackHandler = configuration.getCallbackHandler(); final String host = connection.getHost(); final DomainBareJid xmppServiceDomain = connection.getXMPPServiceDomain(); @@ -312,34 +313,48 @@ public final class SASLAuthentication { return lastUsedMech.getName(); } - private SASLMechanism selectMechanism(EntityBareJid authzid) throws SmackException.SmackSaslException { + private SASLMechanism selectMechanism(EntityBareJid authzid, String password) throws SmackException.SmackSaslException { + final boolean passwordAvailable = StringUtils.isNotEmpty(password); + Iterator it = REGISTERED_MECHANISMS.iterator(); final List serverMechanisms = getServerMechanisms(); if (serverMechanisms.isEmpty()) { LOGGER.warning("Server did not report any SASL mechanisms"); } + + List skipReasons = new ArrayList<>(); + // Iterate in SASL Priority order over registered mechanisms while (it.hasNext()) { SASLMechanism mechanism = it.next(); String mechanismName = mechanism.getName(); + + if (!serverMechanisms.contains(mechanismName)) { + continue; + } + synchronized (BLACKLISTED_MECHANISMS) { if (BLACKLISTED_MECHANISMS.contains(mechanismName)) { continue; } } + if (!configuration.isEnabledSaslMechanism(mechanismName)) { continue; } - if (authzid != null) { - if (!mechanism.authzidSupported()) { - LOGGER.fine("Skipping " + mechanism + " because authzid is required by not supported by this SASL mechanism"); - continue; - } + + if (authzid != null && !mechanism.authzidSupported()) { + skipReasons.add("Skipping " + mechanism + " because authzid is required by not supported by this SASL mechanism"); + continue; } - if (serverMechanisms.contains(mechanismName)) { - // Create a new instance of the SASLMechanism for every authentication attempt. - return mechanism.instanceForAuthentication(connection, configuration); + + if (mechanism.requiresPassword() && !passwordAvailable) { + skipReasons.add("Skipping " + mechanism + " because a password is required for it, but none was provided to the connection configuration"); + continue; } + + // Create a new instance of the SASLMechanism for every authentication attempt. + return mechanism.instanceForAuthentication(connection, configuration); } synchronized (BLACKLISTED_MECHANISMS) { @@ -349,7 +364,8 @@ public final class SASLAuthentication { "Server announced mechanisms: " + serverMechanisms + ". " + "Registered SASL mechanisms with Smack: " + REGISTERED_MECHANISMS + ". " + "Enabled SASL mechanisms for this connection: " + configuration.getEnabledSaslMechanisms() + ". " + - "Blacklisted SASL mechanisms: " + BLACKLISTED_MECHANISMS + '.' + "Blacklisted SASL mechanisms: " + BLACKLISTED_MECHANISMS + ". " + + "Skip reasons: " + skipReasons ); // @formatter;on } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java b/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java index e821e8e91..f1c00ef19 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2014-2019 Florian Schmaus + * Copyright 2003-2007 Jive Software, 2014-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -311,6 +311,10 @@ public abstract class SASLMechanism implements Comparable { return false; } + public boolean requiresPassword() { + return true; + } + public boolean isAuthenticationSuccessful() { return authenticationSuccessful; } diff --git a/smack-sasl-javax/src/main/java/org/jivesoftware/smack/sasl/javax/SASLExternalMechanism.java b/smack-sasl-javax/src/main/java/org/jivesoftware/smack/sasl/javax/SASLExternalMechanism.java index 83500d5c1..d0f24e537 100644 --- a/smack-sasl-javax/src/main/java/org/jivesoftware/smack/sasl/javax/SASLExternalMechanism.java +++ b/smack-sasl-javax/src/main/java/org/jivesoftware/smack/sasl/javax/SASLExternalMechanism.java @@ -65,4 +65,9 @@ public class SASLExternalMechanism extends SASLJavaXMechanism { public SASLExternalMechanism newInstance() { return new SASLExternalMechanism(); } + + @Override + public boolean requiresPassword() { + return false; + } } diff --git a/smack-sasl-provided/src/main/java/org/jivesoftware/smack/sasl/provided/SASLExternalMechanism.java b/smack-sasl-provided/src/main/java/org/jivesoftware/smack/sasl/provided/SASLExternalMechanism.java index cf5fea0af..f1cd947d4 100644 --- a/smack-sasl-provided/src/main/java/org/jivesoftware/smack/sasl/provided/SASLExternalMechanism.java +++ b/smack-sasl-provided/src/main/java/org/jivesoftware/smack/sasl/provided/SASLExternalMechanism.java @@ -76,4 +76,8 @@ public class SASLExternalMechanism extends SASLMechanism { return true; } + @Override + public boolean requiresPassword() { + return false; + } }