Commit a92017da authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gaston

Added login restriction to certain IP addresses or ranges. JM-154


git-svn-id: http://svn.igniterealtime.org/svn/repos/messenger/trunk@1636 b35dd754-fafc-0310-a699-88a17e54d16e
parent b5221a1e
...@@ -19,15 +19,21 @@ import org.jivesoftware.messenger.user.UserNotFoundException; ...@@ -19,15 +19,21 @@ import org.jivesoftware.messenger.user.UserNotFoundException;
import org.jivesoftware.messenger.net.SocketConnection; import org.jivesoftware.messenger.net.SocketConnection;
import org.jivesoftware.util.LocaleUtils; import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log; import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import org.xmpp.packet.Packet; import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence; import org.xmpp.packet.Presence;
import org.xmpp.packet.StreamError;
import org.dom4j.io.XPPPacketReader; import org.dom4j.io.XPPPacketReader;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
import java.io.Writer; import java.io.Writer;
import java.io.IOException; import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;
/** /**
* Represents a session between the server and a client. * Represents a session between the server and a client.
...@@ -46,6 +52,15 @@ public class ClientSession extends Session { ...@@ -46,6 +52,15 @@ public class ClientSession extends Session {
private static final int MAJOR_VERSION = 0; private static final int MAJOR_VERSION = 0;
private static final int MINOR_VERSION = 0; private static final int MINOR_VERSION = 0;
/**
* Keep the list of IP address that are allowed to connect to the server. If the list is
* empty then anyone is allowed to connect to the server.<p>
*
* Note: Key = IP address or IP range; Value = empty string. A hash map is being used for
* performance reasons.
*/
private static Map<String,String> allowedIPs = new HashMap<String,String>();
/** /**
* The authentication token for this session. * The authentication token for this session.
*/ */
...@@ -60,6 +75,16 @@ public class ClientSession extends Session { ...@@ -60,6 +75,16 @@ public class ClientSession extends Session {
private int conflictCount = 0; private int conflictCount = 0;
static {
// Fill out the allowedIPs with the system property
String allowed = JiveGlobals.getProperty("xmpp.client.login.allowed", "");
StringTokenizer tokens = new StringTokenizer(allowed, ", ");
while (tokens.hasMoreTokens()) {
String address = tokens.nextToken().trim();
allowedIPs.put(address, "");
}
}
/** /**
* Returns a newly created session between the server and a client. The session will * Returns a newly created session between the server and a client. The session will
* be created and returned only if correct name/prefix (i.e. 'stream' or 'flash') * be created and returned only if correct name/prefix (i.e. 'stream' or 'flash')
...@@ -93,6 +118,32 @@ public class ClientSession extends Session { ...@@ -93,6 +118,32 @@ public class ClientSession extends Session {
"admin.error.bad-namespace")); "admin.error.bad-namespace"));
} }
if (!allowedIPs.isEmpty()) {
// The server is using a whitelist so check that the IP address of the client
// is authorized to connect to the server
if (!allowedIPs.containsKey(connection.getInetAddress().getHostAddress())) {
byte[] address = connection.getInetAddress().getAddress();
String range1 = address[0] + "." + address[1] + "." + address[2] + ".*";
String range2 = address[0] + "." + address[1] + ".*.*";
String range3 = address[0] + ".*.*.*";
if (!allowedIPs.containsKey(range1) && !allowedIPs.containsKey(range2) &&
!allowedIPs.containsKey(range3)) {
// Client cannot connect from this IP address so end the stream and
// TCP connection
Log.debug("Closed connection to client attempting to connect from: " +
connection.getInetAddress().getHostAddress());
// Include the not-authorized error in the response
StreamError error = new StreamError(StreamError.Condition.not_authorized);
StringBuilder sb = new StringBuilder();
sb.append(error.toXML());
connection.deliverRawText(sb.toString());
// Close the underlying connection
connection.close();
return null;
}
}
}
// Default language is English ("en"). // Default language is English ("en").
String language = "en"; String language = "en";
// Default to a version of "0.0". Clients written before the XMPP 1.0 spec may // Default to a version of "0.0". Clients written before the XMPP 1.0 spec may
...@@ -211,6 +262,41 @@ public class ClientSession extends Session { ...@@ -211,6 +262,41 @@ public class ClientSession extends Session {
return session; return session;
} }
/**
* Returns the list of IP address that are allowed to connect to the server. If the list is
* empty then anyone is allowed to connect to the server.
*
* @return the list of IP address that are allowed to connect to the server.
*/
public static Map<String, String> getAllowedIPs() {
return allowedIPs;
}
/**
* Sets the list of IP address that are allowed to connect to the server. If the list is
* empty then anyone is allowed to connect to the server.
*
* @param allowed the list of IP address that are allowed to connect to the server.
*/
public static void setAllowedIPs(Map<String, String> allowed) {
allowedIPs = allowed;
if (allowedIPs.isEmpty()) {
JiveGlobals.deleteProperty("xmpp.client.login.allowed");
}
else {
// Iterate through the elements in the map.
StringBuilder buf = new StringBuilder();
Iterator<String> iter = allowedIPs.keySet().iterator();
if (iter.hasNext()) {
buf.append(iter.next());
}
while (iter.hasNext()) {
buf.append(", ").append((String)iter.next());
}
JiveGlobals.setProperty("xmpp.client.login.allowed", buf.toString());
}
}
/** /**
* Creates a session with an underlying connection and permission protection. * Creates a session with an underlying connection and permission protection.
* *
......
...@@ -9,11 +9,12 @@ ...@@ -9,11 +9,12 @@
- a copy of which is included in this distribution. - a copy of which is included in this distribution.
--%> --%>
<%@ page import="org.jivesoftware.util.ParamUtils, <%@ page import="org.jivesoftware.messenger.handler.IQRegisterHandler,
org.jivesoftware.messenger.handler.IQRegisterHandler,
org.jivesoftware.messenger.handler.IQAuthHandler, org.jivesoftware.messenger.handler.IQAuthHandler,
org.jivesoftware.admin.AdminPageBean, org.jivesoftware.admin.AdminPageBean,
org.jivesoftware.util.LocaleUtils" java.util.*,
org.jivesoftware.messenger.ClientSession,
org.jivesoftware.util.*"
errorPage="error.jsp" errorPage="error.jsp"
%> %>
...@@ -39,6 +40,7 @@ ...@@ -39,6 +40,7 @@
boolean inbandEnabled = ParamUtils.getBooleanParameter(request,"inbandEnabled"); boolean inbandEnabled = ParamUtils.getBooleanParameter(request,"inbandEnabled");
boolean canChangePassword = ParamUtils.getBooleanParameter(request,"canChangePassword"); boolean canChangePassword = ParamUtils.getBooleanParameter(request,"canChangePassword");
boolean anonLogin = ParamUtils.getBooleanParameter(request,"anonLogin"); boolean anonLogin = ParamUtils.getBooleanParameter(request,"anonLogin");
String allowedIPs = request.getParameter("allowedIPs");
// Get an IQRegisterHandler: // Get an IQRegisterHandler:
IQRegisterHandler regHandler = new IQRegisterHandler(); IQRegisterHandler regHandler = new IQRegisterHandler();
...@@ -48,12 +50,31 @@ ...@@ -48,12 +50,31 @@
regHandler.setInbandRegEnabled(inbandEnabled); regHandler.setInbandRegEnabled(inbandEnabled);
regHandler.setCanChangePassword(canChangePassword); regHandler.setCanChangePassword(canChangePassword);
authHandler.setAllowAnonymous(anonLogin); authHandler.setAllowAnonymous(anonLogin);
// Build a Map with the allowed IP addresses
Map<String,String> newMap = new HashMap<String,String>();
StringTokenizer tokens = new StringTokenizer(allowedIPs, ", ");
while (tokens.hasMoreTokens()) {
String address = tokens.nextToken().trim();
newMap.put(address, "");
}
ClientSession.setAllowedIPs(newMap);
} }
// Reset the value of page vars: // Reset the value of page vars:
inbandEnabled = regHandler.isInbandRegEnabled(); inbandEnabled = regHandler.isInbandRegEnabled();
canChangePassword = regHandler.canChangePassword(); canChangePassword = regHandler.canChangePassword();
anonLogin = authHandler.isAllowAnonymous(); anonLogin = authHandler.isAllowAnonymous();
// Encode the allowed IP addresses
StringBuilder buf = new StringBuilder();
Iterator<String> iter = ClientSession.getAllowedIPs().keySet().iterator();
if (iter.hasNext()) {
buf.append(iter.next());
}
while (iter.hasNext()) {
buf.append(", ").append((String)iter.next());
}
allowedIPs = buf.toString();
%> %>
<p> <p>
...@@ -175,6 +196,26 @@ ...@@ -175,6 +196,26 @@
</div> </div>
</fieldset> </fieldset>
<br>
<fieldset>
<legend><fmt:message key="reg.settings.allowed_ips" /></legend>
<div>
<p>
<fmt:message key="reg.settings.allowed_ips_info" />
</p>
<table cellpadding="3" cellspacing="0" border="0" width="100%">
<tbody>
<tr>
<td>
<textarea name="allowedIPs" cols="40" rows="3" wrap="virtual"><%= ((allowedIPs != null) ? allowedIPs : "") %></textarea>
</td>
</tr>
</tbody>
</table>
</div>
</fieldset>
<br><br> <br><br>
<input type="submit" name="save" value="<fmt:message key="global.save_settings" />"> <input type="submit" name="save" value="<fmt:message key="global.save_settings" />">
......
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