IoT: Prevent control/read-out from non friends

and make the behavior configurable.
This commit is contained in:
Florian Schmaus 2016-11-17 10:25:35 +01:00
parent 6d74d0383c
commit da58b20b53
4 changed files with 69 additions and 33 deletions

View File

@ -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<XMPPConnection, IoTManager> 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);
}
}

View File

@ -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 <flo@geekplace.eu>}
* @see <a href="http://xmpp.org/extensions/xep-0325.html">XEP-0323: Internet of Things - Control</a>
*/
public final class IoTControlManager extends Manager {
public final class IoTControlManager extends IoTManager {
private static final Map<XMPPConnection, IoTControlManager> 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

View File

@ -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 <flo@geekplace.eu>}
* @see <a href="http://xmpp.org/extensions/xep-0323.html">XEP-0323: Internet of Things - Sensor Data</a>
*/
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()) {

View File

@ -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);