tor-android/src/com/runjva/sourceforge/jsocks/server/IdentAuthenticator.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;
}
}