From da58b20b534113e6b945d475d8a621e336dc52b8 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Thu, 17 Nov 2016 10:25:35 +0100 Subject: [PATCH] IoT: Prevent control/read-out from non friends and make the behavior configurable. --- .../jivesoftware/smackx/iot/IoTManager.java | 61 +++++++++++++++---- .../smackx/iot/control/IoTControlManager.java | 12 ++-- .../smackx/iot/data/IoTDataManager.java | 12 ++-- .../provisioning/IoTProvisioningManager.java | 17 ++++-- 4 files changed, 69 insertions(+), 33 deletions(-) diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/IoTManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/IoTManager.java index 276d2cb3e..eb8b78ac4 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/IoTManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/IoTManager.java @@ -16,27 +16,62 @@ */ package org.jivesoftware.smackx.iot; -import java.util.Map; -import java.util.WeakHashMap; +import java.util.logging.Logger; import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IQ.Type; +import org.jivesoftware.smackx.iot.provisioning.IoTProvisioningManager; +import org.jxmpp.jid.Jid; -public final class IoTManager extends Manager { +public abstract class IoTManager extends Manager { - private static final Map INSTANCES = new WeakHashMap<>(); + private static final Logger LOGGER = Logger.getLogger(IoTManager.class.getName()); - public static synchronized IoTManager getInstanceFor(XMPPConnection connection) { - IoTManager manager = INSTANCES.get(connection); - if (manager == null) { - manager = new IoTManager(connection); - INSTANCES.put(connection, manager); - } - return manager; - } + private final IoTProvisioningManager ioTProvisioningManager; - private IoTManager(XMPPConnection connection) { + private boolean allowNonFriends; + + protected IoTManager(XMPPConnection connection) { super(connection); + + ioTProvisioningManager = IoTProvisioningManager.getInstanceFor(connection); } + /** + * Set whether or not non friends should be able to use the services provided by this manager. Those non-friend + * entities still need to know the full JID for IQ based requests. + * + * @param allowNonFriends true to allow everyone to use the services. + */ + public void setAllowNonFriends(boolean allowNonFriends) { + this.allowNonFriends = allowNonFriends; + } + + protected boolean isAllowed(Jid jid) { + if (allowNonFriends) return true; + + return ioTProvisioningManager.isMyFriend(jid); + } + + protected abstract class IoTIqRequestHandler extends AbstractIqRequestHandler { + + protected IoTIqRequestHandler(String element, String namespace, Type type, Mode mode) { + super(element, namespace, type, mode); + } + + @Override + public final IQ handleIQRequest(IQ iqRequest) { + if (!isAllowed(iqRequest.getFrom())) { + LOGGER.warning("Ignoring IQ request " + iqRequest); + return null; + } + + return handleIoTIqRequest(iqRequest); + } + + protected abstract IQ handleIoTIqRequest(IQ iqRequest); + } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/IoTControlManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/IoTControlManager.java index a1fd4f7c9..e7fa9abf5 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/IoTControlManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/IoTControlManager.java @@ -22,14 +22,13 @@ import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; -import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException.XMPPErrorException; -import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler; import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode; import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smackx.iot.IoTManager; import org.jivesoftware.smackx.iot.Thing; import org.jivesoftware.smackx.iot.control.element.IoTSetRequest; import org.jivesoftware.smackx.iot.control.element.IoTSetResponse; @@ -43,7 +42,7 @@ import org.jxmpp.jid.FullJid; * @author Florian Schmaus {@literal } * @see XEP-0323: Internet of Things - Control */ -public final class IoTControlManager extends Manager { +public final class IoTControlManager extends IoTManager { private static final Map INSTANCES = new WeakHashMap<>(); @@ -66,9 +65,10 @@ public final class IoTControlManager extends Manager { private IoTControlManager(XMPPConnection connection) { super(connection); - connection.registerIQRequestHandler(new AbstractIqRequestHandler(IoTSetRequest.ELEMENT, IoTSetRequest.NAMESPACE, IQ.Type.set, Mode.async) { + + connection.registerIQRequestHandler(new IoTIqRequestHandler(IoTSetRequest.ELEMENT, IoTSetRequest.NAMESPACE, IQ.Type.set, Mode.async) { @Override - public IQ handleIQRequest(IQ iqRequest) { + public IQ handleIoTIqRequest(IQ iqRequest) { // TODO Lookup thing and provide data. IoTSetRequest iotSetRequest = (IoTSetRequest) iqRequest; @@ -101,7 +101,7 @@ public final class IoTControlManager extends Manager { * * @param jid * @param data - * @return + * @return a IoTSetResponse * @throws NoResponseException * @throws XMPPErrorException * @throws NotConnectedException diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/IoTDataManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/IoTDataManager.java index 065893121..2602927d5 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/IoTDataManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/IoTDataManager.java @@ -26,7 +26,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.jivesoftware.smack.ConnectionCreationListener; -import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.PacketCollector; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; @@ -34,10 +33,10 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.filter.StanzaFilter; -import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler; import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smackx.iot.IoTManager; import org.jivesoftware.smackx.iot.Thing; import org.jivesoftware.smackx.iot.data.element.IoTDataField; import org.jivesoftware.smackx.iot.data.element.IoTDataReadOutAccepted; @@ -53,7 +52,7 @@ import org.jxmpp.jid.EntityFullJid; * @author Florian Schmaus {@literal } * @see XEP-0323: Internet of Things - Sensor Data */ -public final class IoTDataManager extends Manager { +public final class IoTDataManager extends IoTManager { private static final Logger LOGGER = Logger.getLogger(IoTDataManager.class.getName()); @@ -89,13 +88,10 @@ public final class IoTDataManager extends Manager { private IoTDataManager(XMPPConnection connection) { super(connection); - - connection.registerIQRequestHandler(new AbstractIqRequestHandler(IoTDataRequest.ELEMENT, + connection.registerIQRequestHandler(new IoTIqRequestHandler(IoTDataRequest.ELEMENT, IoTDataRequest.NAMESPACE, IQ.Type.get, Mode.async) { @Override - public IQ handleIQRequest(IQ iqRequest) { - // TODO Verify that iqRequest.from is friend? - + public IQ handleIoTIqRequest(IQ iqRequest) { final IoTDataRequest dataRequest = (IoTDataRequest) iqRequest; if (!dataRequest.isMomentary()) { diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/IoTProvisioningManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/IoTProvisioningManager.java index 2f4d855e9..33196beb2 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/IoTProvisioningManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/IoTProvisioningManager.java @@ -350,6 +350,13 @@ public final class IoTProvisioningManager extends Manager { return isFriend; } + public boolean iAmFriendOf(BareJid otherJid) { + RosterEntry entry = roster.getEntry(otherJid); + if (entry == null) return false; + + return entry.canSeeHisPresence(); + } + public void sendFriendshipRequest(BareJid bareJid) throws NotConnectedException, InterruptedException { Presence presence = new Presence(Presence.Type.subscribe); presence.setTo(bareJid); @@ -360,19 +367,17 @@ public final class IoTProvisioningManager extends Manager { } public void sendFriendshipRequestIfRequired(BareJid jid) throws NotConnectedException, InterruptedException { - RosterEntry entry = roster.getEntry(jid); - if (entry != null && entry.canSeeHisPresence()) { - return; - } + if (iAmFriendOf(jid)) return; + sendFriendshipRequest(jid); } - public boolean isBefriended(Jid friendInQuestion) { + public boolean isMyFriend(Jid friendInQuestion) { return roster.isSubscribedToMyPresence(friendInQuestion); } public void unfriend(Jid friend) throws NotConnectedException, InterruptedException { - if (isBefriended(friend)) { + if (isMyFriend(friend)) { Presence presence = new Presence(Presence.Type.unsubscribed); presence.setTo(friend); connection().sendStanza(presence);