00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 package com.jcraft.jsch;
00037
00038 import java.io.*;
00039 import java.net.*;
00040
00041
00051 public class ProxySOCKS5 implements Proxy{
00052 private static int DEFAULTPORT=1080;
00053 private String proxy_host;
00054 private int proxy_port;
00055 private InputStream in;
00056 private OutputStream out;
00057 private Socket socket;
00058 private String user;
00059 private String passwd;
00060
00066 public ProxySOCKS5(String proxy_host){
00067 int port=DEFAULTPORT;
00068 String host=proxy_host;
00069 if(proxy_host.indexOf(':')!=-1){
00070 try{
00071 host=proxy_host.substring(0, proxy_host.indexOf(':'));
00072 port=Integer.parseInt(proxy_host.substring(proxy_host.indexOf(':')+1));
00073 }
00074 catch(Exception e){
00075 }
00076 }
00077 this.proxy_host=host;
00078 this.proxy_port=port;
00079 }
00080
00086 public ProxySOCKS5(String proxy_host, int proxy_port){
00087 this.proxy_host=proxy_host;
00088 this.proxy_port=proxy_port;
00089 }
00090
00105 public void setUserPasswd(String user, String passwd){
00106 this.user=user;
00107 this.passwd=passwd;
00108 }
00109
00110
00111 public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws JSchException{
00112 try{
00113 if(socket_factory==null){
00114 socket=Util.createSocket(proxy_host, proxy_port, timeout);
00115
00116 in=socket.getInputStream();
00117 out=socket.getOutputStream();
00118 }
00119 else{
00120 socket=socket_factory.createSocket(proxy_host, proxy_port);
00121 in=socket_factory.getInputStream(socket);
00122 out=socket_factory.getOutputStream(socket);
00123 }
00124 if(timeout>0){
00125 socket.setSoTimeout(timeout);
00126 }
00127 socket.setTcpNoDelay(true);
00128
00129 byte[] buf=new byte[1024];
00130 int index=0;
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 buf[index++]=5;
00154
00155 buf[index++]=2;
00156
00157 buf[index++]=0;
00158 buf[index++]=2;
00159
00160
00161
00162
00163
00164 out.write(buf, 0, index);
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 fill(in, buf, 2);
00178
00179 boolean check=false;
00180 switch((buf[1])&0xff){
00181 case 0:
00182 check=true;
00183 break;
00184 case 2:
00185 if(user==null || passwd==null)break;
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 index=0;
00207 buf[index++]=1;
00208 buf[index++]=(byte)(user.length());
00209 System.arraycopy(Util.str2byte(user), 0, buf, index, user.length());
00210 index+=user.length();
00211 buf[index++]=(byte)(passwd.length());
00212 System.arraycopy(Util.str2byte(passwd), 0, buf, index, passwd.length());
00213 index+=passwd.length();
00214
00215 out.write(buf, 0, index);
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 fill(in, buf, 2);
00233 if(buf[1]==0)
00234 check=true;
00235 break;
00236 default:
00237 }
00238
00239 if(!check){
00240 try{ socket.close(); }
00241 catch(Exception eee){
00242 }
00243 throw new JSchException("fail in SOCKS5 proxy");
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 index=0;
00273 buf[index++]=5;
00274 buf[index++]=1;
00275 buf[index++]=0;
00276
00277 byte[] hostb=Util.str2byte(host);
00278 int len=hostb.length;
00279 buf[index++]=3;
00280 buf[index++]=(byte)(len);
00281 System.arraycopy(hostb, 0, buf, index, len);
00282 index+=len;
00283 buf[index++]=(byte)(port>>>8);
00284 buf[index++]=(byte)(port&0xff);
00285
00286 out.write(buf, 0, index);
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 fill(in, buf, 4);
00325
00326 if(buf[1]!=0){
00327 try{ socket.close(); }
00328 catch(Exception eee){
00329 }
00330 throw new JSchException("ProxySOCKS5: server returns "+buf[1]);
00331 }
00332
00333 switch(buf[3]&0xff){
00334 case 1:
00335
00336 fill(in, buf, 6);
00337 break;
00338 case 3:
00339
00340 fill(in, buf, 1);
00341
00342 fill(in, buf, (buf[0]&0xff)+2);
00343 break;
00344 case 4:
00345
00346 fill(in, buf, 18);
00347 break;
00348 default:
00349 }
00350 }
00351 catch(RuntimeException e){
00352 throw e;
00353 }
00354 catch(Exception e){
00355 try{ if(socket!=null)socket.close(); }
00356 catch(Exception eee){
00357 }
00358 String message="ProxySOCKS5: "+e.toString();
00359 if(e instanceof Throwable)
00360 throw new JSchException(message, (Throwable)e);
00361 throw new JSchException(message);
00362 }
00363 }
00364
00365 public InputStream getInputStream(){ return in; }
00366
00367 public OutputStream getOutputStream(){ return out; }
00368
00369 public Socket getSocket(){ return socket; }
00370
00371 public void close(){
00372 try{
00373 if(in!=null)in.close();
00374 if(out!=null)out.close();
00375 if(socket!=null)socket.close();
00376 }
00377 catch(Exception e){
00378 }
00379 in=null;
00380 out=null;
00381 socket=null;
00382 }
00383
00387 public static int getDefaultPort(){
00388 return DEFAULTPORT;
00389 }
00390
00391 private void fill(InputStream in, byte[] buf, int len) throws JSchException, IOException{
00392 int s=0;
00393 while(s<len){
00394 int i=in.read(buf, s, len-s);
00395 if(i<=0){
00396 throw new JSchException("ProxySOCKS5: stream is closed");
00397 }
00398 s+=i;
00399 }
00400 }
00401 }