183 lines
5.0 KiB
Java
183 lines
5.0 KiB
Java
package com.runjva.sourceforge.jsocks.server;
|
|
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.net.InetAddress;
|
|
import java.net.Socket;
|
|
import java.util.Enumeration;
|
|
import java.util.Hashtable;
|
|
import java.util.Vector;
|
|
|
|
import com.runjva.sourceforge.jsocks.protocol.InetRange;
|
|
import com.runjva.sourceforge.jsocks.protocol.ProxyMessage;
|
|
|
|
/**
|
|
* An implementation of socks.ServerAuthentication which provides simple
|
|
* authentication based on the host from which the connection is made and the
|
|
* name of the user on the remote machine, as reported by identd daemon on the
|
|
* remote machine.
|
|
* <p>
|
|
* It can also be used to provide authentication based only on the contacting
|
|
* host address.
|
|
*/
|
|
|
|
public class IdentAuthenticator extends ServerAuthenticatorBase {
|
|
/** Vector of InetRanges */
|
|
Vector<InetRange> hosts;
|
|
|
|
/** Vector of user hashes */
|
|
Vector<Hashtable<?, ?>> users;
|
|
|
|
String user;
|
|
|
|
/**
|
|
* Constructs empty IdentAuthenticator.
|
|
*/
|
|
public IdentAuthenticator() {
|
|
hosts = new Vector<InetRange>();
|
|
users = new Vector<Hashtable<?, ?>>();
|
|
}
|
|
|
|
/**
|
|
* Used to create instances returned from startSession.
|
|
*
|
|
* @param in
|
|
* Input stream.
|
|
* @param out
|
|
* OutputStream.
|
|
* @param user
|
|
* Username associated with this connection,could be null if name
|
|
* was not required.
|
|
*/
|
|
IdentAuthenticator(InputStream in, OutputStream out, String user) {
|
|
super(in, out);
|
|
this.user = user;
|
|
}
|
|
|
|
/**
|
|
* Adds range of addresses from which connection is allowed. Hashtable users
|
|
* should contain user names as keys and anything as values (value is not
|
|
* used and will be ignored).
|
|
*
|
|
* @param hostRange
|
|
* Range of ip addresses from which connection is allowed.
|
|
* @param users
|
|
* Hashtable of users for whom connection is allowed, or null to
|
|
* indicate that anybody is allowed to connect from the hosts
|
|
* within given range.
|
|
*/
|
|
public synchronized void add(InetRange hostRange, Hashtable<?, ?> users) {
|
|
this.hosts.addElement(hostRange);
|
|
this.users.addElement(users);
|
|
}
|
|
|
|
/**
|
|
* Grants permission only to those users, who connect from one of the hosts
|
|
* registered with add(InetRange,Hashtable) and whose names, as reported by
|
|
* identd daemon, are listed for the host the connection came from.
|
|
*/
|
|
public ServerAuthenticator startSession(Socket s) throws IOException {
|
|
|
|
final int ind = getRangeIndex(s.getInetAddress());
|
|
String user = null;
|
|
|
|
// System.out.println("getRangeReturned:"+ind);
|
|
|
|
if (ind < 0) {
|
|
return null; // Host is not on the list.
|
|
}
|
|
|
|
final ServerAuthenticator serverAuthenticator = super.startSession(s);
|
|
final ServerAuthenticatorBase auth = (ServerAuthenticatorBase) serverAuthenticator;
|
|
|
|
// System.out.println("super.startSession() returned:"+auth);
|
|
if (auth == null) {
|
|
return null;
|
|
}
|
|
|
|
// do the authentication
|
|
|
|
final Hashtable<?, ?> user_names = users.elementAt(ind);
|
|
|
|
if (user_names != null) { // If need to do authentication
|
|
Ident ident;
|
|
ident = new Ident(s);
|
|
// If can't obtain user name, fail
|
|
if (!ident.successful) {
|
|
return null;
|
|
}
|
|
// If user name is not listed for this address, fail
|
|
if (!user_names.containsKey(ident.userName)) {
|
|
return null;
|
|
}
|
|
user = ident.userName;
|
|
}
|
|
return new IdentAuthenticator(auth.in, auth.out, user);
|
|
|
|
}
|
|
|
|
/**
|
|
* For SOCKS5 requests allways returns true. For SOCKS4 requests checks
|
|
* wether the user name supplied in the request corresponds to the name
|
|
* obtained from the ident daemon.
|
|
*/
|
|
public boolean checkRequest(ProxyMessage msg, java.net.Socket s) {
|
|
// If it's version 5 request, or if anybody is permitted, return true;
|
|
if ((msg.version == 5) || (user == null)) {
|
|
return true;
|
|
}
|
|
|
|
if (msg.version != 4) {
|
|
return false; // Who knows?
|
|
}
|
|
|
|
return user.equals(msg.user);
|
|
}
|
|
|
|
/** Get String representaion of the IdentAuthenticator. */
|
|
public String toString() {
|
|
String s = "";
|
|
|
|
for (int i = 0; i < hosts.size(); ++i) {
|
|
s += "(Range:" + hosts.elementAt(i) + "," + //
|
|
" Users:" + userNames(i) + ") ";
|
|
}
|
|
return s;
|
|
}
|
|
|
|
// Private Methods
|
|
// ////////////////
|
|
private int getRangeIndex(InetAddress ip) {
|
|
int index = 0;
|
|
final Enumeration<InetRange> enumx = hosts.elements();
|
|
while (enumx.hasMoreElements()) {
|
|
final InetRange ir = enumx.nextElement();
|
|
if (ir.contains(ip)) {
|
|
return index;
|
|
}
|
|
index++;
|
|
}
|
|
return -1; // Not found
|
|
}
|
|
|
|
private String userNames(int i) {
|
|
if (users.elementAt(i) == null) {
|
|
return "Everybody is permitted.";
|
|
}
|
|
|
|
final Enumeration<?> enumx = ((Hashtable<?, ?>) users.elementAt(i))
|
|
.keys();
|
|
if (!enumx.hasMoreElements()) {
|
|
return "";
|
|
}
|
|
String s = enumx.nextElement().toString();
|
|
while (enumx.hasMoreElements()) {
|
|
s += "; " + enumx.nextElement();
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
}
|