Commit 2b0ca427 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Added blocking communication support. JM-102

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3423 b35dd754-fafc-0310-a699-88a17e54d16e
parent 04301ce7
...@@ -12,16 +12,18 @@ ...@@ -12,16 +12,18 @@
package org.jivesoftware.wildfire; package org.jivesoftware.wildfire;
import org.dom4j.io.XMPPPacketReader; import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.auth.AuthToken; import org.jivesoftware.wildfire.auth.AuthToken;
import org.jivesoftware.wildfire.auth.UnauthorizedException; import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.net.SASLAuthentication; import org.jivesoftware.wildfire.net.SASLAuthentication;
import org.jivesoftware.wildfire.net.SocketConnection; import org.jivesoftware.wildfire.net.SocketConnection;
import org.jivesoftware.wildfire.privacy.PrivacyList;
import org.jivesoftware.wildfire.privacy.PrivacyListManager;
import org.jivesoftware.wildfire.user.User; import org.jivesoftware.wildfire.user.User;
import org.jivesoftware.wildfire.user.UserManager; import org.jivesoftware.wildfire.user.UserManager;
import org.jivesoftware.wildfire.user.UserNotFoundException; import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
...@@ -96,6 +98,17 @@ public class ClientSession extends Session { ...@@ -96,6 +98,17 @@ public class ClientSession extends Session {
private int conflictCount = 0; private int conflictCount = 0;
/**
* Privacy list that overrides the default privacy list. This list affects only this
* session and only for the duration of the session.
*/
private PrivacyList activeList;
/**
* Default privacy list used for the session's user. This list is processed if there
* is no active list set for the session.
*/
private PrivacyList defaultList;
static { static {
// Fill out the allowedIPs with the system property // Fill out the allowedIPs with the system property
String allowed = JiveGlobals.getProperty("xmpp.client.login.allowed", ""); String allowed = JiveGlobals.getProperty("xmpp.client.login.allowed", "");
...@@ -380,6 +393,47 @@ public class ClientSession extends Session { ...@@ -380,6 +393,47 @@ public class ClientSession extends Session {
JiveGlobals.setProperty("xmpp.client.compression.policy", compressionPolicy.toString()); JiveGlobals.setProperty("xmpp.client.compression.policy", compressionPolicy.toString());
} }
/**
* Returns the Privacy list that overrides the default privacy list. This list affects
* only this session and only for the duration of the session.
*
* @return the Privacy list that overrides the default privacy list.
*/
public PrivacyList getActiveList() {
return activeList;
}
/**
* Sets the Privacy list that overrides the default privacy list. This list affects
* only this session and only for the duration of the session.
*
* @param activeList the Privacy list that overrides the default privacy list.
*/
public void setActiveList(PrivacyList activeList) {
this.activeList = activeList;
}
/**
* Returns the default Privacy list used for the session's user. This list is
* processed if there is no active list set for the session.
*
* @return the default Privacy list used for the session's user.
*/
public PrivacyList getDefaultList() {
return defaultList;
}
/**
* Sets the default Privacy list used for the session's user. This list is
* processed if there is no active list set for the session.
*
*
* @param defaultList the default Privacy list used for the session's user.
*/
public void setDefaultList(PrivacyList defaultList) {
this.defaultList = defaultList;
}
/** /**
* Returns the number of milliseconds a connection has to be idle to be closed. Default is * Returns the number of milliseconds a connection has to be idle to be closed. Default is
* 30 minutes. Sending stanzas to the client is not considered as activity. We are only * 30 minutes. Sending stanzas to the client is not considered as activity. We are only
...@@ -463,6 +517,9 @@ public class ClientSession extends Session { ...@@ -463,6 +517,9 @@ public class ClientSession extends Session {
sessionManager.addSession(this); sessionManager.addSession(this);
setStatus(Session.STATUS_AUTHENTICATED); setStatus(Session.STATUS_AUTHENTICATED);
// Set default privacy list for this session
setDefaultList(PrivacyListManager.getInstance().getDefaultPrivacyList(user.getUsername()));
} }
/** /**
...@@ -661,6 +718,22 @@ public class ClientSession extends Session { ...@@ -661,6 +718,22 @@ public class ClientSession extends Session {
} }
public void process(Packet packet) { public void process(Packet packet) {
if (activeList != null) {
// If a privacy list is active then make sure that the packet is not blocked
if (activeList.shouldBlockPacket(packet)) {
// Communication is blocked. Drop packet.
return;
}
}
else if (defaultList != null) {
// There is no active list so check if there exists a default list and make
// sure that the packet is not blocked
if (defaultList.shouldBlockPacket(packet)) {
// Communication is blocked. Drop packet.
return;
}
}
// Deliver packet to the client
deliver(packet); deliver(packet);
} }
......
...@@ -14,6 +14,9 @@ package org.jivesoftware.wildfire; ...@@ -14,6 +14,9 @@ package org.jivesoftware.wildfire;
import org.dom4j.Element; import org.dom4j.Element;
import org.jivesoftware.wildfire.container.BasicModule; import org.jivesoftware.wildfire.container.BasicModule;
import org.jivesoftware.wildfire.handler.IQHandler; import org.jivesoftware.wildfire.handler.IQHandler;
import org.jivesoftware.wildfire.privacy.PrivacyList;
import org.jivesoftware.wildfire.privacy.PrivacyListManager;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.util.LocaleUtils; import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.xmpp.packet.IQ; import org.xmpp.packet.IQ;
...@@ -224,44 +227,34 @@ public class IQRouter extends BasicModule { ...@@ -224,44 +227,34 @@ public class IQRouter extends BasicModule {
} }
} }
else { else {
// Check if communication to local users is allowed
if (recipientJID != null && recipientJID.getNode() != null) {
PrivacyList list = PrivacyListManager.getInstance()
.getDefaultPrivacyList(recipientJID.getNode());
if (list != null && list.shouldBlockPacket(packet)) {
// Communication is blocked
if (IQ.Type.set == packet.getType() || IQ.Type.get == packet.getType()) {
// Answer that the service is unavailable
sendErrorPacket(packet, PacketError.Condition.service_unavailable);
}
return;
}
}
IQHandler handler = getHandler(namespace); IQHandler handler = getHandler(namespace);
if (handler == null) { if (handler == null) {
IQ reply = IQ.createResultIQ(packet);
if (recipientJID == null) { if (recipientJID == null) {
// Answer an error since the server can't handle the requested namespace // Answer an error since the server can't handle the requested namespace
reply.setChildElement(packet.getChildElement().createCopy()); sendErrorPacket(packet, PacketError.Condition.service_unavailable);
reply.setError(PacketError.Condition.service_unavailable);
} }
else if (recipientJID.getNode() == null || else if (recipientJID.getNode() == null ||
"".equals(recipientJID.getNode())) { "".equals(recipientJID.getNode())) {
// Answer an error if JID is of the form <domain> // Answer an error if JID is of the form <domain>
reply.setChildElement(packet.getChildElement().createCopy()); sendErrorPacket(packet, PacketError.Condition.feature_not_implemented);
reply.setError(PacketError.Condition.feature_not_implemented);
} }
else { else {
// JID is of the form <node@domain> // JID is of the form <node@domain>
// Answer an error since the server can't handle packets sent to a node // Answer an error since the server can't handle packets sent to a node
reply.setChildElement(packet.getChildElement().createCopy()); sendErrorPacket(packet, PacketError.Condition.service_unavailable);
reply.setError(PacketError.Condition.service_unavailable);
}
// Locate a route to the sender of the IQ and ask it to process
// the packet. Use the routingTable so that routes to remote servers
// may be found
ChannelHandler route = routingTable.getRoute(packet.getFrom());
if (route != null) {
route.process(reply);
}
else {
// No root was found so try looking for local sessions that have never
// sent an available presence or haven't authenticated yet
Session session = sessionManager.getSession(packet.getFrom());
if (session != null) {
session.process(reply);
}
else {
Log.warn("Packet could not be delivered " + packet);
}
} }
} }
else { else {
...@@ -299,27 +292,7 @@ public class IQRouter extends BasicModule { ...@@ -299,27 +292,7 @@ public class IQRouter extends BasicModule {
// If a route to the target address was not found then try to answer a // If a route to the target address was not found then try to answer a
// service_unavailable error code to the sender of the IQ packet // service_unavailable error code to the sender of the IQ packet
if (!handlerFound && IQ.Type.result != packet.getType()) { if (!handlerFound && IQ.Type.result != packet.getType()) {
IQ reply = IQ.createResultIQ(packet); sendErrorPacket(packet, PacketError.Condition.service_unavailable);
reply.setChildElement(packet.getChildElement().createCopy());
reply.setError(PacketError.Condition.service_unavailable);
// Locate a route to the sender of the IQ and ask it to process
// the packet. Use the routingTable so that routes to remote servers
// may be found
ChannelHandler route = routingTable.getRoute(packet.getFrom());
if (route != null) {
route.process(reply);
}
else {
// No root was found so try looking for local sessions that have never
// sent an available presence or haven't authenticated yet
Session session = sessionManager.getSession(packet.getFrom());
if (session != null) {
session.process(reply);
}
else {
Log.warn("Packet could not be delivered " + reply);
}
}
} }
} }
} }
...@@ -335,6 +308,31 @@ public class IQRouter extends BasicModule { ...@@ -335,6 +308,31 @@ public class IQRouter extends BasicModule {
} }
} }
private void sendErrorPacket(IQ originalPacket, PacketError.Condition condition)
throws UnauthorizedException {
IQ reply = IQ.createResultIQ(originalPacket);
reply.setChildElement(originalPacket.getChildElement().createCopy());
reply.setError(condition);
// Locate a route to the sender of the IQ and ask it to process
// the packet. Use the routingTable so that routes to remote servers
// may be found
ChannelHandler route = routingTable.getRoute(originalPacket.getFrom());
if (route != null) {
route.process(reply);
}
else {
// No root was found so try looking for local sessions that have never
// sent an available presence or haven't authenticated yet
Session session = sessionManager.getSession(originalPacket.getFrom());
if (session != null) {
session.process(reply);
}
else {
Log.warn("Error packet could not be delivered " + reply);
}
}
}
private IQHandler getHandler(String namespace) { private IQHandler getHandler(String namespace) {
IQHandler handler = namespace2Handlers.get(namespace); IQHandler handler = namespace2Handlers.get(namespace);
if (handler == null) { if (handler == null) {
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
package org.jivesoftware.wildfire; package org.jivesoftware.wildfire;
import org.jivesoftware.wildfire.container.BasicModule; import org.jivesoftware.wildfire.container.BasicModule;
import org.jivesoftware.wildfire.privacy.PrivacyList;
import org.jivesoftware.wildfire.privacy.PrivacyListManager;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
...@@ -71,6 +73,12 @@ public class OfflineMessageStrategy extends BasicModule { ...@@ -71,6 +73,12 @@ public class OfflineMessageStrategy extends BasicModule {
Message.Type.headline == message.getType()) { Message.Type.headline == message.getType()) {
return; return;
} }
// Do not store messages if communication is blocked
PrivacyList list =
PrivacyListManager.getInstance().getDefaultPrivacyList(recipientJID.getNode());
if (list != null && list.shouldBlockPacket(message)) {
return;
}
if (type == Type.bounce) { if (type == Type.bounce) {
bounce(message); bounce(message);
......
...@@ -11,20 +11,24 @@ ...@@ -11,20 +11,24 @@
package org.jivesoftware.wildfire.roster; package org.jivesoftware.wildfire.roster;
import org.jivesoftware.database.JiveID;
import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.util.Cacheable;
import org.jivesoftware.util.JiveConstants;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.*;
import org.jivesoftware.wildfire.auth.UnauthorizedException; import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.user.UserNotFoundException; import org.jivesoftware.wildfire.group.Group;
import org.jivesoftware.wildfire.user.UserAlreadyExistsException; import org.jivesoftware.wildfire.group.GroupManager;
import org.jivesoftware.wildfire.privacy.PrivacyList;
import org.jivesoftware.wildfire.privacy.PrivacyListManager;
import org.jivesoftware.wildfire.user.User; import org.jivesoftware.wildfire.user.User;
import org.jivesoftware.wildfire.user.UserAlreadyExistsException;
import org.jivesoftware.wildfire.user.UserManager; import org.jivesoftware.wildfire.user.UserManager;
import org.jivesoftware.wildfire.*; import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.jivesoftware.wildfire.group.GroupManager; import org.xmpp.packet.IQ;
import org.jivesoftware.wildfire.group.Group; import org.xmpp.packet.JID;
import org.jivesoftware.util.Cacheable; import org.xmpp.packet.Presence;
import org.jivesoftware.util.CacheSizes;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveConstants;
import org.jivesoftware.database.JiveID;
import org.xmpp.packet.*;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
...@@ -444,12 +448,31 @@ public class Roster implements Cacheable { ...@@ -444,12 +448,31 @@ public class Roster implements Cacheable {
if (routingTable == null) { if (routingTable == null) {
return; return;
} }
// Get the privacy list of this user
PrivacyList list = null;
if (packet.getFrom() != null) {
// Try to use the active list of the session. If none was found then try to use
// the default privacy list of the session
ClientSession session = sessionManager.getSession(packet.getFrom());
if (session != null) {
list = session.getActiveList();
list = list == null ? session.getDefaultList() : list;
}
}
if (list == null) {
// No privacy list was found (based on the session) so check if there is a default list
list = PrivacyListManager.getInstance().getDefaultPrivacyList(username);
}
for (RosterItem item : rosterItems.values()) { for (RosterItem item : rosterItems.values()) {
if (item.getSubStatus() == RosterItem.SUB_BOTH if (item.getSubStatus() == RosterItem.SUB_BOTH
|| item.getSubStatus() == RosterItem.SUB_FROM) { || item.getSubStatus() == RosterItem.SUB_FROM) {
JID searchNode = new JID(item.getJid().getNode(), item.getJid().getDomain(), null); JID searchNode = new JID(item.getJid().getNode(), item.getJid().getDomain(), null);
Iterator sessions = routingTable.getRoutes(searchNode); Iterator sessions = routingTable.getRoutes(searchNode);
packet.setTo(item.getJid()); packet.setTo(item.getJid());
if (list != null && list.shouldBlockPacket(packet)) {
// Outgoing presence notifications are blocked for this contact
continue;
}
while (sessions.hasNext()) { while (sessions.hasNext()) {
ChannelHandler session = (ChannelHandler)sessions.next(); ChannelHandler session = (ChannelHandler)sessions.next();
try { try {
......
...@@ -15,6 +15,8 @@ import org.dom4j.Document; ...@@ -15,6 +15,8 @@ import org.dom4j.Document;
import org.dom4j.DocumentHelper; import org.dom4j.DocumentHelper;
import org.dom4j.DocumentException; import org.dom4j.DocumentException;
import org.jivesoftware.wildfire.*; import org.jivesoftware.wildfire.*;
import org.jivesoftware.wildfire.privacy.PrivacyList;
import org.jivesoftware.wildfire.privacy.PrivacyListManager;
import org.jivesoftware.wildfire.handler.PresenceUpdateHandler; import org.jivesoftware.wildfire.handler.PresenceUpdateHandler;
import org.jivesoftware.wildfire.component.InternalComponentManager; import org.jivesoftware.wildfire.component.InternalComponentManager;
import org.jivesoftware.wildfire.auth.UnauthorizedException; import org.jivesoftware.wildfire.auth.UnauthorizedException;
...@@ -267,8 +269,14 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -267,8 +269,14 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
Presence presencePacket = new Presence(element.getRootElement()); Presence presencePacket = new Presence(element.getRootElement());
presencePacket.setFrom(probee.toBareJID()); presencePacket.setFrom(probee.toBareJID());
presencePacket.setTo(prober); presencePacket.setTo(prober);
// Send the presence to the prober // Check if default privacy list of the probee blocks the
deliverer.deliver(presencePacket); // outgoing presence
PrivacyList list = PrivacyListManager.getInstance()
.getDefaultPrivacyList(probee.getNode());
if (list == null || !list.shouldBlockPacket(presencePacket)) {
// Send the presence to the prober
deliverer.deliver(presencePacket);
}
} }
catch (Exception e) { catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e); Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
...@@ -283,9 +291,19 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager ...@@ -283,9 +291,19 @@ public class PresenceManagerImpl extends BasicModule implements PresenceManager
// The contact is online so send to the prober all the resources where the // The contact is online so send to the prober all the resources where the
// probee is connected // probee is connected
for (ClientSession session : sessions) { for (ClientSession session : sessions) {
// Create presence to send from probee to prober
Presence presencePacket = session.getPresence().createCopy(); Presence presencePacket = session.getPresence().createCopy();
presencePacket.setFrom(session.getAddress()); presencePacket.setFrom(session.getAddress());
presencePacket.setTo(prober); presencePacket.setTo(prober);
// Check if a privacy list of the probee blocks the outgoing presence
PrivacyList list = session.getActiveList();
list = list == null ? session.getDefaultList() : list;
if (list != null) {
if (list.shouldBlockPacket(presencePacket)) {
// Default list blocked outgoing presence so skip this session
continue;
}
}
try { try {
deliverer.deliver(presencePacket); deliverer.deliver(presencePacket);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment