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 package com.jcraft.jsch;
00031
00032 import java.io.*;
00033 import java.net.*;
00034
00046 public class Session
00047 implements Runnable
00048 {
00049 static private final String version="JSCH-0.1.45";
00050
00051
00052
00053 static final int SSH_MSG_DISCONNECT= 1;
00054 static final int SSH_MSG_IGNORE= 2;
00055 static final int SSH_MSG_UNIMPLEMENTED= 3;
00056 static final int SSH_MSG_DEBUG= 4;
00057 static final int SSH_MSG_SERVICE_REQUEST= 5;
00058 static final int SSH_MSG_SERVICE_ACCEPT= 6;
00059 static final int SSH_MSG_KEXINIT= 20;
00060 static final int SSH_MSG_NEWKEYS= 21;
00061 static final int SSH_MSG_KEXDH_INIT= 30;
00062 static final int SSH_MSG_KEXDH_REPLY= 31;
00063 static final int SSH_MSG_KEX_DH_GEX_GROUP= 31;
00064 static final int SSH_MSG_KEX_DH_GEX_INIT= 32;
00065 static final int SSH_MSG_KEX_DH_GEX_REPLY= 33;
00066 static final int SSH_MSG_KEX_DH_GEX_REQUEST= 34;
00067 static final int SSH_MSG_GLOBAL_REQUEST= 80;
00068 static final int SSH_MSG_REQUEST_SUCCESS= 81;
00069 static final int SSH_MSG_REQUEST_FAILURE= 82;
00070 static final int SSH_MSG_CHANNEL_OPEN= 90;
00071 static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION= 91;
00072 static final int SSH_MSG_CHANNEL_OPEN_FAILURE= 92;
00073 static final int SSH_MSG_CHANNEL_WINDOW_ADJUST= 93;
00074 static final int SSH_MSG_CHANNEL_DATA= 94;
00075 static final int SSH_MSG_CHANNEL_EXTENDED_DATA= 95;
00076 static final int SSH_MSG_CHANNEL_EOF= 96;
00077 static final int SSH_MSG_CHANNEL_CLOSE= 97;
00078 static final int SSH_MSG_CHANNEL_REQUEST= 98;
00079 static final int SSH_MSG_CHANNEL_SUCCESS= 99;
00080 static final int SSH_MSG_CHANNEL_FAILURE= 100;
00081
00082 private static final int PACKET_MAX_SIZE = 256 * 1024;
00083
00084 private byte[] V_S;
00085 private byte[] V_C=Util.str2byte("SSH-2.0-"+version);
00086
00087 private byte[] I_C;
00088 private byte[] I_S;
00089 private byte[] K_S;
00090
00091 private byte[] session_id;
00092
00093 private byte[] IVc2s;
00094 private byte[] IVs2c;
00095 private byte[] Ec2s;
00096 private byte[] Es2c;
00097 private byte[] MACc2s;
00098 private byte[] MACs2c;
00099
00100 private int seqi=0;
00101 private int seqo=0;
00102
00103 String[] guess=null;
00104 private Cipher s2ccipher;
00105 private Cipher c2scipher;
00106 private MAC s2cmac;
00107 private MAC c2smac;
00108
00109 private byte[] s2cmac_result1;
00110 private byte[] s2cmac_result2;
00111
00112 private Compression deflater;
00113 private Compression inflater;
00114
00115 private IO io;
00116 private Socket socket;
00117 private int timeout=0;
00118
00119 private volatile boolean isConnected=false;
00120
00121 private boolean isAuthed=false;
00122
00123 private Thread connectThread=null;
00124 private Object lock=new Object();
00125
00126 boolean x11_forwarding=false;
00127 boolean agent_forwarding=false;
00128
00129 InputStream in=null;
00130 OutputStream out=null;
00131
00132 static Random random;
00133
00134 Buffer buf;
00135 Packet packet;
00136
00137 SocketFactory socket_factory=null;
00138
00139 static final int buffer_margin = 32 +
00140 20 +
00141 32;
00142
00143 private java.util.Hashtable config=null;
00144
00145 private Proxy proxy=null;
00146 private UserInfo userinfo;
00147
00148 private String hostKeyAlias=null;
00149 private int serverAliveInterval=0;
00150 private int serverAliveCountMax=1;
00151
00152 protected boolean daemon_thread=false;
00153
00154 private long kex_start_time=0L;
00155
00156 String host="127.0.0.1";
00157 int port=22;
00158
00159 String username=null;
00160 byte[] password=null;
00161
00162 JSch jsch;
00163
00167 Session(JSch jsch) throws JSchException{
00168 super();
00169 this.jsch=jsch;
00170 buf=new Buffer();
00171 packet=new Packet(buf);
00172 }
00173
00179 public void connect() throws JSchException{
00180 connect(timeout);
00181 }
00182
00189 public void connect(int connectTimeout) throws JSchException{
00190 if(isConnected){
00191 throw new JSchException("session is already connected");
00192 }
00193
00194 io=new IO();
00195 if(random==null){
00196 try{
00197 Class c=Class.forName(getConfig("random"));
00198 random=(Random)(c.newInstance());
00199 }
00200 catch(Exception e){
00201 throw new JSchException(e.toString(), e);
00202 }
00203 }
00204 Packet.setRandom(random);
00205
00206 if(JSch.getLogger().isEnabled(Logger.INFO)){
00207 JSch.getLogger().log(Logger.INFO,
00208 "Connecting to "+host+" port "+port);
00209 }
00210
00211 try {
00212 int i, j;
00213
00214 if(proxy==null){
00215 InputStream in;
00216 OutputStream out;
00217 if(socket_factory==null){
00218 socket=Util.createSocket(host, port, connectTimeout);
00219 in=socket.getInputStream();
00220 out=socket.getOutputStream();
00221 }
00222 else{
00223 socket=socket_factory.createSocket(host, port);
00224 in=socket_factory.getInputStream(socket);
00225 out=socket_factory.getOutputStream(socket);
00226 }
00227
00228 socket.setTcpNoDelay(true);
00229 io.setInputStream(in);
00230 io.setOutputStream(out);
00231 }
00232 else{
00233 synchronized(proxy){
00234 proxy.connect(socket_factory, host, port, connectTimeout);
00235 io.setInputStream(proxy.getInputStream());
00236 io.setOutputStream(proxy.getOutputStream());
00237 socket=proxy.getSocket();
00238 }
00239 }
00240
00241 if(connectTimeout>0 && socket!=null){
00242 socket.setSoTimeout(connectTimeout);
00243 }
00244
00245 isConnected=true;
00246
00247 if(JSch.getLogger().isEnabled(Logger.INFO)){
00248 JSch.getLogger().log(Logger.INFO,
00249 "Connection established");
00250 }
00251
00252 jsch.addSession(this);
00253
00254 {
00255
00256 byte[] foo=new byte[V_C.length+1];
00257 System.arraycopy(V_C, 0, foo, 0, V_C.length);
00258 foo[foo.length-1]=(byte)'\n';
00259 io.put(foo, 0, foo.length);
00260 }
00261
00262 while(true){
00263 i=0;
00264 j=0;
00265 while(i<buf.buffer.length){
00266 j=io.getByte();
00267 if(j<0)break;
00268 buf.buffer[i]=(byte)j; i++;
00269 if(j==10)break;
00270 }
00271 if(j<0){
00272 throw new JSchException("connection is closed by foreign host");
00273 }
00274
00275 if(buf.buffer[i-1]==10){
00276 i--;
00277 if(i>0 && buf.buffer[i-1]==13){
00278 i--;
00279 }
00280 }
00281
00282 if(i<=3 ||
00283 ((i!=buf.buffer.length) &&
00284 (buf.buffer[0]!='S'||buf.buffer[1]!='S'||
00285 buf.buffer[2]!='H'||buf.buffer[3]!='-'))){
00286
00287
00288 continue;
00289 }
00290
00291 if(i==buf.buffer.length ||
00292 i<7 ||
00293 (buf.buffer[4]=='1' && buf.buffer[6]!='9')
00294 ){
00295 throw new JSchException("invalid server's version string");
00296 }
00297 break;
00298 }
00299
00300 V_S=new byte[i]; System.arraycopy(buf.buffer, 0, V_S, 0, i);
00301
00302
00303 if(JSch.getLogger().isEnabled(Logger.INFO)){
00304 JSch.getLogger().log(Logger.INFO,
00305 "Remote version string: "+Util.byte2str(V_S));
00306 JSch.getLogger().log(Logger.INFO,
00307 "Local version string: "+Util.byte2str(V_C));
00308 }
00309
00310 send_kexinit();
00311
00312 buf=read(buf);
00313 if(buf.getCommand()!=SSH_MSG_KEXINIT){
00314 in_kex=false;
00315 throw new JSchException("invalid protocol: "+buf.getCommand());
00316 }
00317
00318 if(JSch.getLogger().isEnabled(Logger.INFO)){
00319 JSch.getLogger().log(Logger.INFO,
00320 "SSH_MSG_KEXINIT received");
00321 }
00322
00323 KeyExchange kex=receive_kexinit(buf);
00324
00325 while(true){
00326 buf=read(buf);
00327 if(kex.getState()==buf.getCommand()){
00328 kex_start_time=System.currentTimeMillis();
00329 boolean result=kex.next(buf);
00330 if(!result){
00331
00332 in_kex=false;
00333 throw new JSchException("verify: "+result);
00334 }
00335 }
00336 else{
00337 in_kex=false;
00338 throw new JSchException("invalid protocol(kex): "+buf.getCommand());
00339 }
00340 if(kex.getState()==KeyExchange.STATE_END){
00341 break;
00342 }
00343 }
00344
00345 try{ checkHost(host, port, kex); }
00346 catch(JSchException ee){
00347 in_kex=false;
00348 throw ee;
00349 }
00350
00351 send_newkeys();
00352
00353
00354 buf=read(buf);
00355
00356 if(buf.getCommand()==SSH_MSG_NEWKEYS){
00357
00358 if(JSch.getLogger().isEnabled(Logger.INFO)){
00359 JSch.getLogger().log(Logger.INFO,
00360 "SSH_MSG_NEWKEYS received");
00361 }
00362
00363 receive_newkeys(buf, kex);
00364 }
00365 else{
00366 in_kex=false;
00367 throw new JSchException("invalid protocol(newkyes): "+buf.getCommand());
00368 }
00369
00370 boolean auth=false;
00371 boolean auth_cancel=false;
00372
00373 UserAuth ua=null;
00374 try{
00375 Class c=Class.forName(getConfig("userauth.none"));
00376 ua=(UserAuth)(c.newInstance());
00377 }
00378 catch(Exception e){
00379 throw new JSchException(e.toString(), e);
00380 }
00381
00382 auth=ua.start(this);
00383
00384 String cmethods=getConfig("PreferredAuthentications");
00385
00386 String[] cmethoda=Util.split(cmethods, ",");
00387
00388 String smethods=null;
00389 if(!auth){
00390 smethods=((UserAuthNone)ua).getMethods();
00391 if(smethods!=null){
00392 smethods=smethods.toLowerCase();
00393 }
00394 else{
00395
00396
00397 smethods=cmethods;
00398 }
00399 }
00400
00401 String[] smethoda=Util.split(smethods, ",");
00402
00403 int methodi=0;
00404
00405 loop:
00406 while(true){
00407
00408 while(!auth &&
00409 cmethoda!=null && methodi<cmethoda.length){
00410
00411 String method=cmethoda[methodi++];
00412 boolean acceptable=false;
00413 for(int k=0; k<smethoda.length; k++){
00414 if(smethoda[k].equals(method)){
00415 acceptable=true;
00416 break;
00417 }
00418 }
00419 if(!acceptable){
00420 continue;
00421 }
00422
00423
00424
00425 if(JSch.getLogger().isEnabled(Logger.INFO)){
00426 String str="Authentications that can continue: ";
00427 for(int k=methodi-1; k<cmethoda.length; k++){
00428 str+=cmethoda[k];
00429 if(k+1<cmethoda.length)
00430 str+=",";
00431 }
00432 JSch.getLogger().log(Logger.INFO,
00433 str);
00434 JSch.getLogger().log(Logger.INFO,
00435 "Next authentication method: "+method);
00436 }
00437
00438 ua=null;
00439 try{
00440 Class c=null;
00441 if(getConfig("userauth."+method)!=null){
00442 c=Class.forName(getConfig("userauth."+method));
00443 ua=(UserAuth)(c.newInstance());
00444 }
00445 }
00446 catch(Exception e){
00447 if(JSch.getLogger().isEnabled(Logger.WARN)){
00448 JSch.getLogger().log(Logger.WARN,
00449 "failed to load "+method+" method");
00450 }
00451 }
00452
00453 if(ua!=null){
00454 auth_cancel=false;
00455 try{
00456 auth=ua.start(this);
00457 if(auth &&
00458 JSch.getLogger().isEnabled(Logger.INFO)){
00459 JSch.getLogger().log(Logger.INFO,
00460 "Authentication succeeded ("+method+").");
00461 }
00462 }
00463 catch(JSchAuthCancelException ee){
00464 auth_cancel=true;
00465 }
00466 catch(JSchPartialAuthException ee){
00467 String tmp = smethods;
00468 smethods=ee.getMethods();
00469 smethoda=Util.split(smethods, ",");
00470 if(!tmp.equals(smethods)){
00471 methodi=0;
00472 }
00473
00474 auth_cancel=false;
00475 continue loop;
00476 }
00477 catch(RuntimeException ee){
00478 throw ee;
00479 }
00480 catch(Exception ee){
00481
00482 break loop;
00483 }
00484 }
00485 }
00486 break;
00487 }
00488
00489 if(!auth){
00490 if(auth_cancel)
00491 throw new JSchException("Auth cancel");
00492 throw new JSchException("Auth fail");
00493 }
00494
00495 if(connectTimeout>0 || timeout>0){
00496 socket.setSoTimeout(timeout);
00497 }
00498
00499 isAuthed=true;
00500
00501 synchronized(lock){
00502 if(isConnected){
00503 connectThread=new Thread(this);
00504 connectThread.setName("Connect thread "+host+" session");
00505 if(daemon_thread){
00506 connectThread.setDaemon(daemon_thread);
00507 }
00508 connectThread.start();
00509 }
00510 else{
00511
00512
00513 }
00514 }
00515 }
00516 catch(Exception e) {
00517 in_kex=false;
00518 if(isConnected){
00519 try{
00520 packet.reset();
00521 buf.putByte((byte)SSH_MSG_DISCONNECT);
00522 buf.putInt(3);
00523 buf.putString(Util.str2byte(e.toString()));
00524 buf.putString(Util.str2byte("en"));
00525 write(packet);
00526 disconnect();
00527 }
00528 catch(Exception ee){
00529 }
00530 }
00531 isConnected=false;
00532
00533 if(e instanceof RuntimeException) throw (RuntimeException)e;
00534 if(e instanceof JSchException) throw (JSchException)e;
00535 throw new JSchException("Session.connect: "+e);
00536 }
00537 finally{
00538 Util.bzero(this.password);
00539 this.password=null;
00540 }
00541 }
00542
00547 private KeyExchange receive_kexinit(Buffer buf) throws Exception {
00548 int j=buf.getInt();
00549 if(j!=buf.getLength()){
00550 buf.getByte();
00551 I_S=new byte[buf.index-5];
00552 }
00553 else{
00554 I_S=new byte[j-1-buf.getByte()];
00555 }
00556 System.arraycopy(buf.buffer, buf.s, I_S, 0, I_S.length);
00557
00558 if(!in_kex){
00559 send_kexinit();
00560 }
00561
00562 guess=KeyExchange.guess(I_S, I_C);
00563 if(guess==null){
00564 throw new JSchException("Algorithm negotiation fail");
00565 }
00566
00567 if(!isAuthed &&
00568 (guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS].equals("none") ||
00569 (guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC].equals("none")))){
00570 throw new JSchException("NONE Cipher should not be chosen before authentification is successed.");
00571 }
00572
00573 KeyExchange kex=null;
00574 try{
00575 Class c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_KEX_ALGS]));
00576 kex=(KeyExchange)(c.newInstance());
00577 }
00578 catch(Exception e){
00579 throw new JSchException(e.toString(), e);
00580 }
00581
00582 kex.init(this, V_S, V_C, I_S, I_C);
00583 return kex;
00584 }
00585
00586 private boolean in_kex=false;
00587
00593 public void rekey() throws Exception {
00594 send_kexinit();
00595 }
00596 private void send_kexinit() throws Exception {
00597 if(in_kex)
00598 return;
00599
00600 String cipherc2s=getConfig("cipher.c2s");
00601 String ciphers2c=getConfig("cipher.s2c");
00602
00603 String[] not_available_ciphers=checkCiphers(getConfig("CheckCiphers"));
00604 if(not_available_ciphers!=null && not_available_ciphers.length>0){
00605 cipherc2s=Util.diffString(cipherc2s, not_available_ciphers);
00606 ciphers2c=Util.diffString(ciphers2c, not_available_ciphers);
00607 if(cipherc2s==null || ciphers2c==null){
00608 throw new JSchException("There are not any available ciphers.");
00609 }
00610 }
00611
00612 String kex=getConfig("kex");
00613 String[] not_available_kexes=checkKexes(getConfig("CheckKexes"));
00614 if(not_available_kexes!=null && not_available_kexes.length>0){
00615 kex=Util.diffString(kex, not_available_kexes);
00616 if(kex==null){
00617 throw new JSchException("There are not any available kexes.");
00618 }
00619 }
00620
00621 in_kex=true;
00622 kex_start_time=System.currentTimeMillis();
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 Buffer buf = new Buffer();
00637 Packet packet = new Packet(buf);
00638 packet.reset();
00639 buf.putByte((byte) SSH_MSG_KEXINIT);
00640 synchronized(random){
00641 random.fill(buf.buffer, buf.index, 16); buf.skip(16);
00642 }
00643 buf.putString(Util.str2byte(kex));
00644 buf.putString(Util.str2byte(getConfig("server_host_key")));
00645 buf.putString(Util.str2byte(cipherc2s));
00646 buf.putString(Util.str2byte(ciphers2c));
00647 buf.putString(Util.str2byte(getConfig("mac.c2s")));
00648 buf.putString(Util.str2byte(getConfig("mac.s2c")));
00649 buf.putString(Util.str2byte(getConfig("compression.c2s")));
00650 buf.putString(Util.str2byte(getConfig("compression.s2c")));
00651 buf.putString(Util.str2byte(getConfig("lang.c2s")));
00652 buf.putString(Util.str2byte(getConfig("lang.s2c")));
00653 buf.putByte((byte)0);
00654 buf.putInt(0);
00655
00656 buf.setOffSet(5);
00657 I_C=new byte[buf.getLength()];
00658 buf.getByte(I_C);
00659
00660 write(packet);
00661
00662 if(JSch.getLogger().isEnabled(Logger.INFO)){
00663 JSch.getLogger().log(Logger.INFO,
00664 "SSH_MSG_KEXINIT sent");
00665 }
00666 }
00667
00668 private void send_newkeys() throws Exception {
00669
00670 packet.reset();
00671 buf.putByte((byte)SSH_MSG_NEWKEYS);
00672 write(packet);
00673
00674 if(JSch.getLogger().isEnabled(Logger.INFO)){
00675 JSch.getLogger().log(Logger.INFO,
00676 "SSH_MSG_NEWKEYS sent");
00677 }
00678 }
00679
00680 private void checkHost(String chost, int port, KeyExchange kex) throws JSchException {
00681 String shkc=getConfig("StrictHostKeyChecking");
00682
00683 if(hostKeyAlias!=null){
00684 chost=hostKeyAlias;
00685 }
00686
00687
00688
00689 byte[] K_S=kex.getHostKey();
00690 String key_type=kex.getKeyType();
00691 String key_fprint=kex.getFingerPrint();
00692
00693 if(hostKeyAlias==null && port!=22){
00694 chost=("["+chost+"]:"+port);
00695 }
00696
00697
00698
00699 HostKeyRepository hkr=jsch.getHostKeyRepository();
00700 int i=0;
00701 synchronized(hkr){
00702 i=hkr.check(chost, K_S);
00703 }
00704
00705 boolean insert=false;
00706
00707 if((shkc.equals("ask") || shkc.equals("yes")) &&
00708 i==HostKeyRepository.CHANGED) {
00709 String file=null;
00710 synchronized(hkr){
00711 file=hkr.getKnownHostsRepositoryID();
00712 }
00713 if(file==null){file="known_hosts";}
00714
00715 boolean b=false;
00716
00717 if(userinfo!=null){
00718 String message=
00719 "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n"+
00720 "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n"+
00721 "Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n"+
00722 "It is also possible that the "+key_type+" host key has just been changed.\n"+
00723 "The fingerprint for the "+key_type+" key sent by the remote host is\n"+
00724 key_fprint+".\n"+
00725 "Please contact your system administrator.\n"+
00726 "Add correct host key in "+file+" to get rid of this message.";
00727
00728 if(shkc.equals("ask")){
00729 b=userinfo.promptYesNo(message+
00730 "\nDo you want to delete the old key and insert the new key?");
00731 }
00732 else{
00733 userinfo.showMessage(message);
00734 }
00735 }
00736
00737 if(!b){
00738 throw new JSchException("HostKey has been changed: "+chost);
00739 }
00740
00741 synchronized(hkr){
00742 hkr.remove(chost,
00743 (key_type.equals("DSA") ? "ssh-dss" : "ssh-rsa"),
00744 null);
00745 insert=true;
00746 }
00747 }
00748
00749 if((shkc.equals("ask") || shkc.equals("yes")) &&
00750 (i!=HostKeyRepository.OK) && !insert){
00751 if(shkc.equals("yes")){
00752 throw new JSchException("reject HostKey: "+host);
00753 }
00754
00755 if(userinfo!=null){
00756 boolean foo=userinfo.promptYesNo(
00757 "The authenticity of host '"+host+"' can't be established.\n"+
00758 key_type+" key fingerprint is "+key_fprint+".\n"+
00759 "Are you sure you want to continue connecting?"
00760 );
00761 if(!foo){
00762 throw new JSchException("reject HostKey: "+host);
00763 }
00764 insert=true;
00765 }
00766 else{
00767 if(i==HostKeyRepository.NOT_INCLUDED)
00768 throw new JSchException("UnknownHostKey: "+host+". "+key_type+" key fingerprint is "+key_fprint);
00769 else
00770 throw new JSchException("HostKey has been changed: "+host);
00771 }
00772 }
00773
00774 if(shkc.equals("no") &&
00775 HostKeyRepository.NOT_INCLUDED==i){
00776 insert=true;
00777 }
00778
00779 if(i==HostKeyRepository.OK &&
00780 JSch.getLogger().isEnabled(Logger.INFO)){
00781 JSch.getLogger().log(Logger.INFO,
00782 "Host '"+host+"' is known and mathces the "+key_type+" host key");
00783 }
00784
00785 if(insert &&
00786 JSch.getLogger().isEnabled(Logger.WARN)){
00787 JSch.getLogger().log(Logger.WARN,
00788 "Permanently added '"+host+"' ("+key_type+") to the list of known hosts.");
00789 }
00790
00791 String hkh=getConfig("HashKnownHosts");
00792 if(hkh.equals("yes") && (hkr instanceof KnownHosts)){
00793 hostkey=((KnownHosts)hkr).createHashedHostKey(chost, K_S);
00794 }
00795 else{
00796 hostkey=new HostKey(chost, K_S);
00797 }
00798
00799 if(insert){
00800 synchronized(hkr){
00801 hkr.add(hostkey, userinfo);
00802 }
00803
00804 }
00805
00806 }
00807
00808
00809
00810
00833 public Channel openChannel(String type) throws JSchException{
00834 if(!isConnected){
00835 throw new JSchException("session is down");
00836 }
00837 try{
00838 Channel channel=Channel.getChannel(type);
00839 addChannel(channel);
00840 channel.init();
00841 return channel;
00842 }
00843 catch(Exception e){
00844
00845 }
00846 return null;
00847 }
00848
00852
00853 public void encode(Packet packet) throws Exception{
00854
00855
00856
00857
00858
00859 if(deflater!=null){
00860 compress_len[0]=packet.buffer.index;
00861 packet.buffer.buffer=deflater.compress(packet.buffer.buffer,
00862 5, compress_len);
00863 packet.buffer.index=compress_len[0];
00864 }
00865 if(c2scipher!=null){
00866
00867 packet.padding(c2scipher_size);
00868
00869
00870
00871 int pad=packet.buffer.buffer[4];
00872 synchronized(random){
00873 random.fill(packet.buffer.buffer, packet.buffer.index-pad, pad);
00874 }
00875 }
00876 else{
00877 packet.padding(8);
00878 }
00879
00880 if(c2smac!=null){
00881 c2smac.update(seqo);
00882 c2smac.update(packet.buffer.buffer, 0, packet.buffer.index);
00883 c2smac.doFinal(packet.buffer.buffer, packet.buffer.index);
00884 }
00885 if(c2scipher!=null){
00886 byte[] buf=packet.buffer.buffer;
00887 c2scipher.update(buf, 0, packet.buffer.index, buf, 0);
00888 }
00889 if(c2smac!=null){
00890 packet.buffer.skip(c2smac.getBlockSize());
00891 }
00892 }
00893
00894 int[] uncompress_len=new int[1];
00895 int[] compress_len=new int[1];
00896
00897 private int s2ccipher_size=8;
00898 private int c2scipher_size=8;
00899
00903 public Buffer read(Buffer buf) throws Exception{
00904 int j=0;
00905 while(true){
00906 buf.reset();
00907 io.getByte(buf.buffer, buf.index, s2ccipher_size);
00908 buf.index+=s2ccipher_size;
00909 if(s2ccipher!=null){
00910 s2ccipher.update(buf.buffer, 0, s2ccipher_size, buf.buffer, 0);
00911 }
00912 j=((buf.buffer[0]<<24)&0xff000000)|
00913 ((buf.buffer[1]<<16)&0x00ff0000)|
00914 ((buf.buffer[2]<< 8)&0x0000ff00)|
00915 ((buf.buffer[3] )&0x000000ff);
00916
00917 if(j<5 || j>PACKET_MAX_SIZE){
00918 start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE);
00919 }
00920 int need = j+4-s2ccipher_size;
00921
00922
00923
00924 if((buf.index+need)>buf.buffer.length){
00925 byte[] foo=new byte[buf.index+need];
00926 System.arraycopy(buf.buffer, 0, foo, 0, buf.index);
00927 buf.buffer=foo;
00928 }
00929
00930 if((need%s2ccipher_size)!=0){
00931 String message="Bad packet length "+need;
00932 if(JSch.getLogger().isEnabled(Logger.FATAL)){
00933 JSch.getLogger().log(Logger.FATAL, message);
00934 }
00935 start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-s2ccipher_size);
00936 }
00937
00938 if(need>0){
00939 io.getByte(buf.buffer, buf.index, need); buf.index+=(need);
00940 if(s2ccipher!=null){
00941 s2ccipher.update(buf.buffer, s2ccipher_size, need, buf.buffer, s2ccipher_size);
00942 }
00943 }
00944
00945 if(s2cmac!=null){
00946 s2cmac.update(seqi);
00947 s2cmac.update(buf.buffer, 0, buf.index);
00948
00949 s2cmac.doFinal(s2cmac_result1, 0);
00950 io.getByte(s2cmac_result2, 0, s2cmac_result2.length);
00951 if(!java.util.Arrays.equals(s2cmac_result1, s2cmac_result2)){
00952 if(need > PACKET_MAX_SIZE){
00953 throw new IOException("MAC Error");
00954 }
00955 start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-need);
00956 continue;
00957 }
00958 }
00959
00960 seqi++;
00961
00962 if(inflater!=null){
00963
00964 int pad=buf.buffer[4];
00965 uncompress_len[0]=buf.index-5-pad;
00966 byte[] foo=inflater.uncompress(buf.buffer, 5, uncompress_len);
00967 if(foo!=null){
00968 buf.buffer=foo;
00969 buf.index=5+uncompress_len[0];
00970 }
00971 else{
00972 System.err.println("fail in inflater");
00973 break;
00974 }
00975 }
00976
00977 int type=buf.getCommand()&0xff;
00978
00979 if(type==SSH_MSG_DISCONNECT){
00980 buf.rewind();
00981 buf.getInt();buf.getShort();
00982 int reason_code=buf.getInt();
00983 byte[] description=buf.getString();
00984 byte[] language_tag=buf.getString();
00985 throw new JSchException("SSH_MSG_DISCONNECT: "+
00986 reason_code+
00987 " "+Util.byte2str(description)+
00988 " "+Util.byte2str(language_tag));
00989
00990 }
00991 else if(type==SSH_MSG_IGNORE){
00992 }
00993 else if(type==SSH_MSG_UNIMPLEMENTED){
00994 buf.rewind();
00995 buf.getInt();buf.getShort();
00996 int reason_id=buf.getInt();
00997 if(JSch.getLogger().isEnabled(Logger.INFO)){
00998 JSch.getLogger().log(Logger.INFO,
00999 "Received SSH_MSG_UNIMPLEMENTED for "+reason_id);
01000 }
01001 }
01002 else if(type==SSH_MSG_DEBUG){
01003 buf.rewind();
01004 buf.getInt();buf.getShort();
01005
01006
01007
01008
01009
01010
01011
01012
01013 }
01014 else if(type==SSH_MSG_CHANNEL_WINDOW_ADJUST){
01015 buf.rewind();
01016 buf.getInt();buf.getShort();
01017 Channel c=Channel.getChannel(buf.getInt(), this);
01018 if(c==null){
01019 }
01020 else{
01021 c.addRemoteWindowSize(buf.getInt());
01022 }
01023 }
01024 else if(type==UserAuth.SSH_MSG_USERAUTH_SUCCESS){
01025 isAuthed=true;
01026 if(inflater==null && deflater==null){
01027 String method;
01028 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];
01029 initDeflater(method);
01030 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];
01031 initInflater(method);
01032 }
01033 break;
01034 }
01035 else{
01036 break;
01037 }
01038 }
01039 buf.rewind();
01040 return buf;
01041 }
01042
01043 private void start_discard(Buffer buf, Cipher cipher, MAC mac,
01044 int packet_length, int discard) throws JSchException, IOException{
01045 MAC discard_mac = null;
01046
01047 if(!cipher.isCBC()){
01048
01049
01050 throw new JSchException("Packet corrupt");
01051 }
01052
01053 if(packet_length!=PACKET_MAX_SIZE && mac != null){
01054 discard_mac = mac;
01055 }
01056
01057 discard -= buf.index;
01058
01059 while(discard>0){
01060 buf.reset();
01061 int len = discard>buf.buffer.length ? buf.buffer.length : discard;
01062 io.getByte(buf.buffer, 0, len);
01063 if(discard_mac!=null){
01064 discard_mac.update(buf.buffer, 0, len);
01065 }
01066 discard -= len;
01067 }
01068
01069 if(discard_mac!=null){
01070 discard_mac.doFinal(buf.buffer, 0);
01071 }
01072
01073 throw new JSchException("Packet corrupt");
01074 }
01075
01076 byte[] getSessionId(){
01077 return session_id;
01078 }
01079
01080 private void receive_newkeys(Buffer buf, KeyExchange kex) throws Exception {
01081 updateKeys(kex);
01082 in_kex=false;
01083 }
01084 private void updateKeys(KeyExchange kex) throws Exception{
01085 byte[] K=kex.getK();
01086 byte[] H=kex.getH();
01087 HASH hash=kex.getHash();
01088
01089
01090
01091 if(session_id==null){
01092 session_id=new byte[H.length];
01093 System.arraycopy(H, 0, session_id, 0, H.length);
01094 }
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105 buf.reset();
01106 buf.putMPInt(K);
01107 buf.putByte(H);
01108 buf.putByte((byte)0x41);
01109 buf.putByte(session_id);
01110 hash.update(buf.buffer, 0, buf.index);
01111 IVc2s=hash.digest();
01112
01113 int j=buf.index-session_id.length-1;
01114
01115 buf.buffer[j]++;
01116 hash.update(buf.buffer, 0, buf.index);
01117 IVs2c=hash.digest();
01118
01119 buf.buffer[j]++;
01120 hash.update(buf.buffer, 0, buf.index);
01121 Ec2s=hash.digest();
01122
01123 buf.buffer[j]++;
01124 hash.update(buf.buffer, 0, buf.index);
01125 Es2c=hash.digest();
01126
01127 buf.buffer[j]++;
01128 hash.update(buf.buffer, 0, buf.index);
01129 MACc2s=hash.digest();
01130
01131 buf.buffer[j]++;
01132 hash.update(buf.buffer, 0, buf.index);
01133 MACs2c=hash.digest();
01134
01135 try{
01136 Class c;
01137 String method;
01138
01139 method=guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC];
01140 c=Class.forName(getConfig(method));
01141 s2ccipher=(Cipher)(c.newInstance());
01142 while(s2ccipher.getBlockSize()>Es2c.length){
01143 buf.reset();
01144 buf.putMPInt(K);
01145 buf.putByte(H);
01146 buf.putByte(Es2c);
01147 hash.update(buf.buffer, 0, buf.index);
01148 byte[] foo=hash.digest();
01149 byte[] bar=new byte[Es2c.length+foo.length];
01150 System.arraycopy(Es2c, 0, bar, 0, Es2c.length);
01151 System.arraycopy(foo, 0, bar, Es2c.length, foo.length);
01152 Es2c=bar;
01153 }
01154 s2ccipher.init(Cipher.DECRYPT_MODE, Es2c, IVs2c);
01155 s2ccipher_size=s2ccipher.getIVSize();
01156
01157 method=guess[KeyExchange.PROPOSAL_MAC_ALGS_STOC];
01158 c=Class.forName(getConfig(method));
01159 s2cmac=(MAC)(c.newInstance());
01160 s2cmac.init(MACs2c);
01161
01162 s2cmac_result1=new byte[s2cmac.getBlockSize()];
01163 s2cmac_result2=new byte[s2cmac.getBlockSize()];
01164
01165 method=guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS];
01166 c=Class.forName(getConfig(method));
01167 c2scipher=(Cipher)(c.newInstance());
01168 while(c2scipher.getBlockSize()>Ec2s.length){
01169 buf.reset();
01170 buf.putMPInt(K);
01171 buf.putByte(H);
01172 buf.putByte(Ec2s);
01173 hash.update(buf.buffer, 0, buf.index);
01174 byte[] foo=hash.digest();
01175 byte[] bar=new byte[Ec2s.length+foo.length];
01176 System.arraycopy(Ec2s, 0, bar, 0, Ec2s.length);
01177 System.arraycopy(foo, 0, bar, Ec2s.length, foo.length);
01178 Ec2s=bar;
01179 }
01180 c2scipher.init(Cipher.ENCRYPT_MODE, Ec2s, IVc2s);
01181 c2scipher_size=c2scipher.getIVSize();
01182
01183 method=guess[KeyExchange.PROPOSAL_MAC_ALGS_CTOS];
01184 c=Class.forName(getConfig(method));
01185 c2smac=(MAC)(c.newInstance());
01186 c2smac.init(MACc2s);
01187
01188 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];
01189 initDeflater(method);
01190
01191 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];
01192 initInflater(method);
01193 }
01194 catch(Exception e){
01195 if(e instanceof JSchException)
01196 throw e;
01197 throw new JSchException(e.toString(), e);
01198
01199 }
01200 }
01201
01202 void write(Packet packet, Channel c, int length) throws Exception{
01203 long t = getTimeout();
01204 while(true){
01205 if(in_kex){
01206 if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){
01207 throw new JSchException("timeout in wating for rekeying process.");
01208 }
01209 try{Thread.sleep(10);}
01210 catch(java.lang.InterruptedException e){};
01211 continue;
01212 }
01213 synchronized(c){
01214
01215 if(c.rwsize<length){
01216 try{
01217 c.notifyme++;
01218 c.wait(100);
01219 }
01220 catch(java.lang.InterruptedException e){
01221 }
01222 finally{
01223 c.notifyme--;
01224 }
01225 }
01226
01227 if(c.rwsize>=length){
01228 c.rwsize-=length;
01229 break;
01230 }
01231
01232 }
01233 if(c.close || !c.isConnected()){
01234 throw new IOException("channel is broken");
01235 }
01236
01237 boolean sendit=false;
01238 int s=0;
01239 byte command=0;
01240 int recipient=-1;
01241 synchronized(c){
01242 if(c.rwsize>0){
01243 long len=c.rwsize;
01244 if(len>length){
01245 len=length;
01246 }
01247 if(len!=length){
01248 s=packet.shift((int)len,
01249 (c2scipher!=null ? c2scipher_size : 8),
01250 (c2smac!=null ? c2smac.getBlockSize() : 0));
01251 }
01252 command=packet.buffer.getCommand();
01253 recipient=c.getRecipient();
01254 length-=len;
01255 c.rwsize-=len;
01256 sendit=true;
01257 }
01258 }
01259 if(sendit){
01260 _write(packet);
01261 if(length==0){
01262 return;
01263 }
01264 packet.unshift(command, recipient, s, length);
01265 }
01266
01267 synchronized(c){
01268 if(in_kex){
01269 continue;
01270 }
01271 if(c.rwsize>=length){
01272 c.rwsize-=length;
01273 break;
01274 }
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286 }
01287 }
01288 _write(packet);
01289 }
01290
01294 public void write(Packet packet) throws Exception{
01295
01296 long t = getTimeout();
01297 while(in_kex){
01298 if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){
01299 throw new JSchException("timeout in wating for rekeying process.");
01300 }
01301 byte command=packet.buffer.getCommand();
01302
01303 if(command==SSH_MSG_KEXINIT ||
01304 command==SSH_MSG_NEWKEYS ||
01305 command==SSH_MSG_KEXDH_INIT ||
01306 command==SSH_MSG_KEXDH_REPLY ||
01307 command==SSH_MSG_KEX_DH_GEX_GROUP ||
01308 command==SSH_MSG_KEX_DH_GEX_INIT ||
01309 command==SSH_MSG_KEX_DH_GEX_REPLY ||
01310 command==SSH_MSG_KEX_DH_GEX_REQUEST ||
01311 command==SSH_MSG_DISCONNECT){
01312 break;
01313 }
01314 try{Thread.sleep(10);}
01315 catch(java.lang.InterruptedException e){};
01316 }
01317 _write(packet);
01318 }
01319
01320 private void _write(Packet packet) throws Exception{
01321 synchronized(lock){
01322 encode(packet);
01323 if(io!=null){
01324 io.put(packet);
01325 seqo++;
01326 }
01327 }
01328 }
01329
01330 Runnable thread;
01336 public void run(){
01337 thread=this;
01338
01339 byte[] foo;
01340 Buffer buf=new Buffer();
01341 Packet packet=new Packet(buf);
01342 int i=0;
01343 Channel channel;
01344 int[] start=new int[1];
01345 int[] length=new int[1];
01346 KeyExchange kex=null;
01347
01348 int stimeout=0;
01349 try{
01350 while(isConnected &&
01351 thread!=null){
01352 try{
01353 buf=read(buf);
01354 stimeout=0;
01355 }
01356 catch(InterruptedIOException ee){
01357 if(!in_kex && stimeout<serverAliveCountMax){
01358 sendKeepAliveMsg();
01359 stimeout++;
01360 continue;
01361 }
01362 else if(in_kex && stimeout<serverAliveCountMax){
01363 stimeout++;
01364 continue;
01365 }
01366 throw ee;
01367 }
01368
01369 int msgType=buf.getCommand()&0xff;
01370
01371 if(kex!=null && kex.getState()==msgType){
01372 kex_start_time=System.currentTimeMillis();
01373 boolean result=kex.next(buf);
01374 if(!result){
01375 throw new JSchException("verify: "+result);
01376 }
01377 continue;
01378 }
01379
01380 if(jsch.getLogger().isEnabled(Logger.DEBUG)) {
01381 jsch.getLogger().log(Logger.DEBUG, "packet received, type: " +
01382 msgType);
01383 }
01384
01385
01386 switch(msgType){
01387 case SSH_MSG_KEXINIT:
01388 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01389 jsch.getLogger().log(Logger.INFO, "SSH_MSG_KEXINIT received");
01390 }
01391
01392 kex=receive_kexinit(buf);
01393 break;
01394
01395 case SSH_MSG_NEWKEYS:
01396 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01397 jsch.getLogger().log(Logger.INFO, "SSH_MSG_NEWKEYS received");
01398 }
01399
01400 send_newkeys();
01401 receive_newkeys(buf, kex);
01402 kex=null;
01403 break;
01404
01405 case SSH_MSG_CHANNEL_DATA:
01406 buf.getInt();
01407 buf.getByte();
01408 buf.getByte();
01409 i=buf.getInt();
01410 channel=Channel.getChannel(i, this);
01411 foo=buf.getString(start, length);
01412 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01413 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_DATA received, channel: "+i + ", len: " + length[0]);
01414 }
01415 if(channel==null){
01416 break;
01417 }
01418
01419 if(length[0]==0){
01420 break;
01421 }
01422
01423 try{
01424 channel.write(foo, start[0], length[0]);
01425 }
01426 catch(Exception e){
01427
01428 try{channel.disconnect();}catch(Exception ee){}
01429 break;
01430 }
01431 int len=length[0];
01432 channel.setLocalWindowSize(channel.lwsize-len);
01433 if(channel.lwsize<channel.lwsize_max/2){
01434 packet.reset();
01435 buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
01436 buf.putInt(channel.getRecipient());
01437 buf.putInt(channel.lwsize_max-channel.lwsize);
01438 write(packet);
01439 channel.setLocalWindowSize(channel.lwsize_max);
01440 }
01441 break;
01442
01443 case SSH_MSG_CHANNEL_EXTENDED_DATA:
01444 buf.getInt();
01445 buf.getShort();
01446 i=buf.getInt();
01447 channel=Channel.getChannel(i, this);
01448 int type_code = buf.getInt();
01449 foo=buf.getString(start, length);
01450
01451 if(channel==null){
01452 break;
01453 }
01454
01455 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01456 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL__EXTENDED_DATA received, channel: "+i + ", len: " + length[0] +", type: " + type_code);
01457 }
01458
01459 if(length[0]==0){
01460 break;
01461 }
01462
01463 channel.write_ext(foo, start[0], length[0]);
01464
01465 len=length[0];
01466 channel.setLocalWindowSize(channel.lwsize-len);
01467 if(channel.lwsize<channel.lwsize_max/2){
01468 packet.reset();
01469 buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
01470 buf.putInt(channel.getRecipient());
01471 buf.putInt(channel.lwsize_max-channel.lwsize);
01472 write(packet);
01473 channel.setLocalWindowSize(channel.lwsize_max);
01474 }
01475 break;
01476
01477 case SSH_MSG_CHANNEL_WINDOW_ADJUST:
01478 buf.getInt();
01479 buf.getShort();
01480 i=buf.getInt();
01481 channel=Channel.getChannel(i, this);
01482 if(channel==null){
01483 break;
01484 }
01485 int remoteSize = buf.getInt();
01486 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01487 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_DATA received, channel: "+i + ", bytes: " + remoteSize);
01488 }
01489 channel.addRemoteWindowSize(remoteSize);
01490 break;
01491
01492 case SSH_MSG_CHANNEL_EOF:
01493 buf.getInt();
01494 buf.getShort();
01495 i=buf.getInt();
01496 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01497 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_EOF received, channel: "+i);
01498 }
01499 channel=Channel.getChannel(i, this);
01500 if(channel!=null){
01501
01502
01503 channel.eof_remote();
01504 }
01505
01506
01507
01508
01509
01510
01511 break;
01512 case SSH_MSG_CHANNEL_CLOSE:
01513 buf.getInt();
01514 buf.getShort();
01515 i=buf.getInt();
01516 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01517 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_CLOSE received, channel: "+i);
01518 }
01519 channel=Channel.getChannel(i, this);
01520 if(channel!=null){
01521
01522 channel.disconnect();
01523 }
01524
01525
01526
01527
01528
01529 break;
01530 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
01531 buf.getInt();
01532 buf.getShort();
01533 i=buf.getInt();
01534 channel=Channel.getChannel(i, this);
01535 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01536 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_OPEN_CONFIRMATION received, channel: "+i);
01537 }
01538 if(channel==null){
01539
01540 }
01541 int r=buf.getInt();
01542 long rws=buf.getUInt();
01543 int rps=buf.getInt();
01544
01545 channel.setRemoteWindowSize(rws);
01546 channel.setRemotePacketSize(rps);
01547 channel.open_confirmation=true;
01548 channel.setRecipient(r);
01549 break;
01550 case SSH_MSG_CHANNEL_OPEN_FAILURE:
01551 buf.getInt();
01552 buf.getShort();
01553 i=buf.getInt();
01554 channel=Channel.getChannel(i, this);
01555 if(channel==null){
01556
01557 }
01558 int reason_code=buf.getInt();
01559 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01560
01561 String descr =Util.byte2str(buf.getString());
01562
01563 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_OPEN_FAILURE received, reason: " + reason_code+", channel: "+i+", description: " + descr);
01564 }
01565 channel.setExitStatus(reason_code);
01566 channel.close=true;
01567 channel.eof_remote=true;
01568 channel.setRecipient(0);
01569 break;
01570 case SSH_MSG_CHANNEL_REQUEST:
01571 buf.getInt();
01572 buf.getShort();
01573 i=buf.getInt();
01574 foo=buf.getString();
01575 boolean reply=(buf.getByte()!=0);
01576 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01577 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_REQUEST received, channel: "+i +", type: " + foo + ", want reply: " + reply);
01578 }
01579 channel=Channel.getChannel(i, this);
01580 if(channel!=null){
01581 byte reply_type=(byte)SSH_MSG_CHANNEL_FAILURE;
01582 if((Util.byte2str(foo)).equals("exit-status")){
01583 i=buf.getInt();
01584 channel.setExitStatus(i);
01585 reply_type=(byte)SSH_MSG_CHANNEL_SUCCESS;
01586 }
01587 if(reply){
01588 packet.reset();
01589 buf.putByte(reply_type);
01590 buf.putInt(channel.getRecipient());
01591 write(packet);
01592 }
01593 }
01594 else{
01595 }
01596 break;
01597 case SSH_MSG_CHANNEL_OPEN:
01598 buf.getInt();
01599 buf.getShort();
01600 foo=buf.getString();
01601 String ctyp=Util.byte2str(foo);
01602 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01603 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_OPEN received, type: " + ctyp);
01604 }
01605 if(!"forwarded-tcpip".equals(ctyp) &&
01606 !("x11".equals(ctyp) && x11_forwarding) &&
01607 !("auth-agent@openssh.com".equals(ctyp) && agent_forwarding)){
01608
01609
01610 packet.reset();
01611 buf.putByte((byte)SSH_MSG_CHANNEL_OPEN_FAILURE);
01612 buf.putInt(buf.getInt());
01613 buf.putInt(Channel.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED);
01614 buf.putString(Util.empty);
01615 buf.putString(Util.empty);
01616 write(packet);
01617 }
01618 else{
01619 channel=Channel.getChannel(ctyp);
01620 addChannel(channel);
01621 channel.getData(buf);
01622 channel.init();
01623
01624 Thread tmp=new Thread(channel);
01625 tmp.setName("Channel "+ctyp+" "+host);
01626 if(daemon_thread){
01627 tmp.setDaemon(daemon_thread);
01628 }
01629 tmp.start();
01630 break;
01631 }
01632 case SSH_MSG_CHANNEL_SUCCESS:
01633 buf.getInt();
01634 buf.getShort();
01635 i=buf.getInt();
01636 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01637 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_SUCCESS received, channel: " + i);
01638 }
01639 channel=Channel.getChannel(i, this);
01640 if(channel==null){
01641 break;
01642 }
01643 channel.reply=1;
01644 break;
01645 case SSH_MSG_CHANNEL_FAILURE:
01646 buf.getInt();
01647 buf.getShort();
01648 i=buf.getInt();
01649 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01650 jsch.getLogger().log(Logger.INFO, "SSH_MSG_CHANNEL_FAILURE received, channel: " + i);
01651 }
01652 channel=Channel.getChannel(i, this);
01653 if(channel==null){
01654 break;
01655 }
01656 channel.reply=0;
01657 break;
01658 case SSH_MSG_GLOBAL_REQUEST:
01659 buf.getInt();
01660 buf.getShort();
01661 foo=buf.getString();
01662 reply=(buf.getByte()!=0);
01663 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01664 jsch.getLogger().log(Logger.INFO, "SSH_MSG_GLOBAL_REQUEST received, request: " + Util.byte2str(foo) + ", want reply: " + reply);
01665 }
01666 if(reply){
01667
01668 packet.reset();
01669 buf.putByte((byte)SSH_MSG_REQUEST_FAILURE);
01670 write(packet);
01671 }
01672 break;
01673 case SSH_MSG_REQUEST_FAILURE:
01674 case SSH_MSG_REQUEST_SUCCESS:
01675 if(jsch.getLogger().isEnabled(Logger.INFO)) {
01676 jsch.getLogger().log(Logger.INFO, "SSH_MSG_REQUEST_" +(msgType==SSH_MSG_REQUEST_SUCCESS ? "SUCCESS" : "FAILURE")+" received.");
01677 }
01678 Thread t=grr.getThread();
01679 if(t!=null){
01680 grr.setReply(msgType==SSH_MSG_REQUEST_SUCCESS? 1 : 0);
01681 t.interrupt();
01682 }
01683 break;
01684 default:
01685
01686 throw new IOException("Unknown SSH message type "+msgType);
01687 }
01688 }
01689 }
01690 catch(Exception e){
01691 in_kex=false;
01692 if(JSch.getLogger().isEnabled(Logger.INFO)){
01693 JSch.getLogger().log(Logger.INFO,
01694 "Caught an exception, leaving main loop due to " + e.getMessage());
01695 }
01696
01697
01698 }
01699 try{
01700 disconnect();
01701 }
01702 catch(NullPointerException e){
01703
01704
01705 }
01706 catch(Exception e){
01707
01708
01709 }
01710 isConnected=false;
01711 }
01712
01717 public void disconnect(){
01718 if(!isConnected) return;
01719
01720
01721 if(JSch.getLogger().isEnabled(Logger.INFO)){
01722 JSch.getLogger().log(Logger.INFO,
01723 "Disconnecting from "+host+" port "+port);
01724 }
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736 Channel.disconnect(this);
01737
01738 isConnected=false;
01739
01740 PortWatcher.delPort(this);
01741 ChannelForwardedTCPIP.delPort(this);
01742 ChannelX11.removeFakedCookie(this);
01743
01744 synchronized(lock){
01745 if(connectThread!=null){
01746 Thread.yield();
01747 connectThread.interrupt();
01748 connectThread=null;
01749 }
01750 }
01751 thread=null;
01752 try{
01753 if(io!=null){
01754 if(io.in!=null) io.in.close();
01755 if(io.out!=null) io.out.close();
01756 if(io.out_ext!=null) io.out_ext.close();
01757 }
01758 if(proxy==null){
01759 if(socket!=null)
01760 socket.close();
01761 }
01762 else{
01763 synchronized(proxy){
01764 proxy.close();
01765 }
01766 proxy=null;
01767 }
01768 }
01769 catch(Exception e){
01770
01771 }
01772 io=null;
01773 socket=null;
01774
01775
01776
01777
01778 jsch.removeSession(this);
01779
01780
01781 }
01782
01788 public int setPortForwardingL(int lport, String host, int rport) throws JSchException{
01789 return setPortForwardingL("127.0.0.1", lport, host, rport);
01790 }
01801 public int setPortForwardingL(String boundaddress, int lport, String host, int rport) throws JSchException{
01802 return setPortForwardingL(boundaddress, lport, host, rport, null);
01803 }
01809 public int setPortForwardingL(String boundaddress, int lport, String host, int rport, ServerSocketFactory ssf) throws JSchException{
01810 PortWatcher pw=PortWatcher.addPort(this, boundaddress, lport, host, rport, ssf);
01811 Thread tmp=new Thread(pw);
01812 tmp.setName("PortWatcher Thread for "+host);
01813 if(daemon_thread){
01814 tmp.setDaemon(daemon_thread);
01815 }
01816 tmp.start();
01817 return pw.lport;
01818 }
01819
01824 public void delPortForwardingL(int lport) throws JSchException{
01825 delPortForwardingL("127.0.0.1", lport);
01826 }
01832 public void delPortForwardingL(String boundaddress, int lport) throws JSchException{
01833 PortWatcher.delPort(this, boundaddress, lport);
01834 }
01835
01845 public String[] getPortForwardingL() throws JSchException{
01846 return PortWatcher.getPortForwarding(this);
01847 }
01848
01853 public void setPortForwardingR(int rport, String host, int lport) throws JSchException{
01854 setPortForwardingR(null, rport, host, lport, (SocketFactory)null);
01855 }
01860 public void setPortForwardingR(String bind_address, int rport, String host, int lport) throws JSchException{
01861 setPortForwardingR(bind_address, rport, host, lport, (SocketFactory)null);
01862 }
01867 public void setPortForwardingR(int rport, String host, int lport, SocketFactory sf) throws JSchException{
01868 setPortForwardingR(null, rport, host, lport, sf);
01869 }
01880 public void setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf) throws JSchException{
01881 ChannelForwardedTCPIP.addPort(this, bind_address, rport, host, lport, sf);
01882 setPortForwarding(bind_address, rport);
01883 }
01884
01891 public void setPortForwardingR(int rport, String daemon) throws JSchException{
01892 setPortForwardingR(null, rport, daemon, null);
01893 }
01899 public void setPortForwardingR(int rport, String daemon, Object[] arg) throws JSchException{
01900 setPortForwardingR(null, rport, daemon, arg);
01901 }
01902
01922 public void setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg) throws JSchException{
01923 ChannelForwardedTCPIP.addPort(this, bind_address, rport, daemon, arg);
01924 setPortForwarding(bind_address, rport);
01925 }
01926
01927 private class GlobalRequestReply{
01928 private Thread thread=null;
01929 private int reply=-1;
01930 void setThread(Thread thread){
01931 this.thread=thread;
01932 this.reply=-1;
01933 }
01934 Thread getThread(){ return thread; }
01935 void setReply(int reply){ this.reply=reply; }
01936 int getReply(){ return this.reply; }
01937 }
01938 private GlobalRequestReply grr=new GlobalRequestReply();
01939 private void setPortForwarding(String bind_address, int rport) throws JSchException{
01940 synchronized(grr){
01941 Buffer buf=new Buffer(100);
01942 Packet packet=new Packet(buf);
01943
01944 String address_to_bind=ChannelForwardedTCPIP.normalize(bind_address);
01945
01946 grr.setThread(Thread.currentThread());
01947
01948 try{
01949
01950
01951
01952
01953
01954 packet.reset();
01955 buf.putByte((byte) SSH_MSG_GLOBAL_REQUEST);
01956 buf.putString(Util.str2byte("tcpip-forward"));
01957 buf.putByte((byte)1);
01958 buf.putString(Util.str2byte(address_to_bind));
01959 buf.putInt(rport);
01960 write(packet);
01961 }
01962 catch(Exception e){
01963 grr.setThread(null);
01964 if(e instanceof Throwable)
01965 throw new JSchException(e.toString(), (Throwable)e);
01966 throw new JSchException(e.toString());
01967 }
01968
01969 int count = 0;
01970 int reply = grr.getReply();
01971 while(count < 10 && reply == -1){
01972 try{ Thread.sleep(1000); }
01973 catch(Exception e){
01974 }
01975 count++;
01976 reply = grr.getReply();
01977 }
01978 grr.setThread(null);
01979 if(reply != 1){
01980 throw new JSchException("remote port forwarding failed for listen port "+rport);
01981 }
01982 }
01983 }
01984
01989 public void delPortForwardingR(int rport) throws JSchException{
01990 ChannelForwardedTCPIP.delPort(this, rport);
01991 }
01992
01993
02005 private void initDeflater(String method) throws JSchException{
02006 if(method.equals("none")){
02007 deflater=null;
02008 return;
02009 }
02010 String foo=getConfig(method);
02011 if(foo!=null){
02012 if(method.equals("zlib") ||
02013 (isAuthed && method.equals("zlib@openssh.com"))){
02014 try{
02015 Class c=Class.forName(foo);
02016 deflater=(Compression)(c.newInstance());
02017 int level=6;
02018 try{ level=Integer.parseInt(getConfig("compression_level"));}
02019 catch(Exception ee){ }
02020 deflater.init(Compression.DEFLATER, level);
02021 }
02022 catch(Exception ee){
02023 throw new JSchException(ee.toString(), ee);
02024
02025 }
02026 }
02027 }
02028 }
02029
02041 private void initInflater(String method) throws JSchException{
02042 if(method.equals("none")){
02043 inflater=null;
02044 return;
02045 }
02046 String foo=getConfig(method);
02047 if(foo!=null){
02048 if(method.equals("zlib") ||
02049 (isAuthed && method.equals("zlib@openssh.com"))){
02050 try{
02051 Class c=Class.forName(foo);
02052 inflater=(Compression)(c.newInstance());
02053 inflater.init(Compression.INFLATER, 0);
02054 }
02055 catch(Exception ee){
02056 throw new JSchException(ee.toString(), ee);
02057
02058 }
02059 }
02060 }
02061 }
02062
02063 void addChannel(Channel channel){
02064 channel.setSession(this);
02065 }
02066
02076 public void setProxy(Proxy proxy){ this.proxy=proxy; }
02077
02084 public void setHost(String host){ this.host=host; }
02085
02092 public void setPort(int port){ this.port=port; }
02099 void setUserName(String username){ this.username=username; }
02100
02107 public void setUserInfo(UserInfo userinfo){ this.userinfo=userinfo; }
02112 public UserInfo getUserInfo(){ return userinfo; }
02117 public void setInputStream(InputStream in){ this.in=in; }
02122 public void setOutputStream(OutputStream out){ this.out=out; }
02136 public void setX11Host(String host){ ChannelX11.setHost(host); }
02151 public void setX11Port(int port){ ChannelX11.setPort(port); }
02167 public void setX11Cookie(String cookie){ ChannelX11.setCookie(cookie); }
02168
02175 public void setPassword(String password){
02176 if(password!=null)
02177 this.password=Util.str2byte(password);
02178 }
02191 public void setPassword(byte[] password){
02192 if(password!=null){
02193 this.password=new byte[password.length];
02194 System.arraycopy(password, 0, this.password, 0, password.length);
02195 }
02196 }
02197
02205 public void setConfig(java.util.Properties newconf){
02206 setConfig((java.util.Hashtable)newconf);
02207 }
02208
02216 public void setConfig(java.util.Hashtable newconf){
02217 synchronized(lock){
02218 if(config==null)
02219 config=new java.util.Hashtable();
02220 for(java.util.Enumeration e=newconf.keys() ; e.hasMoreElements() ;) {
02221 String key=(String)(e.nextElement());
02222 config.put(key, (String)(newconf.get(key)));
02223 }
02224 }
02225 }
02226
02232 public void setConfig(String key, String value){
02233 synchronized(lock){
02234 if(config==null){
02235 config=new java.util.Hashtable();
02236 }
02237 config.put(key, value);
02238 }
02239 }
02240
02251 public String getConfig(String key){
02252 Object foo=null;
02253 if(config!=null){
02254 foo=config.get(key);
02255 if(foo instanceof String) return (String)foo;
02256 }
02257 foo=jsch.getConfig(key);
02258 if(foo instanceof String) return (String)foo;
02259 return null;
02260 }
02261
02271 public void setSocketFactory(SocketFactory sfactory){
02272 socket_factory=sfactory;
02273 }
02280 public boolean isConnected(){ return isConnected; }
02285 public int getTimeout(){ return timeout; }
02295 public void setTimeout(int timeout) throws JSchException {
02296 if(socket==null){
02297 if(timeout<0){
02298 throw new JSchException("invalid timeout value");
02299 }
02300 this.timeout=timeout;
02301 return;
02302 }
02303 try{
02304 socket.setSoTimeout(timeout);
02305 this.timeout=timeout;
02306 }
02307 catch(Exception e){
02308 if(e instanceof Throwable)
02309 throw new JSchException(e.toString(), (Throwable)e);
02310 throw new JSchException(e.toString());
02311 }
02312 }
02313
02319 public String getServerVersion(){
02320 return Util.byte2str(V_S);
02321 }
02322
02328 public String getClientVersion(){
02329 return Util.byte2str(V_C);
02330 }
02341 public void setClientVersion(String cv){
02342 V_C=Util.str2byte(cv);
02343 }
02344
02352 public void sendIgnore() throws Exception{
02353 Buffer buf=new Buffer();
02354 Packet packet=new Packet(buf);
02355 packet.reset();
02356 buf.putByte((byte)SSH_MSG_IGNORE);
02357 write(packet);
02358 }
02359
02360 private static final byte[] keepalivemsg=Util.str2byte("keepalive@jcraft.com");
02361
02366 public void sendKeepAliveMsg() throws Exception{
02367 Buffer buf=new Buffer();
02368 Packet packet=new Packet(buf);
02369 packet.reset();
02370 buf.putByte((byte)SSH_MSG_GLOBAL_REQUEST);
02371 buf.putString(keepalivemsg);
02372 buf.putByte((byte)1);
02373 write(packet);
02374 }
02375
02376 private HostKey hostkey=null;
02377
02384 public HostKey getHostKey(){ return hostkey; }
02385
02389 public String getHost(){return host;}
02390
02395 public String getUserName(){return username;}
02396
02401 public int getPort(){return port;}
02409 public void setHostKeyAlias(String hostKeyAlias){
02410 this.hostKeyAlias=hostKeyAlias;
02411 }
02412
02417 public String getHostKeyAlias(){
02418 return hostKeyAlias;
02419 }
02420
02428 public void setServerAliveInterval(int interval) throws JSchException {
02429 setTimeout(interval);
02430 this.serverAliveInterval=interval;
02431 }
02432
02440 public void setServerAliveCountMax(int count){
02441 this.serverAliveCountMax=count;
02442 }
02443
02448 public int getServerAliveInterval(){
02449 return this.serverAliveInterval;
02450 }
02451
02456 public int getServerAliveCountMax(){
02457 return this.serverAliveCountMax;
02458 }
02459
02474 public void setDaemonThread(boolean enable){
02475 this.daemon_thread=enable;
02476 }
02477
02478 private String[] checkCiphers(String ciphers){
02479 if(ciphers==null || ciphers.length()==0)
02480 return null;
02481
02482 if(JSch.getLogger().isEnabled(Logger.INFO)){
02483 JSch.getLogger().log(Logger.INFO,
02484 "CheckCiphers: "+ciphers);
02485 }
02486
02487 java.util.Vector result=new java.util.Vector();
02488 String[] _ciphers=Util.split(ciphers, ",");
02489 for(int i=0; i<_ciphers.length; i++){
02490 if(!checkCipher(getConfig(_ciphers[i]))){
02491 result.addElement(_ciphers[i]);
02492 }
02493 }
02494 if(result.size()==0)
02495 return null;
02496 String[] foo=new String[result.size()];
02497 System.arraycopy(result.toArray(), 0, foo, 0, result.size());
02498
02499 if(JSch.getLogger().isEnabled(Logger.INFO)){
02500 for(int i=0; i<foo.length; i++){
02501 JSch.getLogger().log(Logger.INFO,
02502 foo[i]+" is not available.");
02503 }
02504 }
02505
02506 return foo;
02507 }
02508
02509 static boolean checkCipher(String cipher){
02510 try{
02511 Class c=Class.forName(cipher);
02512 Cipher _c=(Cipher)(c.newInstance());
02513 _c.init(Cipher.ENCRYPT_MODE,
02514 new byte[_c.getBlockSize()],
02515 new byte[_c.getIVSize()]);
02516 return true;
02517 }
02518 catch(Exception e){
02519 return false;
02520 }
02521 }
02522
02523 private String[] checkKexes(String kexes){
02524 if(kexes==null || kexes.length()==0)
02525 return null;
02526
02527 if(JSch.getLogger().isEnabled(Logger.INFO)){
02528 JSch.getLogger().log(Logger.INFO,
02529 "CheckKexes: "+kexes);
02530 }
02531
02532 java.util.Vector result=new java.util.Vector();
02533 String[] _kexes=Util.split(kexes, ",");
02534 for(int i=0; i<_kexes.length; i++){
02535 if(!checkKex(this, getConfig(_kexes[i]))){
02536 result.addElement(_kexes[i]);
02537 }
02538 }
02539 if(result.size()==0)
02540 return null;
02541 String[] foo=new String[result.size()];
02542 System.arraycopy(result.toArray(), 0, foo, 0, result.size());
02543
02544 if(JSch.getLogger().isEnabled(Logger.INFO)){
02545 for(int i=0; i<foo.length; i++){
02546 JSch.getLogger().log(Logger.INFO,
02547 foo[i]+" is not available.");
02548 }
02549 }
02550
02551 return foo;
02552 }
02553
02554 static boolean checkKex(Session s, String kex){
02555 try{
02556 Class c=Class.forName(kex);
02557 KeyExchange _c=(KeyExchange)(c.newInstance());
02558 _c.init(s ,null, null, null, null);
02559 return true;
02560 }
02561 catch(Exception e){ return false; }
02562 }
02563 }