Commit 4f2ccfe4 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Allow external components to bind many domains. JM-624

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3689 b35dd754-fafc-0310-a699-88a17e54d16e
parent 8f401fe8
...@@ -12,11 +12,11 @@ package org.jivesoftware.wildfire.component; ...@@ -12,11 +12,11 @@ package org.jivesoftware.wildfire.component;
import org.dom4j.Element; import org.dom4j.Element;
import org.dom4j.io.XMPPPacketReader; import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.*; import org.jivesoftware.wildfire.*;
import org.jivesoftware.wildfire.auth.AuthFactory; import org.jivesoftware.wildfire.auth.AuthFactory;
import org.jivesoftware.wildfire.auth.UnauthorizedException; import org.jivesoftware.wildfire.auth.UnauthorizedException;
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.component.Component; import org.xmpp.component.Component;
...@@ -27,6 +27,8 @@ import org.xmpp.packet.StreamError; ...@@ -27,6 +27,8 @@ import org.xmpp.packet.StreamError;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
/** /**
* Represents a session between the server and a component. * Represents a session between the server and a component.
...@@ -180,7 +182,7 @@ public class ComponentSession extends Session { ...@@ -180,7 +182,7 @@ public class ComponentSession extends Session {
writer.flush(); writer.flush();
// Bind the domain to this component // Bind the domain to this component
ExternalComponent component = ((ComponentSession) session).getExternalComponent(); ExternalComponent component = ((ComponentSession) session).getExternalComponent();
component.setSubdomain(subdomain); component.setInitialSubdomain(subdomain);
InternalComponentManager.getInstance().addComponent(subdomain, component); InternalComponentManager.getInstance().addComponent(subdomain, component);
Log.debug("[ExComp] External component was registered SUCCESSFULLY with domain: " + Log.debug("[ExComp] External component was registered SUCCESSFULLY with domain: " +
domain); domain);
...@@ -229,7 +231,15 @@ public class ComponentSession extends Session { ...@@ -229,7 +231,15 @@ public class ComponentSession extends Session {
private String name = ""; private String name = "";
private String type = ""; private String type = "";
private String category = ""; private String category = "";
private String subdomain; /**
* Subdomain used when creating the initial connection.
*/
private String initialSubdomain;
/**
* List of subdomains that were binded for this component. The list will include
* the initial subdomain.
*/
private Collection<String> subdomains = new ArrayList<String>();
public void processPacket(Packet packet) { public void processPacket(Packet packet) {
if (conn != null && !conn.isClosed()) { if (conn != null && !conn.isClosed()) {
...@@ -271,12 +281,21 @@ public class ComponentSession extends Session { ...@@ -271,12 +281,21 @@ public class ComponentSession extends Session {
this.category = category; this.category = category;
} }
public String getSubdomain() { public String getInitialSubdomain() {
return subdomain; return initialSubdomain;
}
public void setInitialSubdomain(String initialSubdomain) {
this.initialSubdomain = initialSubdomain;
addSubdomain(initialSubdomain);
}
public void addSubdomain(String subdomain) {
subdomains.add(subdomain);
} }
public void setSubdomain(String subdomain) { public Collection<String> getSubdomains() {
this.subdomain = subdomain; return subdomains;
} }
public void initialize(JID jid, ComponentManager componentManager) { public void initialize(JID jid, ComponentManager componentManager) {
...@@ -287,5 +306,9 @@ public class ComponentSession extends Session { ...@@ -287,5 +306,9 @@ public class ComponentSession extends Session {
public void shutdown() { public void shutdown() {
} }
public String toString() {
return super.toString() + " - subdomains: " + subdomains;
}
} }
} }
\ No newline at end of file
package org.jivesoftware.wildfire.component; package org.jivesoftware.wildfire.component;
import org.jivesoftware.database.DbConnectionManager; import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.Session; import org.jivesoftware.wildfire.Session;
import org.jivesoftware.wildfire.SessionManager; import org.jivesoftware.wildfire.SessionManager;
import org.jivesoftware.wildfire.XMPPServer; import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.component.ExternalComponentConfiguration.Permission; import org.jivesoftware.wildfire.component.ExternalComponentConfiguration.Permission;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
...@@ -325,10 +325,13 @@ public class ExternalComponentManager { ...@@ -325,10 +325,13 @@ public class ExternalComponentManager {
*/ */
public static void setPermissionPolicy(PermissionPolicy policy) { public static void setPermissionPolicy(PermissionPolicy policy) {
JiveGlobals.setProperty("xmpp.component.permission", policy.toString()); JiveGlobals.setProperty("xmpp.component.permission", policy.toString());
// Check if the connected component can remain connected to the server // Check if connected components can remain connected to the server
for (ComponentSession session : SessionManager.getInstance().getComponentSessions()) { for (ComponentSession session : SessionManager.getInstance().getComponentSessions()) {
if (!canAccess(session.getExternalComponent().getSubdomain())) { for (String domain : session.getExternalComponent().getSubdomains()) {
session.getConnection().close(); if (!canAccess(domain)) {
session.getConnection().close();
break;
}
} }
} }
} }
...@@ -357,6 +360,6 @@ public class ExternalComponentManager { ...@@ -357,6 +360,6 @@ public class ExternalComponentManager {
* Only the XMPP entities listed in the <b>allowed list</b> are able to connect to * Only the XMPP entities listed in the <b>allowed list</b> are able to connect to
* the server. * the server.
*/ */
whitelist; whitelist
} }
} }
...@@ -12,10 +12,14 @@ ...@@ -12,10 +12,14 @@
package org.jivesoftware.wildfire.net; package org.jivesoftware.wildfire.net;
import org.dom4j.Element; import org.dom4j.Element;
import org.jivesoftware.wildfire.component.ComponentSession; import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.PacketRouter; import org.jivesoftware.wildfire.PacketRouter;
import org.jivesoftware.wildfire.auth.UnauthorizedException; import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.component.ComponentSession;
import org.jivesoftware.wildfire.component.InternalComponentManager;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.xmpp.component.ComponentException;
import org.xmpp.packet.PacketError;
import java.io.IOException; import java.io.IOException;
import java.net.Socket; import java.net.Socket;
...@@ -34,13 +38,63 @@ public class ComponentSocketReader extends SocketReader { ...@@ -34,13 +38,63 @@ public class ComponentSocketReader extends SocketReader {
} }
/** /**
* Only packets of type Message, Presence and IQ can be processed by this class. Any other * Only <tt>bind<tt> packets will be processed by this class to bind more domains
* type of packet is unknown and thus rejected generating the connection to be closed. * to existing external components. Any other type of packet is unknown and thus
* rejected generating the connection to be closed.
* *
* @param doc the unknown DOM element that was received * @param doc the unknown DOM element that was received
* @return always false. * @return false if packet is unknown otherwise true.
*/ */
protected boolean processUnknowPacket(Element doc) { protected boolean processUnknowPacket(Element doc) {
// Handle subsequent bind packets
if ("bind".equals(doc.getName())) {
ComponentSession componentSession = (ComponentSession) session;
// Get the external component of this session
ComponentSession.ExternalComponent component = componentSession.getExternalComponent();
String initialDomain = component.getInitialSubdomain();
String extraDomain = doc.attributeValue("name");
if (extraDomain == null || "".equals(extraDomain)) {
// No new bind domain was specified so return a bad_request error
Element reply = doc.createCopy();
reply.add(new PacketError(PacketError.Condition.bad_request).getElement());
connection.deliverRawText(reply.asXML());
}
else if (extraDomain.endsWith(initialDomain)) {
// Only accept subdomains under the initial registered domain
if (component.getSubdomains().contains(extraDomain)) {
// Domain already in use so return a conflict error
Element reply = doc.createCopy();
reply.add(new PacketError(PacketError.Condition.conflict).getElement());
connection.deliverRawText(reply.asXML());
}
else {
try {
InternalComponentManager.getInstance().addComponent(extraDomain, component);
component.addSubdomain(extraDomain);
// Send confirmation that the new domain has been registered
connection.deliverRawText("<bind/>");
}
catch (ComponentException e) {
Log.error("Error binding extra domain: " + extraDomain + " to component: " +
component, e);
// Return internal server error
Element reply = doc.createCopy();
reply.add(new PacketError(
PacketError.Condition.internal_server_error).getElement());
connection.deliverRawText(reply.asXML());
}
}
}
else {
// Return forbidden error since we only allow subdomains of the intial domain
// to be used by the same external component
Element reply = doc.createCopy();
reply.add(new PacketError(PacketError.Condition.forbidden).getElement());
connection.deliverRawText(reply.asXML());
}
return true;
}
// This is an unknown packet so return false (and close the connection)
return false; return false;
} }
......
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