tor-android/src/com/runjva/sourceforge/jsocks/server/ServerAuthenticatorBase.java

188 lines
4.5 KiB
Java

package com.runjva.sourceforge.jsocks.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.net.Socket;
import com.runjva.sourceforge.jsocks.protocol.ProxyMessage;
import com.runjva.sourceforge.jsocks.protocol.UDPEncapsulation;
/**
* An implementation of ServerAuthenticator, which does <b>not</b> do any
* authentication.
* <P>
* <FONT size="+3" color ="FF0000"> Warning!!</font><br>
* Should not be used on machines which are not behind the firewall.
* <p>
* It is only provided to make implementing other authentication schemes easier.
* <br>
* For Example: <tt><pre>
class MyAuth extends socks.server.ServerAuthenticator{
...
public ServerAuthenticator startSession(java.net.Socket s){
if(!checkHost(s.getInetAddress()) return null;
return super.startSession(s);
}
boolean checkHost(java.net.Inetaddress addr){
boolean allow;
//Do it somehow
return allow;
}
}
</pre></tt>
*/
public abstract class ServerAuthenticatorBase implements ServerAuthenticator {
static final byte[] socks5response = { 5, 0 };
InputStream in;
OutputStream out;
/**
* Creates new instance of the ServerAuthenticatorNone.
*/
public ServerAuthenticatorBase() {
this.in = null;
this.out = null;
}
/**
* Constructs new ServerAuthenticatorNone object suitable for returning from
* the startSession function.
*
* @param in
* Input stream to return from getInputStream method.
* @param out
* Output stream to return from getOutputStream method.
*/
public ServerAuthenticatorBase(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
}
/**
* Grants access to everyone.Removes authentication related bytes from the
* stream, when a SOCKS5 connection is being made, selects an authentication
* NONE.
*/
public ServerAuthenticator startSession(Socket s) throws IOException {
final PushbackInputStream in = new PushbackInputStream(s
.getInputStream());
final OutputStream out = s.getOutputStream();
final int version = in.read();
if (version == 5) {
if (!selectSocks5Authentication(in, out, 0)) {
return null;
}
} else if (version == 4) {
// Else it is the request message already, version 4
in.unread(version);
} else {
return null;
}
return new ServerAuthenticatorNone(in, out);
}
/**
* Get input stream.
*
* @return Input stream speciefied in the constructor.
*/
public InputStream getInputStream() {
return in;
}
/**
* Get output stream.
*
* @return Output stream speciefied in the constructor.
*/
public OutputStream getOutputStream() {
return out;
}
/**
* Allways returns null.
*
* @return null
*/
public UDPEncapsulation getUdpEncapsulation() {
return null;
}
/**
* Allways returns true.
*/
public boolean checkRequest(ProxyMessage msg) {
return true;
}
/**
* Allways returns true.
*/
public boolean checkRequest(java.net.DatagramPacket dp, boolean out) {
return true;
}
/**
* Does nothing.
*/
public void endSession() {
}
/**
* Convinience routine for selecting SOCKSv5 authentication.
* <p>
* This method reads in authentication methods that client supports, checks
* wether it supports given method. If it does, the notification method is
* written back to client, that this method have been chosen for
* authentication. If given method was not found, authentication failure
* message is send to client ([5,FF]).
*
* @param in
* Input stream, version byte should be removed from the stream
* before calling this method.
* @param out
* Output stream.
* @param methodId
* Method which should be selected.
* @return true if methodId was found, false otherwise.
*/
static public boolean selectSocks5Authentication(InputStream in,
OutputStream out, int methodId) throws IOException {
final int num_methods = in.read();
if (num_methods <= 0) {
return false;
}
final byte method_ids[] = new byte[num_methods];
final byte response[] = new byte[2];
boolean found = false;
response[0] = (byte) 5; // SOCKS version
response[1] = (byte) 0xFF; // Not found, we are pessimistic
int bread = 0; // bytes read so far
while (bread < num_methods) {
bread += in.read(method_ids, bread, num_methods - bread);
}
for (int i = 0; i < num_methods; ++i) {
if (method_ids[i] == methodId) {
found = true;
response[1] = (byte) methodId;
break;
}
}
out.write(response);
return found;
}
}