[3030] | 1 | package nu.fw.jeti.plugins.filetransfer.socks5.jsocks; |
---|
| 2 | import java.io.IOException; |
---|
| 3 | import java.io.InputStream; |
---|
| 4 | import java.io.InterruptedIOException; |
---|
| 5 | import java.io.OutputStream; |
---|
| 6 | import java.net.InetAddress; |
---|
| 7 | import java.net.Socket; |
---|
| 8 | import java.net.UnknownHostException; |
---|
| 9 | |
---|
| 10 | /** |
---|
| 11 | Abstract class Proxy, base for classes Socks4Proxy and Socks5Proxy. |
---|
| 12 | Defines methods for specifying default proxy, to be |
---|
| 13 | used by all classes of this package. |
---|
| 14 | */ |
---|
| 15 | |
---|
| 16 | public abstract class Proxy{ |
---|
| 17 | |
---|
| 18 | //Data members |
---|
| 19 | protected InetRange directHosts = new InetRange(); |
---|
| 20 | |
---|
| 21 | protected InetAddress proxyIP = null; |
---|
| 22 | protected String proxyHost = null; |
---|
| 23 | protected int proxyPort; |
---|
| 24 | protected Socket proxySocket = null; |
---|
| 25 | |
---|
| 26 | protected InputStream in; |
---|
| 27 | protected OutputStream out; |
---|
| 28 | |
---|
| 29 | protected int version; |
---|
| 30 | |
---|
| 31 | protected Proxy chainProxy = null; |
---|
| 32 | |
---|
| 33 | |
---|
| 34 | //Protected static/class variables |
---|
| 35 | protected static Proxy defaultProxy = null; |
---|
| 36 | |
---|
| 37 | //Constructors |
---|
| 38 | //==================== |
---|
| 39 | Proxy(Proxy chainProxy, |
---|
| 40 | String proxyHost,int proxyPort)throws UnknownHostException{ |
---|
| 41 | this.chainProxy = chainProxy; |
---|
| 42 | this.proxyHost = proxyHost; |
---|
| 43 | |
---|
| 44 | if(chainProxy == null) |
---|
| 45 | this.proxyIP = InetAddress.getByName(proxyHost); |
---|
| 46 | |
---|
| 47 | this.proxyPort = proxyPort; |
---|
| 48 | } |
---|
| 49 | |
---|
| 50 | |
---|
| 51 | Proxy(String proxyHost,int proxyPort)throws UnknownHostException{ |
---|
| 52 | this(null,proxyHost,proxyPort); |
---|
| 53 | } |
---|
| 54 | |
---|
| 55 | Proxy(Proxy chainProxy,InetAddress proxyIP,int proxyPort){ |
---|
| 56 | this.chainProxy = chainProxy; |
---|
| 57 | this.proxyIP = proxyIP; |
---|
| 58 | this.proxyPort = proxyPort; |
---|
| 59 | } |
---|
| 60 | |
---|
| 61 | Proxy(InetAddress proxyIP,int proxyPort){ |
---|
| 62 | this(null,proxyIP,proxyPort); |
---|
| 63 | } |
---|
| 64 | |
---|
| 65 | Proxy(Proxy p){ |
---|
| 66 | this.proxyIP = p.proxyIP; |
---|
| 67 | this.proxyPort = p.proxyPort; |
---|
| 68 | this.version = p.version; |
---|
| 69 | this.directHosts = p.directHosts; |
---|
| 70 | } |
---|
| 71 | |
---|
| 72 | //Public instance methods |
---|
| 73 | //======================== |
---|
| 74 | |
---|
| 75 | /** |
---|
| 76 | Get the port on which proxy server is running. |
---|
| 77 | * @return Proxy port. |
---|
| 78 | */ |
---|
| 79 | public int getPort(){ |
---|
| 80 | return proxyPort; |
---|
| 81 | } |
---|
| 82 | /** |
---|
| 83 | Get the ip address of the proxy server host. |
---|
| 84 | * @return Proxy InetAddress. |
---|
| 85 | */ |
---|
| 86 | public InetAddress getInetAddress(){ |
---|
| 87 | return proxyIP; |
---|
| 88 | } |
---|
| 89 | /** |
---|
| 90 | * Adds given ip to the list of direct addresses. |
---|
| 91 | * This machine will be accessed without using proxy. |
---|
| 92 | */ |
---|
| 93 | public void addDirect(InetAddress ip){ |
---|
| 94 | directHosts.add(ip); |
---|
| 95 | } |
---|
| 96 | /** |
---|
| 97 | * Adds host to the list of direct addresses. |
---|
| 98 | * This machine will be accessed without using proxy. |
---|
| 99 | */ |
---|
| 100 | public boolean addDirect(String host){ |
---|
| 101 | return directHosts.add(host); |
---|
| 102 | } |
---|
| 103 | /** |
---|
| 104 | * Adds given range of addresses to the lsit of direct addresses, |
---|
| 105 | * machines within this range will be accessed without using proxy. |
---|
| 106 | */ |
---|
| 107 | public void addDirect(InetAddress from,InetAddress to){ |
---|
| 108 | directHosts.add(from,to); |
---|
| 109 | } |
---|
| 110 | /** |
---|
| 111 | * Sets given InetRange as the list of direct address, previous |
---|
| 112 | * list will be discarded, any changes done previously with |
---|
| 113 | * addDirect(Inetaddress) will be lost. |
---|
| 114 | * The machines in this range will be accessed without using proxy. |
---|
| 115 | * @param ir InetRange which should be used to look up direct addresses. |
---|
| 116 | * @see InetRange |
---|
| 117 | */ |
---|
| 118 | public void setDirect(InetRange ir){ |
---|
| 119 | directHosts = ir; |
---|
| 120 | } |
---|
| 121 | |
---|
| 122 | /** |
---|
| 123 | Get the list of direct hosts. |
---|
| 124 | * @return Current range of direct address as InetRange object. |
---|
| 125 | * @see InetRange |
---|
| 126 | */ |
---|
| 127 | public InetRange getDirect(){ |
---|
| 128 | return directHosts; |
---|
| 129 | } |
---|
| 130 | /** |
---|
| 131 | Check wether the given host is on the list of direct address. |
---|
| 132 | @param host Host name to check. |
---|
| 133 | * @return true if the given host is specified as the direct addresses. |
---|
| 134 | */ |
---|
| 135 | public boolean isDirect(String host){ |
---|
| 136 | return directHosts.contains(host); |
---|
| 137 | } |
---|
| 138 | /** |
---|
| 139 | Check wether the given host is on the list of direct addresses. |
---|
| 140 | @param host Host address to check. |
---|
| 141 | * @return true if the given host is specified as the direct address. |
---|
| 142 | */ |
---|
| 143 | public boolean isDirect(InetAddress host){ |
---|
| 144 | return directHosts.contains(host); |
---|
| 145 | } |
---|
| 146 | /** |
---|
| 147 | Set the proxy which should be used to connect to given proxy. |
---|
| 148 | @param chainProxy Proxy to use to connect to this proxy. |
---|
| 149 | */ |
---|
| 150 | public void setChainProxy(Proxy chainProxy){ |
---|
| 151 | this.chainProxy = chainProxy; |
---|
| 152 | } |
---|
| 153 | |
---|
| 154 | /** |
---|
| 155 | Get proxy which is used to connect to this proxy. |
---|
| 156 | @return Proxy which is used to connect to this proxy, or null |
---|
| 157 | if proxy is to be contacted directly. |
---|
| 158 | */ |
---|
| 159 | public Proxy getChainProxy(){ |
---|
| 160 | return chainProxy; |
---|
| 161 | } |
---|
| 162 | |
---|
| 163 | /** |
---|
| 164 | Get string representation of this proxy. |
---|
| 165 | * @returns string in the form:proxyHost:proxyPort \t Version versionNumber |
---|
| 166 | */ |
---|
| 167 | public String toString(){ |
---|
| 168 | return (""+proxyIP.getHostName()+":"+proxyPort+"\tVersion "+version); |
---|
| 169 | } |
---|
| 170 | |
---|
| 171 | |
---|
| 172 | //Public Static(Class) Methods |
---|
| 173 | //============================== |
---|
| 174 | |
---|
| 175 | |
---|
| 176 | |
---|
| 177 | |
---|
| 178 | /** |
---|
| 179 | * Sets SOCKS5 proxy as default. |
---|
| 180 | * Default proxy only supports no-authentication. |
---|
| 181 | @param hostName Host name on which SOCKS5 server is running. |
---|
| 182 | @param port Port on which SOCKS5 server is running. |
---|
| 183 | */ |
---|
| 184 | public static void setDefaultProxy(String hostName,int port) |
---|
| 185 | throws UnknownHostException{ |
---|
| 186 | defaultProxy = new Socks5Proxy(hostName,port); |
---|
| 187 | } |
---|
| 188 | /** |
---|
| 189 | * Sets SOCKS5 proxy as default. |
---|
| 190 | * Default proxy only supports no-authentication. |
---|
| 191 | @param ipAddress Host address on which SOCKS5 server is running. |
---|
| 192 | @param port Port on which SOCKS5 server is running. |
---|
| 193 | */ |
---|
| 194 | public static void setDefaultProxy(InetAddress ipAddress,int port){ |
---|
| 195 | defaultProxy = new Socks5Proxy(ipAddress,port); |
---|
| 196 | } |
---|
| 197 | /** |
---|
| 198 | * Sets default proxy. |
---|
| 199 | @param p Proxy to use as default proxy. |
---|
| 200 | */ |
---|
| 201 | public static void setDefaultProxy(Proxy p){ |
---|
| 202 | defaultProxy = p; |
---|
| 203 | } |
---|
| 204 | |
---|
| 205 | /** |
---|
| 206 | Get current default proxy. |
---|
| 207 | * @return Current default proxy, or null if none is set. |
---|
| 208 | */ |
---|
| 209 | public static Proxy getDefaultProxy(){ |
---|
| 210 | return defaultProxy; |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | |
---|
| 214 | |
---|
| 215 | //Protected Methods |
---|
| 216 | //================= |
---|
| 217 | |
---|
| 218 | protected void startSession()throws SocksException{ |
---|
| 219 | try{ |
---|
| 220 | if(chainProxy == null) |
---|
| 221 | proxySocket = new Socket(proxyIP,proxyPort); |
---|
| 222 | else if(proxyIP != null) |
---|
| 223 | proxySocket = new SocksSocket(chainProxy,proxyIP,proxyPort); |
---|
| 224 | else |
---|
| 225 | proxySocket = new SocksSocket(chainProxy,proxyHost,proxyPort); |
---|
| 226 | |
---|
| 227 | in = proxySocket.getInputStream(); |
---|
| 228 | out = proxySocket.getOutputStream(); |
---|
| 229 | }catch(SocksException se){ |
---|
| 230 | throw se; |
---|
| 231 | }catch(IOException io_ex){ |
---|
| 232 | throw new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex); |
---|
| 233 | } |
---|
| 234 | } |
---|
| 235 | |
---|
| 236 | protected abstract Proxy copy(); |
---|
| 237 | protected abstract ProxyMessage formMessage(int cmd,InetAddress ip,int port); |
---|
| 238 | protected abstract ProxyMessage formMessage(int cmd,String host,int port) |
---|
| 239 | throws UnknownHostException; |
---|
| 240 | protected abstract ProxyMessage formMessage(InputStream in) |
---|
| 241 | throws SocksException, |
---|
| 242 | IOException; |
---|
| 243 | |
---|
| 244 | |
---|
| 245 | protected ProxyMessage connect(InetAddress ip,int port) |
---|
| 246 | throws SocksException{ |
---|
| 247 | try{ |
---|
| 248 | startSession(); |
---|
| 249 | ProxyMessage request = formMessage(SOCKS_CMD_CONNECT, |
---|
| 250 | ip,port); |
---|
| 251 | return exchange(request); |
---|
| 252 | }catch(SocksException se){ |
---|
| 253 | endSession(); |
---|
| 254 | throw se; |
---|
| 255 | } |
---|
| 256 | } |
---|
| 257 | protected ProxyMessage connect(String host,int port) |
---|
| 258 | throws UnknownHostException,SocksException{ |
---|
| 259 | try{ |
---|
| 260 | startSession(); |
---|
| 261 | ProxyMessage request = formMessage(SOCKS_CMD_CONNECT, |
---|
| 262 | host,port); |
---|
| 263 | return exchange(request); |
---|
| 264 | }catch(SocksException se){ |
---|
| 265 | endSession(); |
---|
| 266 | throw se; |
---|
| 267 | } |
---|
| 268 | } |
---|
| 269 | |
---|
| 270 | protected ProxyMessage bind(InetAddress ip,int port) |
---|
| 271 | throws SocksException{ |
---|
| 272 | try{ |
---|
| 273 | startSession(); |
---|
| 274 | ProxyMessage request = formMessage(SOCKS_CMD_BIND, |
---|
| 275 | ip,port); |
---|
| 276 | return exchange(request); |
---|
| 277 | }catch(SocksException se){ |
---|
| 278 | endSession(); |
---|
| 279 | throw se; |
---|
| 280 | } |
---|
| 281 | } |
---|
| 282 | protected ProxyMessage bind(String host,int port) |
---|
| 283 | throws UnknownHostException,SocksException{ |
---|
| 284 | try{ |
---|
| 285 | startSession(); |
---|
| 286 | ProxyMessage request = formMessage(SOCKS_CMD_BIND, |
---|
| 287 | host,port); |
---|
| 288 | return exchange(request); |
---|
| 289 | }catch(SocksException se){ |
---|
| 290 | endSession(); |
---|
| 291 | throw se; |
---|
| 292 | } |
---|
| 293 | } |
---|
| 294 | |
---|
| 295 | protected ProxyMessage accept() |
---|
| 296 | throws IOException,SocksException{ |
---|
| 297 | ProxyMessage msg; |
---|
| 298 | try{ |
---|
| 299 | msg = formMessage(in); |
---|
| 300 | }catch(InterruptedIOException iioe){ |
---|
| 301 | throw iioe; |
---|
| 302 | }catch(IOException io_ex){ |
---|
| 303 | endSession(); |
---|
| 304 | throw new SocksException(SOCKS_PROXY_IO_ERROR,"While Trying accept:" |
---|
| 305 | +io_ex); |
---|
| 306 | } |
---|
| 307 | return msg; |
---|
| 308 | } |
---|
| 309 | |
---|
| 310 | protected ProxyMessage udpAssociate(InetAddress ip,int port) |
---|
| 311 | throws SocksException{ |
---|
| 312 | try{ |
---|
| 313 | startSession(); |
---|
| 314 | ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE, |
---|
| 315 | ip,port); |
---|
| 316 | if(request != null) |
---|
| 317 | return exchange(request); |
---|
| 318 | }catch(SocksException se){ |
---|
| 319 | endSession(); |
---|
| 320 | throw se; |
---|
| 321 | } |
---|
| 322 | //Only get here if request was null |
---|
| 323 | endSession(); |
---|
| 324 | throw new SocksException(SOCKS_METHOD_NOTSUPPORTED, |
---|
| 325 | "This version of proxy does not support UDP associate, use version 5"); |
---|
| 326 | } |
---|
| 327 | protected ProxyMessage udpAssociate(String host,int port) |
---|
| 328 | throws UnknownHostException,SocksException{ |
---|
| 329 | try{ |
---|
| 330 | startSession(); |
---|
| 331 | ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE, |
---|
| 332 | host,port); |
---|
| 333 | if(request != null) return exchange(request); |
---|
| 334 | }catch(SocksException se){ |
---|
| 335 | endSession(); |
---|
| 336 | throw se; |
---|
| 337 | } |
---|
| 338 | //Only get here if request was null |
---|
| 339 | endSession(); |
---|
| 340 | throw new SocksException(SOCKS_METHOD_NOTSUPPORTED, |
---|
| 341 | "This version of proxy does not support UDP associate, use version 5"); |
---|
| 342 | } |
---|
| 343 | |
---|
| 344 | |
---|
| 345 | protected void endSession(){ |
---|
| 346 | try{ |
---|
| 347 | if(proxySocket!=null) proxySocket.close(); |
---|
| 348 | proxySocket = null; |
---|
| 349 | }catch(IOException io_ex){ |
---|
| 350 | } |
---|
| 351 | } |
---|
| 352 | |
---|
| 353 | /** |
---|
| 354 | *Sends the request to SOCKS server |
---|
| 355 | */ |
---|
| 356 | protected void sendMsg(ProxyMessage msg)throws SocksException, |
---|
| 357 | IOException{ |
---|
| 358 | msg.write(out); |
---|
| 359 | } |
---|
| 360 | |
---|
| 361 | /** |
---|
| 362 | * Reads the reply from the SOCKS server |
---|
| 363 | */ |
---|
| 364 | protected ProxyMessage readMsg()throws SocksException, |
---|
| 365 | IOException{ |
---|
| 366 | return formMessage(in); |
---|
| 367 | } |
---|
| 368 | /** |
---|
| 369 | *Sends the request reads reply and returns it |
---|
| 370 | *throws exception if something wrong with IO |
---|
| 371 | *or the reply code is not zero |
---|
| 372 | */ |
---|
| 373 | protected ProxyMessage exchange(ProxyMessage request) |
---|
| 374 | throws SocksException{ |
---|
| 375 | ProxyMessage reply; |
---|
| 376 | try{ |
---|
| 377 | request.write(out); |
---|
| 378 | reply = formMessage(in); |
---|
| 379 | }catch(SocksException s_ex){ |
---|
| 380 | throw s_ex; |
---|
| 381 | }catch(IOException ioe){ |
---|
| 382 | throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+ioe)); |
---|
| 383 | } |
---|
| 384 | return reply; |
---|
| 385 | } |
---|
| 386 | |
---|
| 387 | |
---|
| 388 | //Private methods |
---|
| 389 | //=============== |
---|
| 390 | |
---|
| 391 | |
---|
| 392 | //Constants |
---|
| 393 | |
---|
| 394 | public static final int SOCKS_SUCCESS =0; |
---|
| 395 | public static final int SOCKS_FAILURE =1; |
---|
| 396 | public static final int SOCKS_BADCONNECT =2; |
---|
| 397 | public static final int SOCKS_BADNETWORK =3; |
---|
| 398 | public static final int SOCKS_HOST_UNREACHABLE =4; |
---|
| 399 | public static final int SOCKS_CONNECTION_REFUSED =5; |
---|
| 400 | public static final int SOCKS_TTL_EXPIRE =6; |
---|
| 401 | public static final int SOCKS_CMD_NOT_SUPPORTED =7; |
---|
| 402 | public static final int SOCKS_ADDR_NOT_SUPPORTED =8; |
---|
| 403 | |
---|
| 404 | public static final int SOCKS_NO_PROXY =1<<16; |
---|
| 405 | public static final int SOCKS_PROXY_NO_CONNECT =2<<16; |
---|
| 406 | public static final int SOCKS_PROXY_IO_ERROR =3<<16; |
---|
| 407 | public static final int SOCKS_AUTH_NOT_SUPPORTED =4<<16; |
---|
| 408 | public static final int SOCKS_AUTH_FAILURE =5<<16; |
---|
| 409 | public static final int SOCKS_JUST_ERROR =6<<16; |
---|
| 410 | |
---|
| 411 | public static final int SOCKS_DIRECT_FAILED =7<<16; |
---|
| 412 | public static final int SOCKS_METHOD_NOTSUPPORTED =8<<16; |
---|
| 413 | |
---|
| 414 | |
---|
| 415 | static final int SOCKS_CMD_CONNECT =0x1; |
---|
| 416 | static final int SOCKS_CMD_BIND =0x2; |
---|
| 417 | static final int SOCKS_CMD_UDP_ASSOCIATE =0x3; |
---|
| 418 | |
---|
| 419 | } |
---|