1 /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
3 Copyright (c) 2002-2010 ymnk, JCraft,Inc. All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
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.
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.
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.
30 package com.jcraft.jsch;
35 public class Session implements Runnable{
36 static private final String version="JSCH-0.1.43";
38 // http://ietf.org/internet-drafts/draft-ietf-secsh-assignednumbers-01.txt
39 static final int SSH_MSG_DISCONNECT= 1;
40 static final int SSH_MSG_IGNORE= 2;
41 static final int SSH_MSG_UNIMPLEMENTED= 3;
42 static final int SSH_MSG_DEBUG= 4;
43 static final int SSH_MSG_SERVICE_REQUEST= 5;
44 static final int SSH_MSG_SERVICE_ACCEPT= 6;
45 static final int SSH_MSG_KEXINIT= 20;
46 static final int SSH_MSG_NEWKEYS= 21;
47 static final int SSH_MSG_KEXDH_INIT= 30;
48 static final int SSH_MSG_KEXDH_REPLY= 31;
49 static final int SSH_MSG_KEX_DH_GEX_GROUP= 31;
50 static final int SSH_MSG_KEX_DH_GEX_INIT= 32;
51 static final int SSH_MSG_KEX_DH_GEX_REPLY= 33;
52 static final int SSH_MSG_KEX_DH_GEX_REQUEST= 34;
53 static final int SSH_MSG_GLOBAL_REQUEST= 80;
54 static final int SSH_MSG_REQUEST_SUCCESS= 81;
55 static final int SSH_MSG_REQUEST_FAILURE= 82;
56 static final int SSH_MSG_CHANNEL_OPEN= 90;
57 static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION= 91;
58 static final int SSH_MSG_CHANNEL_OPEN_FAILURE= 92;
59 static final int SSH_MSG_CHANNEL_WINDOW_ADJUST= 93;
60 static final int SSH_MSG_CHANNEL_DATA= 94;
61 static final int SSH_MSG_CHANNEL_EXTENDED_DATA= 95;
62 static final int SSH_MSG_CHANNEL_EOF= 96;
63 static final int SSH_MSG_CHANNEL_CLOSE= 97;
64 static final int SSH_MSG_CHANNEL_REQUEST= 98;
65 static final int SSH_MSG_CHANNEL_SUCCESS= 99;
66 static final int SSH_MSG_CHANNEL_FAILURE= 100;
68 private static final int PACKET_MAX_SIZE = 256 * 1024;
70 private byte[] V_S; // server version
71 private byte[] V_C=Util.str2byte("SSH-2.0-"+version); // client version
73 private byte[] I_C; // the payload of the client's SSH_MSG_KEXINIT
74 private byte[] I_S; // the payload of the server's SSH_MSG_KEXINIT
75 private byte[] K_S; // the host key
77 private byte[] session_id;
83 private byte[] MACc2s;
84 private byte[] MACs2c;
90 private Cipher s2ccipher;
91 private Cipher c2scipher;
94 //private byte[] mac_buf;
95 private byte[] s2cmac_result1;
96 private byte[] s2cmac_result2;
98 private Compression deflater;
99 private Compression inflater;
102 private Socket socket;
103 private int timeout=0;
105 private boolean isConnected=false;
107 private boolean isAuthed=false;
109 private Thread connectThread=null;
110 private Object lock=new Object();
112 boolean x11_forwarding=false;
113 boolean agent_forwarding=false;
116 OutputStream out=null;
118 static Random random;
123 SocketFactory socket_factory=null;
125 private java.util.Hashtable config=null;
127 private Proxy proxy=null;
128 private UserInfo userinfo;
130 private String hostKeyAlias=null;
131 private int serverAliveInterval=0;
132 private int serverAliveCountMax=1;
134 protected boolean daemon_thread=false;
136 private long kex_start_time=0L;
138 String host="127.0.0.1";
141 String username=null;
142 byte[] password=null;
146 Session(JSch jsch) throws JSchException{
150 packet=new Packet(buf);
153 public void connect() throws JSchException{
157 public void connect(int connectTimeout) throws JSchException{
159 throw new JSchException("session is already connected");
165 Class c=Class.forName(getConfig("random"));
166 random=(Random)(c.newInstance());
169 throw new JSchException(e.toString(), e);
172 Packet.setRandom(random);
174 if(JSch.getLogger().isEnabled(Logger.INFO)){
175 JSch.getLogger().log(Logger.INFO,
176 "Connecting to "+host+" port "+port);
185 if(socket_factory==null){
186 socket=Util.createSocket(host, port, connectTimeout);
187 in=socket.getInputStream();
188 out=socket.getOutputStream();
191 socket=socket_factory.createSocket(host, port);
192 in=socket_factory.getInputStream(socket);
193 out=socket_factory.getOutputStream(socket);
195 //if(timeout>0){ socket.setSoTimeout(timeout); }
196 socket.setTcpNoDelay(true);
197 io.setInputStream(in);
198 io.setOutputStream(out);
202 proxy.connect(socket_factory, host, port, connectTimeout);
203 io.setInputStream(proxy.getInputStream());
204 io.setOutputStream(proxy.getOutputStream());
205 socket=proxy.getSocket();
209 if(connectTimeout>0 && socket!=null){
210 socket.setSoTimeout(connectTimeout);
215 if(JSch.getLogger().isEnabled(Logger.INFO)){
216 JSch.getLogger().log(Logger.INFO,
217 "Connection established");
220 jsch.addSession(this);
223 // Some Cisco devices will miss to read '\n' if it is sent separately.
224 byte[] foo=new byte[V_C.length+1];
225 System.arraycopy(V_C, 0, foo, 0, V_C.length);
226 foo[foo.length-1]=(byte)'\n';
227 io.put(foo, 0, foo.length);
233 while(i<buf.buffer.length){
236 buf.buffer[i]=(byte)j; i++;
240 throw new JSchException("connection is closed by foreign host");
243 if(buf.buffer[i-1]==10){ // 0x0a
245 if(i>0 && buf.buffer[i-1]==13){ // 0x0d
251 ((i!=buf.buffer.length) &&
252 (buf.buffer[0]!='S'||buf.buffer[1]!='S'||
253 buf.buffer[2]!='H'||buf.buffer[3]!='-'))){
254 // It must not start with 'SSH-'
255 //System.err.println(new String(buf.buffer, 0, i);
259 if(i==buf.buffer.length ||
260 i<7 || // SSH-1.99 or SSH-2.0
261 (buf.buffer[4]=='1' && buf.buffer[6]!='9') // SSH-1.5
263 throw new JSchException("invalid server's version string");
268 V_S=new byte[i]; System.arraycopy(buf.buffer, 0, V_S, 0, i);
269 //System.err.println("V_S: ("+i+") ["+new String(V_S)+"]");
271 if(JSch.getLogger().isEnabled(Logger.INFO)){
272 JSch.getLogger().log(Logger.INFO,
273 "Remote version string: "+Util.byte2str(V_S));
274 JSch.getLogger().log(Logger.INFO,
275 "Local version string: "+Util.byte2str(V_C));
281 if(buf.getCommand()!=SSH_MSG_KEXINIT){
283 throw new JSchException("invalid protocol: "+buf.getCommand());
286 if(JSch.getLogger().isEnabled(Logger.INFO)){
287 JSch.getLogger().log(Logger.INFO,
288 "SSH_MSG_KEXINIT received");
291 KeyExchange kex=receive_kexinit(buf);
295 if(kex.getState()==buf.getCommand()){
296 kex_start_time=System.currentTimeMillis();
297 boolean result=kex.next(buf);
299 //System.err.println("verify: "+result);
301 throw new JSchException("verify: "+result);
306 throw new JSchException("invalid protocol(kex): "+buf.getCommand());
308 if(kex.getState()==KeyExchange.STATE_END){
313 try{ checkHost(host, port, kex); }
314 catch(JSchException ee){
321 // receive SSH_MSG_NEWKEYS(21)
323 //System.err.println("read: 21 ? "+buf.getCommand());
324 if(buf.getCommand()==SSH_MSG_NEWKEYS){
326 if(JSch.getLogger().isEnabled(Logger.INFO)){
327 JSch.getLogger().log(Logger.INFO,
328 "SSH_MSG_NEWKEYS received");
331 receive_newkeys(buf, kex);
335 throw new JSchException("invalid protocol(newkyes): "+buf.getCommand());
339 boolean auth_cancel=false;
343 Class c=Class.forName(getConfig("userauth.none"));
344 ua=(UserAuth)(c.newInstance());
347 throw new JSchException(e.toString(), e);
352 String cmethods=getConfig("PreferredAuthentications");
353 String[] cmethoda=Util.split(cmethods, ",");
355 String smethods=null;
357 smethods=((UserAuthNone)ua).getMethods();
359 smethods=smethods.toLowerCase();
362 // methods: publickey,password,keyboard-interactive
363 //smethods="publickey,password,keyboard-interactive";
368 String[] smethoda=Util.split(smethods, ",");
375 //System.err.println("methods: "+methods);
378 cmethoda!=null && methodi<cmethoda.length){
380 String method=cmethoda[methodi++];
381 boolean acceptable=false;
382 for(int k=0; k<smethoda.length; k++){
383 if(smethoda[k].equals(method)){
392 //System.err.println(" method: "+method);
394 if(JSch.getLogger().isEnabled(Logger.INFO)){
395 String str="Authentications that can continue: ";
396 for(int k=methodi-1; k<cmethoda.length; k++){
398 if(k+1<cmethoda.length)
401 JSch.getLogger().log(Logger.INFO,
403 JSch.getLogger().log(Logger.INFO,
404 "Next authentication method: "+method);
410 if(getConfig("userauth."+method)!=null){
411 c=Class.forName(getConfig("userauth."+method));
412 ua=(UserAuth)(c.newInstance());
416 if(JSch.getLogger().isEnabled(Logger.WARN)){
417 JSch.getLogger().log(Logger.WARN,
418 "failed to load "+method+" method");
427 JSch.getLogger().isEnabled(Logger.INFO)){
428 JSch.getLogger().log(Logger.INFO,
429 "Authentication succeeded ("+method+").");
432 catch(JSchAuthCancelException ee){
435 catch(JSchPartialAuthException ee){
436 String tmp = smethods;
437 smethods=ee.getMethods();
438 smethoda=Util.split(smethods, ",");
439 if(!tmp.equals(smethods)){
442 //System.err.println("PartialAuth: "+methods);
446 catch(RuntimeException ee){
450 //System.err.println("ee: "+ee); // SSH_MSG_DISCONNECT: 2 Too many authentication failures
460 throw new JSchException("Auth cancel");
461 throw new JSchException("Auth fail");
464 if(connectTimeout>0 || timeout>0){
465 socket.setSoTimeout(timeout);
472 connectThread=new Thread(this);
473 connectThread.setName("Connect thread "+host+" session");
475 connectThread.setDaemon(daemon_thread);
477 connectThread.start();
480 // The session has been already down and
481 // we don't have to start new thread.
490 buf.putByte((byte)SSH_MSG_DISCONNECT);
492 buf.putString(Util.str2byte(e.toString()));
493 buf.putString(Util.str2byte("en"));
501 //e.printStackTrace();
502 if(e instanceof RuntimeException) throw (RuntimeException)e;
503 if(e instanceof JSchException) throw (JSchException)e;
504 throw new JSchException("Session.connect: "+e);
507 Util.bzero(this.password);
512 private KeyExchange receive_kexinit(Buffer buf) throws Exception {
514 if(j!=buf.getLength()){ // packet was compressed and
515 buf.getByte(); // j is the size of deflated packet.
516 I_S=new byte[buf.index-5];
519 I_S=new byte[j-1-buf.getByte()];
521 System.arraycopy(buf.buffer, buf.s, I_S, 0, I_S.length);
523 if(!in_kex){ // We are in rekeying activated by the remote!
527 guess=KeyExchange.guess(I_S, I_C);
529 throw new JSchException("Algorithm negotiation fail");
533 (guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS].equals("none") ||
534 (guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC].equals("none")))){
535 throw new JSchException("NONE Cipher should not be chosen before authentification is successed.");
538 KeyExchange kex=null;
540 Class c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_KEX_ALGS]));
541 kex=(KeyExchange)(c.newInstance());
544 throw new JSchException(e.toString(), e);
547 kex.init(this, V_S, V_C, I_S, I_C);
551 private boolean in_kex=false;
552 public void rekey() throws Exception {
555 private void send_kexinit() throws Exception {
559 String cipherc2s=getConfig("cipher.c2s");
560 String ciphers2c=getConfig("cipher.s2c");
562 String[] not_available=checkCiphers(getConfig("CheckCiphers"));
563 if(not_available!=null && not_available.length>0){
564 cipherc2s=Util.diffString(cipherc2s, not_available);
565 ciphers2c=Util.diffString(ciphers2c, not_available);
566 if(cipherc2s==null || ciphers2c==null){
567 throw new JSchException("There are not any available ciphers.");
572 kex_start_time=System.currentTimeMillis();
574 // byte SSH_MSG_KEXINIT(20)
575 // byte[16] cookie (random bytes)
576 // string kex_algorithms
577 // string server_host_key_algorithms
578 // string encryption_algorithms_client_to_server
579 // string encryption_algorithms_server_to_client
580 // string mac_algorithms_client_to_server
581 // string mac_algorithms_server_to_client
582 // string compression_algorithms_client_to_server
583 // string compression_algorithms_server_to_client
584 // string languages_client_to_server
585 // string languages_server_to_client
586 Buffer buf = new Buffer(); // send_kexinit may be invoked
587 Packet packet = new Packet(buf); // by user thread.
589 buf.putByte((byte) SSH_MSG_KEXINIT);
590 synchronized(random){
591 random.fill(buf.buffer, buf.index, 16); buf.skip(16);
593 buf.putString(Util.str2byte(getConfig("kex")));
594 buf.putString(Util.str2byte(getConfig("server_host_key")));
595 buf.putString(Util.str2byte(cipherc2s));
596 buf.putString(Util.str2byte(ciphers2c));
597 buf.putString(Util.str2byte(getConfig("mac.c2s")));
598 buf.putString(Util.str2byte(getConfig("mac.s2c")));
599 buf.putString(Util.str2byte(getConfig("compression.c2s")));
600 buf.putString(Util.str2byte(getConfig("compression.s2c")));
601 buf.putString(Util.str2byte(getConfig("lang.c2s")));
602 buf.putString(Util.str2byte(getConfig("lang.s2c")));
603 buf.putByte((byte)0);
607 I_C=new byte[buf.getLength()];
612 if(JSch.getLogger().isEnabled(Logger.INFO)){
613 JSch.getLogger().log(Logger.INFO,
614 "SSH_MSG_KEXINIT sent");
618 private void send_newkeys() throws Exception {
619 // send SSH_MSG_NEWKEYS(21)
621 buf.putByte((byte)SSH_MSG_NEWKEYS);
624 if(JSch.getLogger().isEnabled(Logger.INFO)){
625 JSch.getLogger().log(Logger.INFO,
626 "SSH_MSG_NEWKEYS sent");
630 private void checkHost(String chost, int port, KeyExchange kex) throws JSchException {
631 String shkc=getConfig("StrictHostKeyChecking");
633 if(hostKeyAlias!=null){
637 //System.err.println("shkc: "+shkc);
639 byte[] K_S=kex.getHostKey();
640 String key_type=kex.getKeyType();
641 String key_fprint=kex.getFingerPrint();
643 if(hostKeyAlias==null && port!=22){
644 chost=("["+chost+"]:"+port);
647 // hostkey=new HostKey(chost, K_S);
649 HostKeyRepository hkr=jsch.getHostKeyRepository();
652 i=hkr.check(chost, K_S);
655 boolean insert=false;
657 if((shkc.equals("ask") || shkc.equals("yes")) &&
658 i==HostKeyRepository.CHANGED){
661 file=hkr.getKnownHostsRepositoryID();
663 if(file==null){file="known_hosts";}
669 "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n"+
670 "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n"+
671 "Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n"+
672 "It is also possible that the "+key_type+" host key has just been changed.\n"+
673 "The fingerprint for the "+key_type+" key sent by the remote host is\n"+
675 "Please contact your system administrator.\n"+
676 "Add correct host key in "+file+" to get rid of this message.";
678 if(shkc.equals("ask")){
679 b=userinfo.promptYesNo(message+
680 "\nDo you want to delete the old key and insert the new key?");
682 else{ // shkc.equals("yes")
683 userinfo.showMessage(message);
688 throw new JSchException("HostKey has been changed: "+chost);
693 (key_type.equals("DSA") ? "ssh-dss" : "ssh-rsa"),
699 if((shkc.equals("ask") || shkc.equals("yes")) &&
700 (i!=HostKeyRepository.OK) && !insert){
701 if(shkc.equals("yes")){
702 throw new JSchException("reject HostKey: "+host);
704 //System.err.println("finger-print: "+key_fprint);
706 boolean foo=userinfo.promptYesNo(
707 "The authenticity of host '"+host+"' can't be established.\n"+
708 key_type+" key fingerprint is "+key_fprint+".\n"+
709 "Are you sure you want to continue connecting?"
712 throw new JSchException("reject HostKey: "+host);
717 if(i==HostKeyRepository.NOT_INCLUDED)
718 throw new JSchException("UnknownHostKey: "+host+". "+key_type+" key fingerprint is "+key_fprint);
720 throw new JSchException("HostKey has been changed: "+host);
724 if(shkc.equals("no") &&
725 HostKeyRepository.NOT_INCLUDED==i){
729 if(i==HostKeyRepository.OK &&
730 JSch.getLogger().isEnabled(Logger.INFO)){
731 JSch.getLogger().log(Logger.INFO,
732 "Host '"+host+"' is known and mathces the "+key_type+" host key");
736 JSch.getLogger().isEnabled(Logger.WARN)){
737 JSch.getLogger().log(Logger.WARN,
738 "Permanently added '"+host+"' ("+key_type+") to the list of known hosts.");
741 String hkh=getConfig("HashKnownHosts");
742 if(hkh.equals("yes") && (hkr instanceof KnownHosts)){
743 hostkey=((KnownHosts)hkr).createHashedHostKey(chost, K_S);
746 hostkey=new HostKey(chost, K_S);
751 hkr.add(hostkey, userinfo);
758 //public void start(){ (new Thread(this)).start(); }
760 public Channel openChannel(String type) throws JSchException{
762 throw new JSchException("session is down");
765 Channel channel=Channel.getChannel(type);
771 //e.printStackTrace();
776 // encode will bin invoked in write with synchronization.
777 public void encode(Packet packet) throws Exception{
778 //System.err.println("encode: "+packet.buffer.getCommand());
779 //System.err.println(" "+packet.buffer.index);
780 //if(packet.buffer.getCommand()==96){
781 //Thread.dumpStack();
784 packet.buffer.index=deflater.compress(packet.buffer.buffer,
785 5, packet.buffer.index);
788 //packet.padding(c2scipher.getIVSize());
789 packet.padding(c2scipher_size);
790 int pad=packet.buffer.buffer[4];
791 synchronized(random){
792 random.fill(packet.buffer.buffer, packet.buffer.index-pad, pad);
801 c2smac.update(packet.buffer.buffer, 0, packet.buffer.index);
802 c2smac.doFinal(packet.buffer.buffer, packet.buffer.index);
805 byte[] buf=packet.buffer.buffer;
806 c2scipher.update(buf, 0, packet.buffer.index, buf, 0);
809 packet.buffer.skip(c2smac.getBlockSize());
813 int[] uncompress_len=new int[1];
815 private int s2ccipher_size=8;
816 private int c2scipher_size=8;
817 public Buffer read(Buffer buf) throws Exception{
821 io.getByte(buf.buffer, buf.index, s2ccipher_size);
822 buf.index+=s2ccipher_size;
824 s2ccipher.update(buf.buffer, 0, s2ccipher_size, buf.buffer, 0);
826 j=((buf.buffer[0]<<24)&0xff000000)|
827 ((buf.buffer[1]<<16)&0x00ff0000)|
828 ((buf.buffer[2]<< 8)&0x0000ff00)|
829 ((buf.buffer[3] )&0x000000ff);
830 // RFC 4253 6.1. Maximum Packet Length
831 if(j<5 || j>PACKET_MAX_SIZE){
832 start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE);
834 int need = j+4-s2ccipher_size;
836 // throw new IOException("invalid data");
838 if((buf.index+need)>buf.buffer.length){
839 byte[] foo=new byte[buf.index+need];
840 System.arraycopy(buf.buffer, 0, foo, 0, buf.index);
844 if((need%s2ccipher_size)!=0){
845 String message="Bad packet length "+need;
846 if(JSch.getLogger().isEnabled(Logger.FATAL)){
847 JSch.getLogger().log(Logger.FATAL, message);
849 start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-s2ccipher_size);
853 io.getByte(buf.buffer, buf.index, need); buf.index+=(need);
855 s2ccipher.update(buf.buffer, s2ccipher_size, need, buf.buffer, s2ccipher_size);
861 s2cmac.update(buf.buffer, 0, buf.index);
863 s2cmac.doFinal(s2cmac_result1, 0);
864 io.getByte(s2cmac_result2, 0, s2cmac_result2.length);
865 if(!java.util.Arrays.equals(s2cmac_result1, s2cmac_result2)){
866 if(need > PACKET_MAX_SIZE){
867 throw new IOException("MAC Error");
869 start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-need);
877 //inflater.uncompress(buf);
878 int pad=buf.buffer[4];
879 uncompress_len[0]=buf.index-5-pad;
880 byte[] foo=inflater.uncompress(buf.buffer, 5, uncompress_len);
883 buf.index=5+uncompress_len[0];
886 System.err.println("fail in inflater");
891 int type=buf.getCommand()&0xff;
892 //System.err.println("read: "+type);
893 if(type==SSH_MSG_DISCONNECT){
895 buf.getInt();buf.getShort();
896 int reason_code=buf.getInt();
897 byte[] description=buf.getString();
898 byte[] language_tag=buf.getString();
899 throw new JSchException("SSH_MSG_DISCONNECT: "+
901 " "+Util.byte2str(description)+
902 " "+Util.byte2str(language_tag));
905 else if(type==SSH_MSG_IGNORE){
907 else if(type==SSH_MSG_UNIMPLEMENTED){
909 buf.getInt();buf.getShort();
910 int reason_id=buf.getInt();
911 if(JSch.getLogger().isEnabled(Logger.INFO)){
912 JSch.getLogger().log(Logger.INFO,
913 "Received SSH_MSG_UNIMPLEMENTED for "+reason_id);
916 else if(type==SSH_MSG_DEBUG){
918 buf.getInt();buf.getShort();
920 byte always_display=(byte)buf.getByte();
921 byte[] message=buf.getString();
922 byte[] language_tag=buf.getString();
923 System.err.println("SSH_MSG_DEBUG:"+
924 " "+Util.byte2str(message)+
925 " "+Util.byte2str(language_tag));
928 else if(type==SSH_MSG_CHANNEL_WINDOW_ADJUST){
930 buf.getInt();buf.getShort();
931 Channel c=Channel.getChannel(buf.getInt(), this);
935 c.addRemoteWindowSize(buf.getInt());
938 else if(type==UserAuth.SSH_MSG_USERAUTH_SUCCESS){
940 if(inflater==null && deflater==null){
942 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];
943 initDeflater(method);
945 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];
946 initInflater(method);
958 private void start_discard(Buffer buf, Cipher cipher, MAC mac,
959 int packet_length, int discard) throws JSchException, IOException{
960 MAC discard_mac = null;
963 throw new JSchException("Packet corrupt");
966 if(packet_length!=PACKET_MAX_SIZE && mac != null){
970 discard -= buf.index;
974 int len = discard>buf.buffer.length ? buf.buffer.length : discard;
975 io.getByte(buf.buffer, 0, len);
976 if(discard_mac!=null){
977 discard_mac.update(buf.buffer, 0, len);
982 if(discard_mac!=null){
983 discard_mac.doFinal(buf.buffer, 0);
986 throw new JSchException("Packet corrupt");
989 byte[] getSessionId(){
993 private void receive_newkeys(Buffer buf, KeyExchange kex) throws Exception {
997 private void updateKeys(KeyExchange kex) throws Exception{
1000 HASH hash=kex.getHash();
1002 // String[] guess=kex.guess;
1004 if(session_id==null){
1005 session_id=new byte[H.length];
1006 System.arraycopy(H, 0, session_id, 0, H.length);
1010 Initial IV client to server: HASH (K || H || "A" || session_id)
1011 Initial IV server to client: HASH (K || H || "B" || session_id)
1012 Encryption key client to server: HASH (K || H || "C" || session_id)
1013 Encryption key server to client: HASH (K || H || "D" || session_id)
1014 Integrity key client to server: HASH (K || H || "E" || session_id)
1015 Integrity key server to client: HASH (K || H || "F" || session_id)
1021 buf.putByte((byte)0x41);
1022 buf.putByte(session_id);
1023 hash.update(buf.buffer, 0, buf.index);
1024 IVc2s=hash.digest();
1026 int j=buf.index-session_id.length-1;
1029 hash.update(buf.buffer, 0, buf.index);
1030 IVs2c=hash.digest();
1033 hash.update(buf.buffer, 0, buf.index);
1037 hash.update(buf.buffer, 0, buf.index);
1041 hash.update(buf.buffer, 0, buf.index);
1042 MACc2s=hash.digest();
1045 hash.update(buf.buffer, 0, buf.index);
1046 MACs2c=hash.digest();
1052 method=guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC];
1053 c=Class.forName(getConfig(method));
1054 s2ccipher=(Cipher)(c.newInstance());
1055 while(s2ccipher.getBlockSize()>Es2c.length){
1060 hash.update(buf.buffer, 0, buf.index);
1061 byte[] foo=hash.digest();
1062 byte[] bar=new byte[Es2c.length+foo.length];
1063 System.arraycopy(Es2c, 0, bar, 0, Es2c.length);
1064 System.arraycopy(foo, 0, bar, Es2c.length, foo.length);
1067 s2ccipher.init(Cipher.DECRYPT_MODE, Es2c, IVs2c);
1068 s2ccipher_size=s2ccipher.getIVSize();
1070 method=guess[KeyExchange.PROPOSAL_MAC_ALGS_STOC];
1071 c=Class.forName(getConfig(method));
1072 s2cmac=(MAC)(c.newInstance());
1073 s2cmac.init(MACs2c);
1074 //mac_buf=new byte[s2cmac.getBlockSize()];
1075 s2cmac_result1=new byte[s2cmac.getBlockSize()];
1076 s2cmac_result2=new byte[s2cmac.getBlockSize()];
1078 method=guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS];
1079 c=Class.forName(getConfig(method));
1080 c2scipher=(Cipher)(c.newInstance());
1081 while(c2scipher.getBlockSize()>Ec2s.length){
1086 hash.update(buf.buffer, 0, buf.index);
1087 byte[] foo=hash.digest();
1088 byte[] bar=new byte[Ec2s.length+foo.length];
1089 System.arraycopy(Ec2s, 0, bar, 0, Ec2s.length);
1090 System.arraycopy(foo, 0, bar, Ec2s.length, foo.length);
1093 c2scipher.init(Cipher.ENCRYPT_MODE, Ec2s, IVc2s);
1094 c2scipher_size=c2scipher.getIVSize();
1096 method=guess[KeyExchange.PROPOSAL_MAC_ALGS_CTOS];
1097 c=Class.forName(getConfig(method));
1098 c2smac=(MAC)(c.newInstance());
1099 c2smac.init(MACc2s);
1101 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];
1102 initDeflater(method);
1104 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];
1105 initInflater(method);
1108 if(e instanceof JSchException)
1110 throw new JSchException(e.toString(), e);
1111 //System.err.println("updatekeys: "+e);
1115 /*public*/ /*synchronized*/ void write(Packet packet, Channel c, int length) throws Exception{
1116 long t = getTimeout();
1119 if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){
1120 throw new JSchException("timeout in wating for rekeying process.");
1122 try{Thread.sleep(10);}
1123 catch(java.lang.InterruptedException e){};
1127 if(c.rwsize>=length){
1132 if(c.close || !c.isConnected()){
1133 throw new IOException("channel is broken");
1136 boolean sendit=false;
1147 s=packet.shift((int)len, (c2smac!=null ? c2smac.getBlockSize() : 0));
1149 command=packet.buffer.getCommand();
1150 recipient=c.getRecipient();
1161 packet.unshift(command, recipient, s, length);
1168 if(c.rwsize>=length){
1176 catch(java.lang.InterruptedException e){
1187 public void write(Packet packet) throws Exception{
1188 // System.err.println("in_kex="+in_kex+" "+(packet.buffer.getCommand()));
1189 long t = getTimeout();
1191 if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){
1192 throw new JSchException("timeout in wating for rekeying process.");
1194 byte command=packet.buffer.getCommand();
1195 //System.err.println("command: "+command);
1196 if(command==SSH_MSG_KEXINIT ||
1197 command==SSH_MSG_NEWKEYS ||
1198 command==SSH_MSG_KEXDH_INIT ||
1199 command==SSH_MSG_KEXDH_REPLY ||
1200 command==SSH_MSG_KEX_DH_GEX_GROUP ||
1201 command==SSH_MSG_KEX_DH_GEX_INIT ||
1202 command==SSH_MSG_KEX_DH_GEX_REPLY ||
1203 command==SSH_MSG_KEX_DH_GEX_REQUEST ||
1204 command==SSH_MSG_DISCONNECT){
1207 try{Thread.sleep(10);}
1208 catch(java.lang.InterruptedException e){};
1213 private void _write(Packet packet) throws Exception{
1228 Buffer buf=new Buffer();
1229 Packet packet=new Packet(buf);
1232 int[] start=new int[1];
1233 int[] length=new int[1];
1234 KeyExchange kex=null;
1238 while(isConnected &&
1244 catch(InterruptedIOException/*SocketTimeoutException*/ ee){
1245 if(!in_kex && stimeout<serverAliveCountMax){
1253 int msgType=buf.getCommand()&0xff;
1255 if(kex!=null && kex.getState()==msgType){
1256 kex_start_time=System.currentTimeMillis();
1257 boolean result=kex.next(buf);
1259 throw new JSchException("verify: "+result);
1265 case SSH_MSG_KEXINIT:
1266 //System.err.println("KEXINIT");
1267 kex=receive_kexinit(buf);
1270 case SSH_MSG_NEWKEYS:
1271 //System.err.println("NEWKEYS");
1273 receive_newkeys(buf, kex);
1277 case SSH_MSG_CHANNEL_DATA:
1282 channel=Channel.getChannel(i, this);
1283 foo=buf.getString(start, length);
1293 channel.write(foo, start[0], length[0]);
1296 //System.err.println(e);
1297 try{channel.disconnect();}catch(Exception ee){}
1301 channel.setLocalWindowSize(channel.lwsize-len);
1302 if(channel.lwsize<channel.lwsize_max/2){
1304 buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
1305 buf.putInt(channel.getRecipient());
1306 buf.putInt(channel.lwsize_max-channel.lwsize);
1308 channel.setLocalWindowSize(channel.lwsize_max);
1312 case SSH_MSG_CHANNEL_EXTENDED_DATA:
1316 channel=Channel.getChannel(i, this);
1317 buf.getInt(); // data_type_code == 1
1318 foo=buf.getString(start, length);
1319 //System.err.println("stderr: "+new String(foo,start[0],length[0]));
1328 channel.write_ext(foo, start[0], length[0]);
1331 channel.setLocalWindowSize(channel.lwsize-len);
1332 if(channel.lwsize<channel.lwsize_max/2){
1334 buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
1335 buf.putInt(channel.getRecipient());
1336 buf.putInt(channel.lwsize_max-channel.lwsize);
1338 channel.setLocalWindowSize(channel.lwsize_max);
1342 case SSH_MSG_CHANNEL_WINDOW_ADJUST:
1346 channel=Channel.getChannel(i, this);
1350 channel.addRemoteWindowSize(buf.getInt());
1353 case SSH_MSG_CHANNEL_EOF:
1357 channel=Channel.getChannel(i, this);
1359 //channel.eof_remote=true;
1361 channel.eof_remote();
1365 buf.putByte((byte)SSH_MSG_CHANNEL_EOF);
1366 buf.putInt(channel.getRecipient());
1370 case SSH_MSG_CHANNEL_CLOSE:
1374 channel=Channel.getChannel(i, this);
1377 channel.disconnect();
1380 if(Channel.pool.size()==0){
1385 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
1389 channel=Channel.getChannel(i, this);
1394 long rws=buf.getUInt();
1395 int rps=buf.getInt();
1397 channel.setRemoteWindowSize(rws);
1398 channel.setRemotePacketSize(rps);
1399 channel.setRecipient(r);
1401 case SSH_MSG_CHANNEL_OPEN_FAILURE:
1405 channel=Channel.getChannel(i, this);
1409 int reason_code=buf.getInt();
1410 //foo=buf.getString(); // additional textual information
1411 //foo=buf.getString(); // language tag
1412 channel.exitstatus=reason_code;
1414 channel.eof_remote=true;
1415 channel.setRecipient(0);
1417 case SSH_MSG_CHANNEL_REQUEST:
1421 foo=buf.getString();
1422 boolean reply=(buf.getByte()!=0);
1423 channel=Channel.getChannel(i, this);
1425 byte reply_type=(byte)SSH_MSG_CHANNEL_FAILURE;
1426 if((Util.byte2str(foo)).equals("exit-status")){
1427 i=buf.getInt(); // exit-status
1428 channel.setExitStatus(i);
1429 reply_type=(byte)SSH_MSG_CHANNEL_SUCCESS;
1433 buf.putByte(reply_type);
1434 buf.putInt(channel.getRecipient());
1441 case SSH_MSG_CHANNEL_OPEN:
1444 foo=buf.getString();
1445 String ctyp=Util.byte2str(foo);
1446 if(!"forwarded-tcpip".equals(ctyp) &&
1447 !("x11".equals(ctyp) && x11_forwarding) &&
1448 !("auth-agent@openssh.com".equals(ctyp) && agent_forwarding)){
1449 //System.err.println("Session.run: CHANNEL OPEN "+ctyp);
1450 //throw new IOException("Session.run: CHANNEL OPEN "+ctyp);
1452 buf.putByte((byte)SSH_MSG_CHANNEL_OPEN_FAILURE);
1453 buf.putInt(buf.getInt());
1454 buf.putInt(Channel.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED);
1455 buf.putString(Util.empty);
1456 buf.putString(Util.empty);
1460 channel=Channel.getChannel(ctyp);
1461 addChannel(channel);
1462 channel.getData(buf);
1465 Thread tmp=new Thread(channel);
1466 tmp.setName("Channel "+ctyp+" "+host);
1468 tmp.setDaemon(daemon_thread);
1473 case SSH_MSG_CHANNEL_SUCCESS:
1477 channel=Channel.getChannel(i, this);
1483 case SSH_MSG_CHANNEL_FAILURE:
1487 channel=Channel.getChannel(i, this);
1493 case SSH_MSG_GLOBAL_REQUEST:
1496 foo=buf.getString(); // request name
1497 reply=(buf.getByte()!=0);
1500 buf.putByte((byte)SSH_MSG_REQUEST_FAILURE);
1504 case SSH_MSG_REQUEST_FAILURE:
1505 case SSH_MSG_REQUEST_SUCCESS:
1506 Thread t=grr.getThread();
1508 grr.setReply(msgType==SSH_MSG_REQUEST_SUCCESS? 1 : 0);
1513 //System.err.println("Session.run: unsupported type "+msgType);
1514 throw new IOException("Unknown SSH message type "+msgType);
1520 if(JSch.getLogger().isEnabled(Logger.INFO)){
1521 JSch.getLogger().log(Logger.INFO,
1522 "Caught an exception, leaving main loop due to " + e.getMessage());
1524 //System.err.println("# Session.run");
1525 //e.printStackTrace();
1530 catch(NullPointerException e){
1531 //System.err.println("@1");
1532 //e.printStackTrace();
1535 //System.err.println("@2");
1536 //e.printStackTrace();
1541 public void disconnect(){
1542 if(!isConnected) return;
1543 //System.err.println(this+": disconnect");
1544 //Thread.dumpStack();
1545 if(JSch.getLogger().isEnabled(Logger.INFO)){
1546 JSch.getLogger().log(Logger.INFO,
1547 "Disconnecting from "+host+" port "+port);
1550 for(int i=0; i<Channel.pool.size(); i++){
1552 Channel c=((Channel)(Channel.pool.elementAt(i)));
1553 if(c.session==this) c.eof();
1560 Channel.disconnect(this);
1564 PortWatcher.delPort(this);
1565 ChannelForwardedTCPIP.delPort(this);
1568 if(connectThread!=null){
1570 connectThread.interrupt();
1577 if(io.in!=null) io.in.close();
1578 if(io.out!=null) io.out.close();
1579 if(io.out_ext!=null) io.out_ext.close();
1586 synchronized(proxy){
1593 // e.printStackTrace();
1597 // synchronized(jsch.pool){
1598 // jsch.pool.removeElement(this);
1601 jsch.removeSession(this);
1606 public int setPortForwardingL(int lport, String host, int rport) throws JSchException{
1607 return setPortForwardingL("127.0.0.1", lport, host, rport);
1609 public int setPortForwardingL(String boundaddress, int lport, String host, int rport) throws JSchException{
1610 return setPortForwardingL(boundaddress, lport, host, rport, null);
1612 public int setPortForwardingL(String boundaddress, int lport, String host, int rport, ServerSocketFactory ssf) throws JSchException{
1613 PortWatcher pw=PortWatcher.addPort(this, boundaddress, lport, host, rport, ssf);
1614 Thread tmp=new Thread(pw);
1615 tmp.setName("PortWatcher Thread for "+host);
1617 tmp.setDaemon(daemon_thread);
1622 public void delPortForwardingL(int lport) throws JSchException{
1623 delPortForwardingL("127.0.0.1", lport);
1625 public void delPortForwardingL(String boundaddress, int lport) throws JSchException{
1626 PortWatcher.delPort(this, boundaddress, lport);
1628 public String[] getPortForwardingL() throws JSchException{
1629 return PortWatcher.getPortForwarding(this);
1632 public void setPortForwardingR(int rport, String host, int lport) throws JSchException{
1633 setPortForwardingR(null, rport, host, lport, (SocketFactory)null);
1635 public void setPortForwardingR(String bind_address, int rport, String host, int lport) throws JSchException{
1636 setPortForwardingR(bind_address, rport, host, lport, (SocketFactory)null);
1638 public void setPortForwardingR(int rport, String host, int lport, SocketFactory sf) throws JSchException{
1639 setPortForwardingR(null, rport, host, lport, sf);
1641 public void setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf) throws JSchException{
1642 ChannelForwardedTCPIP.addPort(this, bind_address, rport, host, lport, sf);
1643 setPortForwarding(bind_address, rport);
1646 public void setPortForwardingR(int rport, String daemon) throws JSchException{
1647 setPortForwardingR(null, rport, daemon, null);
1649 public void setPortForwardingR(int rport, String daemon, Object[] arg) throws JSchException{
1650 setPortForwardingR(null, rport, daemon, arg);
1652 public void setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg) throws JSchException{
1653 ChannelForwardedTCPIP.addPort(this, bind_address, rport, daemon, arg);
1654 setPortForwarding(bind_address, rport);
1657 private class GlobalRequestReply{
1658 private Thread thread=null;
1659 private int reply=-1;
1660 void setThread(Thread thread){
1664 Thread getThread(){ return thread; }
1665 void setReply(int reply){ this.reply=reply; }
1666 int getReply(){ return this.reply; }
1668 private GlobalRequestReply grr=new GlobalRequestReply();
1669 private void setPortForwarding(String bind_address, int rport) throws JSchException{
1671 Buffer buf=new Buffer(100); // ??
1672 Packet packet=new Packet(buf);
1674 String address_to_bind=ChannelForwardedTCPIP.normalize(bind_address);
1677 // byte SSH_MSG_GLOBAL_REQUEST 80
1678 // string "tcpip-forward"
1679 // boolean want_reply
1680 // string address_to_bind
1681 // uint32 port number to bind
1683 buf.putByte((byte) SSH_MSG_GLOBAL_REQUEST);
1684 buf.putString(Util.str2byte("tcpip-forward"));
1685 // buf.putByte((byte)0);
1686 buf.putByte((byte)1);
1687 buf.putString(Util.str2byte(address_to_bind));
1692 if(e instanceof Throwable)
1693 throw new JSchException(e.toString(), (Throwable)e);
1694 throw new JSchException(e.toString());
1697 grr.setThread(Thread.currentThread());
1698 try{ Thread.sleep(10000);}
1701 int reply=grr.getReply();
1702 grr.setThread(null);
1704 throw new JSchException("remote port forwarding failed for listen port "+rport);
1708 public void delPortForwardingR(int rport) throws JSchException{
1709 ChannelForwardedTCPIP.delPort(this, rport);
1712 private void initDeflater(String method) throws JSchException{
1713 if(method.equals("none")){
1717 String foo=getConfig(method);
1719 if(method.equals("zlib") ||
1720 (isAuthed && method.equals("zlib@openssh.com"))){
1722 Class c=Class.forName(foo);
1723 deflater=(Compression)(c.newInstance());
1725 try{ level=Integer.parseInt(getConfig("compression_level"));}
1726 catch(Exception ee){ }
1727 deflater.init(Compression.DEFLATER, level);
1729 catch(Exception ee){
1730 throw new JSchException(ee.toString(), ee);
1731 //System.err.println(foo+" isn't accessible.");
1736 private void initInflater(String method) throws JSchException{
1737 if(method.equals("none")){
1741 String foo=getConfig(method);
1743 if(method.equals("zlib") ||
1744 (isAuthed && method.equals("zlib@openssh.com"))){
1746 Class c=Class.forName(foo);
1747 inflater=(Compression)(c.newInstance());
1748 inflater.init(Compression.INFLATER, 0);
1750 catch(Exception ee){
1751 throw new JSchException(ee.toString(), ee);
1752 //System.err.println(foo+" isn't accessible.");
1758 void addChannel(Channel channel){
1759 channel.setSession(this);
1762 public void setProxy(Proxy proxy){ this.proxy=proxy; }
1763 public void setHost(String host){ this.host=host; }
1764 public void setPort(int port){ this.port=port; }
1765 void setUserName(String username){ this.username=username; }
1766 public void setUserInfo(UserInfo userinfo){ this.userinfo=userinfo; }
1767 public UserInfo getUserInfo(){ return userinfo; }
1768 public void setInputStream(InputStream in){ this.in=in; }
1769 public void setOutputStream(OutputStream out){ this.out=out; }
1770 public void setX11Host(String host){ ChannelX11.setHost(host); }
1771 public void setX11Port(int port){ ChannelX11.setPort(port); }
1772 public void setX11Cookie(String cookie){ ChannelX11.setCookie(cookie); }
1773 public void setPassword(String password){
1775 this.password=Util.str2byte(password);
1777 public void setPassword(byte[] password){
1779 this.password=new byte[password.length];
1780 System.arraycopy(password, 0, this.password, 0, password.length);
1784 public void setConfig(java.util.Properties newconf){
1785 setConfig((java.util.Hashtable)newconf);
1788 public void setConfig(java.util.Hashtable newconf){
1791 config=new java.util.Hashtable();
1792 for(java.util.Enumeration e=newconf.keys() ; e.hasMoreElements() ;) {
1793 String key=(String)(e.nextElement());
1794 config.put(key, (String)(newconf.get(key)));
1799 public void setConfig(String key, String value){
1802 config=new java.util.Hashtable();
1804 config.put(key, value);
1808 public String getConfig(String key){
1811 foo=config.get(key);
1812 if(foo instanceof String) return (String)foo;
1814 foo=jsch.getConfig(key);
1815 if(foo instanceof String) return (String)foo;
1819 public void setSocketFactory(SocketFactory sfactory){
1820 socket_factory=sfactory;
1822 public boolean isConnected(){ return isConnected; }
1823 public int getTimeout(){ return timeout; }
1824 public void setTimeout(int timeout) throws JSchException {
1827 throw new JSchException("invalid timeout value");
1829 this.timeout=timeout;
1833 socket.setSoTimeout(timeout);
1834 this.timeout=timeout;
1837 if(e instanceof Throwable)
1838 throw new JSchException(e.toString(), (Throwable)e);
1839 throw new JSchException(e.toString());
1842 public String getServerVersion(){
1843 return Util.byte2str(V_S);
1845 public String getClientVersion(){
1846 return Util.byte2str(V_C);
1848 public void setClientVersion(String cv){
1849 V_C=Util.str2byte(cv);
1852 public void sendIgnore() throws Exception{
1853 Buffer buf=new Buffer();
1854 Packet packet=new Packet(buf);
1856 buf.putByte((byte)SSH_MSG_IGNORE);
1860 private static final byte[] keepalivemsg=Util.str2byte("keepalive@jcraft.com");
1861 public void sendKeepAliveMsg() throws Exception{
1862 Buffer buf=new Buffer();
1863 Packet packet=new Packet(buf);
1865 buf.putByte((byte)SSH_MSG_GLOBAL_REQUEST);
1866 buf.putString(keepalivemsg);
1867 buf.putByte((byte)1);
1871 private HostKey hostkey=null;
1872 public HostKey getHostKey(){ return hostkey; }
1873 public String getHost(){return host;}
1874 public String getUserName(){return username;}
1875 public int getPort(){return port;}
1876 public void setHostKeyAlias(String hostKeyAlias){
1877 this.hostKeyAlias=hostKeyAlias;
1879 public String getHostKeyAlias(){
1880 return hostKeyAlias;
1883 public void setServerAliveInterval(int interval) throws JSchException {
1884 setTimeout(interval);
1885 this.serverAliveInterval=interval;
1887 public void setServerAliveCountMax(int count){
1888 this.serverAliveCountMax=count;
1891 public int getServerAliveInterval(){
1892 return this.serverAliveInterval;
1894 public int getServerAliveCountMax(){
1895 return this.serverAliveCountMax;
1898 public void setDaemonThread(boolean enable){
1899 this.daemon_thread=enable;
1902 private String[] checkCiphers(String ciphers){
1903 if(ciphers==null || ciphers.length()==0)
1906 if(JSch.getLogger().isEnabled(Logger.INFO)){
1907 JSch.getLogger().log(Logger.INFO,
1908 "CheckCiphers: "+ciphers);
1911 java.util.Vector result=new java.util.Vector();
1912 String[] _ciphers=Util.split(ciphers, ",");
1913 for(int i=0; i<_ciphers.length; i++){
1914 if(!checkCipher(getConfig(_ciphers[i]))){
1915 result.addElement(_ciphers[i]);
1918 if(result.size()==0)
1920 String[] foo=new String[result.size()];
1921 System.arraycopy(result.toArray(), 0, foo, 0, result.size());
1923 if(JSch.getLogger().isEnabled(Logger.INFO)){
1924 for(int i=0; i<foo.length; i++){
1925 JSch.getLogger().log(Logger.INFO,
1926 foo[i]+" is not available.");
1933 static boolean checkCipher(String cipher){
1935 Class c=Class.forName(cipher);
1936 Cipher _c=(Cipher)(c.newInstance());
1937 _c.init(Cipher.ENCRYPT_MODE,
1938 new byte[_c.getBlockSize()],
1939 new byte[_c.getIVSize()]);