KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcraft > jsch > ProxySOCKS5


1 /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
2 /*
3 Copyright (c) 2002,2003,2004,2005,2006 ymnk, JCraft,Inc. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8   1. Redistributions of source code must retain the above copyright notice,
9      this list of conditions and the following disclaimer.
10
11   2. Redistributions in binary form must reproduce the above copyright
12      notice, this list of conditions and the following disclaimer in
13      the documentation and/or other materials provided with the distribution.
14
15   3. The names of the authors may not be used to endorse or promote products
16      derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
21 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */

29
30 /*
31  This file depends on following documents,
32    - RFC 1928 SOCKS Protocol Verseion 5
33    - RFC 1929 Username/Password Authentication for SOCKS V5.
34  */

35
36 package com.jcraft.jsch;
37
38 import java.io.*;
39 import java.net.*;
40
41 public class ProxySOCKS5 implements Proxy{
42   private static int DEFAULTPORT=1080;
43   private String JavaDoc proxy_host;
44   private int proxy_port;
45   private InputStream in;
46   private OutputStream out;
47   private Socket socket;
48   private String JavaDoc user;
49   private String JavaDoc passwd;
50
51   public ProxySOCKS5(String JavaDoc proxy_host){
52     int port=DEFAULTPORT;
53     String JavaDoc host=proxy_host;
54     if(proxy_host.indexOf(':')!=-1){
55       try{
56     host=proxy_host.substring(0, proxy_host.indexOf(':'));
57     port=Integer.parseInt(proxy_host.substring(proxy_host.indexOf(':')+1));
58       }
59       catch(Exception JavaDoc e){
60       }
61     }
62     this.proxy_host=host;
63     this.proxy_port=port;
64   }
65   public ProxySOCKS5(String JavaDoc proxy_host, int proxy_port){
66     this.proxy_host=proxy_host;
67     this.proxy_port=proxy_port;
68   }
69   public void setUserPasswd(String JavaDoc user, String JavaDoc passwd){
70     this.user=user;
71     this.passwd=passwd;
72   }
73   public void connect(SocketFactory socket_factory, String JavaDoc host, int port, int timeout) throws JSchException{
74     try{
75       if(socket_factory==null){
76         socket=Util.createSocket(proxy_host, proxy_port, timeout);
77         //socket=new Socket(proxy_host, proxy_port);
78
in=socket.getInputStream();
79         out=socket.getOutputStream();
80       }
81       else{
82         socket=socket_factory.createSocket(proxy_host, proxy_port);
83         in=socket_factory.getInputStream(socket);
84         out=socket_factory.getOutputStream(socket);
85       }
86       if(timeout>0){
87         socket.setSoTimeout(timeout);
88       }
89       socket.setTcpNoDelay(true);
90
91       byte[] buf=new byte[1024];
92       int index=0;
93
94 /*
95                    +----+----------+----------+
96                    |VER | NMETHODS | METHODS |
97                    +----+----------+----------+
98                    | 1 | 1 | 1 to 255 |
99                    +----+----------+----------+
100
101    The VER field is set to X'05' for this version of the protocol. The
102    NMETHODS field contains the number of method identifier octets that
103    appear in the METHODS field.
104
105    The values currently defined for METHOD are:
106
107           o X'00' NO AUTHENTICATION REQUIRED
108           o X'01' GSSAPI
109           o X'02' USERNAME/PASSWORD
110           o X'03' to X'7F' IANA ASSIGNED
111           o X'80' to X'FE' RESERVED FOR PRIVATE METHODS
112           o X'FF' NO ACCEPTABLE METHODS
113 */

114
115       buf[index++]=5;
116
117       buf[index++]=2;
118       buf[index++]=0; // NO AUTHENTICATION REQUIRED
119
buf[index++]=2; // USERNAME/PASSWORD
120

121       out.write(buf, 0, index);
122
123 /*
124     The server selects from one of the methods given in METHODS, and
125     sends a METHOD selection message:
126
127                          +----+--------+
128                          |VER | METHOD |
129                          +----+--------+
130                          | 1 | 1 |
131                          +----+--------+
132 */

133       //in.read(buf, 0, 2);
134
fill(in, buf, 2);
135  
136       boolean check=false;
137       switch((buf[1])&0xff){
138         case 0: // NO AUTHENTICATION REQUIRED
139
check=true;
140           break;
141         case 2: // USERNAME/PASSWORD
142
if(user==null || passwd==null)break;
143
144 /*
145    Once the SOCKS V5 server has started, and the client has selected the
146    Username/Password Authentication protocol, the Username/Password
147    subnegotiation begins. This begins with the client producing a
148    Username/Password request:
149
150            +----+------+----------+------+----------+
151            |VER | ULEN | UNAME | PLEN | PASSWD |
152            +----+------+----------+------+----------+
153            | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
154            +----+------+----------+------+----------+
155
156    The VER field contains the current version of the subnegotiation,
157    which is X'01'. The ULEN field contains the length of the UNAME field
158    that follows. The UNAME field contains the username as known to the
159    source operating system. The PLEN field contains the length of the
160    PASSWD field that follows. The PASSWD field contains the password
161    association with the given UNAME.
162 */

163           index=0;
164           buf[index++]=1;
165           buf[index++]=(byte)(user.length());
166       System.arraycopy(user.getBytes(), 0, buf, index, user.length());
167       index+=user.length();
168           buf[index++]=(byte)(passwd.length());
169       System.arraycopy(passwd.getBytes(), 0, buf, index, passwd.length());
170       index+=passwd.length();
171
172           out.write(buf, 0, index);
173
174 /*
175    The server verifies the supplied UNAME and PASSWD, and sends the
176    following response:
177
178                         +----+--------+
179                         |VER | STATUS |
180                         +----+--------+
181                         | 1 | 1 |
182                         +----+--------+
183
184    A STATUS field of X'00' indicates success. If the server returns a
185    `failure' (STATUS value other than X'00') status, it MUST close the
186    connection.
187 */

188           //in.read(buf, 0, 2);
189
fill(in, buf, 2);
190           if(buf[1]==0)
191             check=true;
192           break;
193         default:
194       }
195
196       if(!check){
197         try{ socket.close(); }
198     catch(Exception JavaDoc eee){
199     }
200         throw new JSchException("fail in SOCKS5 proxy");
201       }
202
203 /*
204       The SOCKS request is formed as follows:
205
206         +----+-----+-------+------+----------+----------+
207         |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
208         +----+-----+-------+------+----------+----------+
209         | 1 | 1 | X'00' | 1 | Variable | 2 |
210         +----+-----+-------+------+----------+----------+
211
212       Where:
213
214       o VER protocol version: X'05'
215       o CMD
216          o CONNECT X'01'
217          o BIND X'02'
218          o UDP ASSOCIATE X'03'
219       o RSV RESERVED
220          o ATYP address type of following address
221          o IP V4 address: X'01'
222          o DOMAINNAME: X'03'
223          o IP V6 address: X'04'
224       o DST.ADDR desired destination address
225       o DST.PORT desired destination port in network octet
226          order
227 */

228      
229       index=0;
230       buf[index++]=5;
231       buf[index++]=1; // CONNECT
232
buf[index++]=0;
233
234       byte[] hostb=host.getBytes();
235       int len=hostb.length;
236       buf[index++]=3; // DOMAINNAME
237
buf[index++]=(byte)(len);
238       System.arraycopy(hostb, 0, buf, index, len);
239       index+=len;
240       buf[index++]=(byte)(port>>>8);
241       buf[index++]=(byte)(port&0xff);
242
243       out.write(buf, 0, index);
244
245 /*
246    The SOCKS request information is sent by the client as soon as it has
247    established a connection to the SOCKS server, and completed the
248    authentication negotiations. The server evaluates the request, and
249    returns a reply formed as follows:
250
251         +----+-----+-------+------+----------+----------+
252         |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
253         +----+-----+-------+------+----------+----------+
254         | 1 | 1 | X'00' | 1 | Variable | 2 |
255         +----+-----+-------+------+----------+----------+
256
257    Where:
258
259    o VER protocol version: X'05'
260    o REP Reply field:
261       o X'00' succeeded
262       o X'01' general SOCKS server failure
263       o X'02' connection not allowed by ruleset
264       o X'03' Network unreachable
265       o X'04' Host unreachable
266       o X'05' Connection refused
267       o X'06' TTL expired
268       o X'07' Command not supported
269       o X'08' Address type not supported
270       o X'09' to X'FF' unassigned
271     o RSV RESERVED
272     o ATYP address type of following address
273       o IP V4 address: X'01'
274       o DOMAINNAME: X'03'
275       o IP V6 address: X'04'
276     o BND.ADDR server bound address
277     o BND.PORT server bound port in network octet order
278 */

279
280       //in.read(buf, 0, 4);
281
fill(in, buf, 4);
282
283       if(buf[1]!=0){
284         try{ socket.close(); }
285     catch(Exception JavaDoc eee){
286     }
287         throw new JSchException("ProxySOCKS5: server returns "+buf[1]);
288       }
289
290       switch(buf[3]&0xff){
291         case 1:
292           //in.read(buf, 0, 6);
293
fill(in, buf, 6);
294       break;
295         case 3:
296           //in.read(buf, 0, 1);
297
fill(in, buf, 1);
298           //in.read(buf, 0, buf[0]+2);
299
fill(in, buf, (buf[0]&0xff)+2);
300       break;
301         case 4:
302           //in.read(buf, 0, 18);
303
fill(in, buf, 18);
304           break;
305         default:
306       }
307     }
308     catch(RuntimeException JavaDoc e){
309       throw e;
310     }
311     catch(Exception JavaDoc e){
312       try{ if(socket!=null)socket.close(); }
313       catch(Exception JavaDoc eee){
314       }
315       String JavaDoc message="ProxySOCKS5: "+e.toString();
316       if(e instanceof Throwable JavaDoc)
317         throw new JSchException(message, (Throwable JavaDoc)e);
318       throw new JSchException(message);
319     }
320   }
321   public InputStream getInputStream(){ return in; }
322   public OutputStream getOutputStream(){ return out; }
323   public Socket getSocket(){ return socket; }
324   public void close(){
325     try{
326       if(in!=null)in.close();
327       if(out!=null)out.close();
328       if(socket!=null)socket.close();
329     }
330     catch(Exception JavaDoc e){
331     }
332     in=null;
333     out=null;
334     socket=null;
335   }
336   public static int getDefaultPort(){
337     return DEFAULTPORT;
338   }
339   private void fill(InputStream in, byte[] buf, int len) throws JSchException, IOException{
340     int s=0;
341     while(s<len){
342       int i=in.read(buf, s, len-s);
343       if(i<=0){
344         throw new JSchException("ProxySOCKS5: stream is closed");
345       }
346       s+=i;
347     }
348   }
349 }
350
Popular Tags