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; } }