KickJava   Java API By Example, From Geeks To Geeks.

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


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

29
30 package com.jcraft.jsch;
31
32 import java.io.*;
33 import java.net.*;
34
35 public class Session implements Runnable JavaDoc{
36   static private final String JavaDoc version="JSCH-0.1.33";
37
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;
67
68   private byte[] V_S; // server version
69
private byte[] V_C=("SSH-2.0-"+version).getBytes(); // client version
70

71   private byte[] I_C; // the payload of the client's SSH_MSG_KEXINIT
72
private byte[] I_S; // the payload of the server's SSH_MSG_KEXINIT
73
private byte[] K_S; // the host key
74

75   private byte[] session_id;
76
77   private byte[] IVc2s;
78   private byte[] IVs2c;
79   private byte[] Ec2s;
80   private byte[] Es2c;
81   private byte[] MACc2s;
82   private byte[] MACs2c;
83
84   private int seqi=0;
85   private int seqo=0;
86
87   String JavaDoc[] guess=null;
88   private Cipher s2ccipher;
89   private Cipher c2scipher;
90   private MAC s2cmac;
91   private MAC c2smac;
92   //private byte[] mac_buf;
93
private byte[] s2cmac_result1;
94   private byte[] s2cmac_result2;
95
96   private Compression deflater;
97   private Compression inflater;
98
99   private IO io;
100   private Socket socket;
101   private int timeout=0;
102
103   private boolean isConnected=false;
104
105   private boolean isAuthed=false;
106
107   private Thread JavaDoc connectThread=null;
108
109   boolean x11_forwarding=false;
110   boolean agent_forwarding=false;
111
112   InputStream in=null;
113   OutputStream out=null;
114
115   static Random random;
116
117   Buffer buf;
118   Packet packet;
119
120   SocketFactory socket_factory=null;
121
122   private java.util.Hashtable JavaDoc config=null;
123
124   private Proxy proxy=null;
125   private UserInfo userinfo;
126
127   private String JavaDoc hostKeyAlias=null;
128   private int serverAliveInterval=0;
129   private int serverAliveCountMax=1;
130
131   protected boolean daemon_thread=false;
132
133   String JavaDoc host="127.0.0.1";
134   int port=22;
135
136   String JavaDoc username=null;
137   byte[] password=null;
138
139   JSch jsch;
140
141   Session(JSch jsch) throws JSchException{
142     super();
143     this.jsch=jsch;
144     buf=new Buffer();
145     packet=new Packet(buf);
146   }
147
148   public void connect() throws JSchException{
149     connect(timeout);
150   }
151
152   public void connect(int connectTimeout) throws JSchException{
153     if(isConnected){
154       throw new JSchException("session is already connected");
155     }
156
157     io=new IO();
158     if(random==null){
159       try{
160     Class JavaDoc c=Class.forName(getConfig("random"));
161         random=(Random)(c.newInstance());
162       }
163       catch(Exception JavaDoc e){
164         throw new JSchException(e.toString(), e);
165       }
166     }
167     Packet.setRandom(random);
168
169     if(JSch.getLogger().isEnabled(Logger.INFO)){
170       JSch.getLogger().log(Logger.INFO,
171                            "Connecting to "+host+" port "+port);
172     }
173
174     try {
175       int i, j;
176
177       if(proxy==null){
178     proxy=jsch.getProxy(host);
179     if(proxy!=null){
180       synchronized(proxy){
181         proxy.close();
182       }
183     }
184       }
185
186       if(proxy==null){
187         InputStream in;
188         OutputStream out;
189     if(socket_factory==null){
190           socket=Util.createSocket(host, port, connectTimeout);
191       in=socket.getInputStream();
192       out=socket.getOutputStream();
193     }
194     else{
195           socket=socket_factory.createSocket(host, port);
196       in=socket_factory.getInputStream(socket);
197       out=socket_factory.getOutputStream(socket);
198     }
199     //if(timeout>0){ socket.setSoTimeout(timeout); }
200
socket.setTcpNoDelay(true);
201         io.setInputStream(in);
202         io.setOutputStream(out);
203       }
204       else{
205     synchronized(proxy){
206           proxy.connect(socket_factory, host, port, connectTimeout);
207       io.setInputStream(proxy.getInputStream());
208       io.setOutputStream(proxy.getOutputStream());
209           socket=proxy.getSocket();
210     }
211       }
212
213       if(connectTimeout>0 && socket!=null){
214         socket.setSoTimeout(connectTimeout);
215       }
216
217       isConnected=true;
218
219       if(JSch.getLogger().isEnabled(Logger.INFO)){
220         JSch.getLogger().log(Logger.INFO,
221                              "Connection established");
222       }
223
224       jsch.addSession(this);
225
226       while(true){
227         i=0;
228         j=0;
229         while(i<buf.buffer.length){
230           j=io.getByte();
231           if(j<0)break;
232           buf.buffer[i]=(byte)j; i++;
233           if(j==10)break;
234         }
235         if(j<0){
236           throw new JSchException("connection is closed by foreign host");
237         }
238
239         if(buf.buffer[i-1]==10){ // 0x0a
240
i--;
241           if(buf.buffer[i-1]==13){ // 0x0d
242
i--;
243           }
244         }
245
246         if(i>4 && (i!=buf.buffer.length) &&
247            (buf.buffer[0]!='S'||buf.buffer[1]!='S'||
248             buf.buffer[2]!='H'||buf.buffer[3]!='-')){
249           //System.err.println(new String(buf.buffer, 0, i);
250
continue;
251         }
252
253         if(i==buf.buffer.length ||
254            i<7 || // SSH-1.99 or SSH-2.0
255
(buf.buffer[4]=='1' && buf.buffer[6]!='9') // SSH-1.5
256
){
257           throw new JSchException("invalid server's version string");
258         }
259         break;
260       }
261
262       V_S=new byte[i]; System.arraycopy(buf.buffer, 0, V_S, 0, i);
263       //System.err.println("V_S: ("+i+") ["+new String(V_S)+"]");
264

265       if(JSch.getLogger().isEnabled(Logger.INFO)){
266         JSch.getLogger().log(Logger.INFO,
267                              "Remote version string: "+new String JavaDoc(V_S));
268         JSch.getLogger().log(Logger.INFO,
269                              "Local version string: "+new String JavaDoc(V_C));
270       }
271
272       //io.put(V_C, 0, V_C.length); io.put("\n".getBytes(), 0, 1);
273
{
274     // Some Cisco devices will miss to read '\n' if it is sent separately.
275
byte[] foo=new byte[V_C.length+1];
276     System.arraycopy(V_C, 0, foo, 0, V_C.length);
277     foo[foo.length-1]=(byte)'\n';
278     io.put(foo, 0, foo.length);
279       }
280
281       buf=read(buf);
282       //System.err.println("read: 20 ? "+buf.buffer[5]);
283
if(buf.buffer[5]!=SSH_MSG_KEXINIT){
284     throw new JSchException("invalid protocol: "+buf.buffer[5]);
285       }
286
287       if(JSch.getLogger().isEnabled(Logger.INFO)){
288         JSch.getLogger().log(Logger.INFO,
289                              "SSH_MSG_KEXINIT received");
290       }
291
292       KeyExchange kex=receive_kexinit(buf);
293
294       while(true){
295     buf=read(buf);
296     if(kex.getState()==buf.buffer[5]){
297           boolean result=kex.next(buf);
298       if(!result){
299         //System.err.println("verify: "+result);
300
in_kex=false;
301         throw new JSchException("verify: "+result);
302       }
303     }
304     else{
305           in_kex=false;
306       throw new JSchException("invalid protocol(kex): "+buf.buffer[5]);
307     }
308     if(kex.getState()==KeyExchange.STATE_END){
309       break;
310     }
311       }
312
313       try{ checkHost(host, port, kex); }
314       catch(JSchException ee){
315         in_kex=false;
316         throw ee;
317       }
318
319       send_newkeys();
320
321       // receive SSH_MSG_NEWKEYS(21)
322
buf=read(buf);
323       //System.err.println("read: 21 ? "+buf.buffer[5]);
324
if(buf.buffer[5]==SSH_MSG_NEWKEYS){
325
326         if(JSch.getLogger().isEnabled(Logger.INFO)){
327           JSch.getLogger().log(Logger.INFO,
328                                "SSH_MSG_NEWKEYS received");
329         }
330
331     receive_newkeys(buf, kex);
332       }
333       else{
334         in_kex=false;
335     throw new JSchException("invalid protocol(newkyes): "+buf.buffer[5]);
336       }
337
338       boolean auth=false;
339       boolean auth_cancel=false;
340
341       /*
342       UserAuthNone usn=new UserAuthNone();
343       auth=usn.start(this, userinfo);
344       */

345       UserAuth ua=null;
346       try{
347     Class JavaDoc c=Class.forName(getConfig("userauth.none"));
348         ua=(UserAuth)(c.newInstance());
349       }
350       catch(Exception JavaDoc e){
351         throw new JSchException(e.toString(), e);
352       }
353
354       auth=ua.start(this, userinfo);
355
356       String JavaDoc cmethods=getConfig("PreferredAuthentications");
357       String JavaDoc[] cmethoda=Util.split(cmethods, ",");
358
359       String JavaDoc smethods=null;
360       if(!auth){
361         smethods=((UserAuthNone)ua).getMethods();
362         if(smethods!=null){
363           smethods=smethods.toLowerCase();
364         }
365         else{
366           // methods: publickey,password,keyboard-interactive
367
//smethods="publickey,password,keyboard-interactive";
368
smethods=cmethods;
369         }
370       }
371
372       String JavaDoc[] smethoda=Util.split(smethods, ",");
373
374       int methodi=0;
375
376       loop:
377       while(true){
378
379 //System.err.println("methods: "+methods);
380

381     while(!auth &&
382           cmethoda!=null && methodi<cmethoda.length){
383
384           String JavaDoc method=cmethoda[methodi++];
385           boolean acceptable=false;
386           for(int k=0; k<smethoda.length; k++){
387             if(smethoda[k].equals(method)){
388               acceptable=true;
389               break;
390             }
391           }
392           if(!acceptable){
393             continue;
394           }
395
396           //System.err.println(" method: "+method);
397

398           if(JSch.getLogger().isEnabled(Logger.INFO)){
399             String JavaDoc str="Authentications that can continue: ";
400             for(int k=methodi-1; k<cmethoda.length; k++){
401               str+=cmethoda[k];
402               if(k+1<cmethoda.length)
403                 str+=",";
404             }
405             JSch.getLogger().log(Logger.INFO,
406                                  str);
407             JSch.getLogger().log(Logger.INFO,
408                                  "Next authentication method: "+method);
409           }
410
411       ua=null;
412           try{
413             Class JavaDoc c=null;
414             if(getConfig("userauth."+method)!=null){
415               c=Class.forName(getConfig("userauth."+method));
416               ua=(UserAuth)(c.newInstance());
417             }
418           }
419           catch(Exception JavaDoc e){
420             if(JSch.getLogger().isEnabled(Logger.WARN)){
421               JSch.getLogger().log(Logger.WARN,
422                                    "failed to load "+method+" method");
423             }
424           }
425
426       if(ua!=null){
427             auth_cancel=false;
428         try{
429           auth=ua.start(this, userinfo);
430               if(auth &&
431                  JSch.getLogger().isEnabled(Logger.INFO)){
432                 JSch.getLogger().log(Logger.INFO,
433                                      "Authentication succeeded ("+method+").");
434               }
435         }
436         catch(JSchAuthCancelException ee){
437           auth_cancel=true;
438         }
439         catch(JSchPartialAuthException ee){
440           smethods=ee.getMethods();
441               smethoda=Util.split(smethods, ",");
442               methodi=0;
443           //System.err.println("PartialAuth: "+methods);
444
auth_cancel=false;
445           continue loop;
446         }
447         catch(RuntimeException JavaDoc ee){
448           throw ee;
449         }
450         catch(Exception JavaDoc ee){
451           //System.err.println("ee: "+ee); // SSH_MSG_DISCONNECT: 2 Too many authentication failures
452
break loop;
453         }
454       }
455     }
456         break;
457       }
458
459       if(auth){
460
461         if(connectTimeout>0 || timeout>0){
462           socket.setSoTimeout(timeout);
463         }
464
465         isAuthed=true;
466     connectThread=new Thread JavaDoc(this);
467     connectThread.setName("Connect thread "+host+" session");
468         if(daemon_thread){
469           connectThread.setDaemon(daemon_thread);
470         }
471     connectThread.start();
472     return;
473       }
474
475       if(auth_cancel)
476     throw new JSchException("Auth cancel");
477       throw new JSchException("Auth fail");
478     }
479     catch(Exception JavaDoc e) {
480       in_kex=false;
481       if(isConnected){
482     try{
483       packet.reset();
484       buf.putByte((byte)SSH_MSG_DISCONNECT);
485       buf.putInt(3);
486       buf.putString(e.toString().getBytes());
487       buf.putString("en".getBytes());
488       write(packet);
489       disconnect();
490     }
491     catch(Exception JavaDoc ee){
492     }
493       }
494       isConnected=false;
495       //e.printStackTrace();
496
if(e instanceof RuntimeException JavaDoc) throw (RuntimeException JavaDoc)e;
497       if(e instanceof JSchException) throw (JSchException)e;
498       throw new JSchException("Session.connect: "+e);
499     }
500     finally{
501       Util.bzero(this.password);
502       this.password=null;
503     }
504   }
505
506   private KeyExchange receive_kexinit(Buffer buf) throws Exception JavaDoc {
507     int j=buf.getInt();
508     if(j!=buf.getLength()){ // packet was compressed and
509
buf.getByte(); // j is the size of deflated packet.
510
I_S=new byte[buf.index-5];
511     }
512     else{
513       I_S=new byte[j-1-buf.getByte()];
514     }
515     System.arraycopy(buf.buffer, buf.s, I_S, 0, I_S.length);
516 /*
517 try{
518 byte[] tmp=new byte[I_S.length];
519 System.arraycopy(I_S, 0, tmp, 0, I_S.length);
520 Buffer tmpb=new Buffer(tmp);
521 System.err.println("I_S: len="+I_S.length);
522 tmpb.setOffSet(17);
523 System.err.println("kex: "+new String(tmpb.getString()));
524 System.err.println("server_host_key: "+new String(tmpb.getString()));
525 System.err.println("cipher.c2s: "+new String(tmpb.getString()));
526 System.err.println("cipher.s2c: "+new String(tmpb.getString()));
527 System.err.println("mac.c2s: "+new String(tmpb.getString()));
528 System.err.println("mac.s2c: "+new String(tmpb.getString()));
529 System.err.println("compression.c2s: "+new String(tmpb.getString()));
530 System.err.println("compression.s2c: "+new String(tmpb.getString()));
531 System.err.println("lang.c2s: "+new String(tmpb.getString()));
532 System.err.println("lang.s2c: "+new String(tmpb.getString()));
533 System.err.println("?: "+(tmpb.getByte()&0xff));
534 System.err.println("??: "+tmpb.getInt());
535 }
536 catch(Exception e){
537 System.err.println(e);
538 }
539 */

540
541     send_kexinit();
542     guess=KeyExchange.guess(I_S, I_C);
543     if(guess==null){
544       throw new JSchException("Algorithm negotiation fail");
545     }
546
547     if(!isAuthed &&
548        (guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS].equals("none") ||
549         (guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC].equals("none")))){
550       throw new JSchException("NONE Cipher should not be chosen before authentification is successed.");
551     }
552
553     KeyExchange kex=null;
554     try{
555       Class JavaDoc c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_KEX_ALGS]));
556       kex=(KeyExchange)(c.newInstance());
557     }
558     catch(Exception JavaDoc e){
559       throw new JSchException(e.toString(), e);
560     }
561     //kex.guess=guess;
562
kex.init(this, V_S, V_C, I_S, I_C);
563     return kex;
564   }
565
566   private boolean in_kex=false;
567   public void rekey() throws Exception JavaDoc {
568     send_kexinit();
569   }
570   private void send_kexinit() throws Exception JavaDoc {
571     if(in_kex) return;
572     in_kex=true;
573
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
packet.reset();
587     buf.putByte((byte) SSH_MSG_KEXINIT);
588     synchronized(random){
589       random.fill(buf.buffer, buf.index, 16); buf.skip(16);
590     }
591     buf.putString(getConfig("kex").getBytes());
592     buf.putString(getConfig("server_host_key").getBytes());
593     buf.putString(getConfig("cipher.c2s").getBytes());
594     buf.putString(getConfig("cipher.s2c").getBytes());
595     buf.putString(getConfig("mac.c2s").getBytes());
596     buf.putString(getConfig("mac.s2c").getBytes());
597     buf.putString(getConfig("compression.c2s").getBytes());
598     buf.putString(getConfig("compression.s2c").getBytes());
599     buf.putString(getConfig("lang.c2s").getBytes());
600     buf.putString(getConfig("lang.s2c").getBytes());
601     buf.putByte((byte)0);
602     buf.putInt(0);
603
604     buf.setOffSet(5);
605     I_C=new byte[buf.getLength()];
606     buf.getByte(I_C);
607
608     write(packet);
609
610     if(JSch.getLogger().isEnabled(Logger.INFO)){
611       JSch.getLogger().log(Logger.INFO,
612                            "SSH_MSG_KEXINIT sent");
613     }
614   }
615
616   private void send_newkeys() throws Exception JavaDoc {
617     // send SSH_MSG_NEWKEYS(21)
618
packet.reset();
619     buf.putByte((byte)SSH_MSG_NEWKEYS);
620     write(packet);
621
622     if(JSch.getLogger().isEnabled(Logger.INFO)){
623       JSch.getLogger().log(Logger.INFO,
624                            "SSH_MSG_NEWKEYS sent");
625     }
626   }
627
628   private void checkHost(String JavaDoc chost, int port, KeyExchange kex) throws JSchException {
629     String JavaDoc shkc=getConfig("StrictHostKeyChecking");
630
631     if(hostKeyAlias!=null){
632       chost=hostKeyAlias;
633     }
634
635     //System.err.println("shkc: "+shkc);
636

637     byte[] K_S=kex.getHostKey();
638     String JavaDoc key_type=kex.getKeyType();
639     String JavaDoc key_fprint=kex.getFingerPrint();
640
641     if(hostKeyAlias==null && port!=22){
642       chost=("["+chost+"]:"+port);
643     }
644
645 // hostkey=new HostKey(chost, K_S);
646

647     HostKeyRepository hkr=jsch.getHostKeyRepository();
648     int i=0;
649     synchronized(hkr){
650       i=hkr.check(chost, K_S);
651     }
652
653     boolean insert=false;
654
655     if((shkc.equals("ask") || shkc.equals("yes")) &&
656        i==HostKeyRepository.CHANGED){
657       String JavaDoc file=null;
658       synchronized(hkr){
659     file=hkr.getKnownHostsRepositoryID();
660       }
661       if(file==null){file="known_hosts";}
662
663       boolean b=false;
664
665       if(userinfo!=null){
666         String JavaDoc message=
667 "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n"+
668 "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n"+
669 "Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n"+
670 "It is also possible that the "+key_type+" host key has just been changed.\n"+
671 "The fingerprint for the "+key_type+" key sent by the remote host is\n"+
672 key_fprint+".\n"+
673 "Please contact your system administrator.\n"+
674 "Add correct host key in "+file+" to get rid of this message.";
675
676         if(shkc.equals("ask")){
677           b=userinfo.promptYesNo(message+
678                                  "\nDo you want to delete the old key and insert the new key?");
679         }
680         else{ // shkc.equals("yes")
681
userinfo.showMessage(message);
682         }
683       }
684
685       if(!b){
686         throw new JSchException("HostKey has been changed: "+chost);
687       }
688
689       synchronized(hkr){
690         hkr.remove(chost,
691                    (key_type.equals("DSA") ? "ssh-dss" : "ssh-rsa"),
692                    null);
693         insert=true;
694       }
695     }
696
697     if((shkc.equals("ask") || shkc.equals("yes")) &&
698        (i!=HostKeyRepository.OK) && !insert){
699       if(shkc.equals("yes")){
700     throw new JSchException("reject HostKey: "+host);
701       }
702       //System.err.println("finger-print: "+key_fprint);
703
if(userinfo!=null){
704     boolean foo=userinfo.promptYesNo(
705 "The authenticity of host '"+host+"' can't be established.\n"+
706 key_type+" key fingerprint is "+key_fprint+".\n"+
707 "Are you sure you want to continue connecting?"
708                      );
709     if(!foo){
710       throw new JSchException("reject HostKey: "+host);
711     }
712     insert=true;
713       }
714       else{
715     if(i==HostKeyRepository.NOT_INCLUDED)
716       throw new JSchException("UnknownHostKey: "+host+". "+key_type+" key fingerprint is "+key_fprint);
717     else
718           throw new JSchException("HostKey has been changed: "+host);
719       }
720     }
721
722     if(shkc.equals("no") &&
723        HostKeyRepository.NOT_INCLUDED==i){
724       insert=true;
725     }
726
727     if(i==HostKeyRepository.OK &&
728        JSch.getLogger().isEnabled(Logger.INFO)){
729       JSch.getLogger().log(Logger.INFO,
730                            "Host '"+host+"' is known and mathces the "+key_type+" host key");
731     }
732
733     if(insert &&
734        JSch.getLogger().isEnabled(Logger.WARN)){
735       JSch.getLogger().log(Logger.WARN,
736                            "Permanently added '"+host+"' ("+key_type+") to the list of known hosts.");
737     }
738
739     String JavaDoc hkh=getConfig("HashKnownHosts");
740     if(hkh.equals("yes") && (hkr instanceof KnownHosts)){
741       hostkey=((KnownHosts)hkr).createHashedHostKey(chost, K_S);
742     }
743     else{
744       hostkey=new HostKey(chost, K_S);
745     }
746
747     if(insert){
748       synchronized(hkr){
749     hkr.add(hostkey, userinfo);
750       }
751
752     }
753
754   }
755
756 //public void start(){ (new Thread(this)).start(); }
757

758   public Channel openChannel(String JavaDoc type) throws JSchException{
759     if(!isConnected){
760       throw new JSchException("session is down");
761     }
762     try{
763       Channel channel=Channel.getChannel(type);
764       addChannel(channel);
765       channel.init();
766       return channel;
767     }
768     catch(Exception JavaDoc e){
769       //e.printStackTrace();
770
}
771     return null;
772   }
773
774   // encode will bin invoked in write with synchronization.
775
public void encode(Packet packet) throws Exception JavaDoc{
776 //System.err.println("encode: "+packet.buffer.buffer[5]);
777
//System.err.println(" "+packet.buffer.index);
778
//if(packet.buffer.buffer[5]==96){
779
//Thread.dumpStack();
780
//}
781
if(deflater!=null){
782       packet.buffer.index=deflater.compress(packet.buffer.buffer,
783                         5, packet.buffer.index);
784     }
785     if(c2scipher!=null){
786       //packet.padding(c2scipher.getIVSize());
787
packet.padding(c2scipher_size);
788       int pad=packet.buffer.buffer[4];
789       synchronized(random){
790     random.fill(packet.buffer.buffer, packet.buffer.index-pad, pad);
791       }
792     }
793     else{
794       packet.padding(8);
795     }
796
797     if(c2smac!=null){
798       c2smac.update(seqo);
799       c2smac.update(packet.buffer.buffer, 0, packet.buffer.index);
800       c2smac.doFinal(packet.buffer.buffer, packet.buffer.index);
801     }
802     if(c2scipher!=null){
803       byte[] buf=packet.buffer.buffer;
804       c2scipher.update(buf, 0, packet.buffer.index, buf, 0);
805     }
806     if(c2smac!=null){
807       packet.buffer.skip(c2smac.getBlockSize());
808     }
809   }
810
811   int[] uncompress_len=new int[1];
812
813   private int s2ccipher_size=8;
814   private int c2scipher_size=8;
815   public Buffer read(Buffer buf) throws Exception JavaDoc{
816     int j=0;
817     while(true){
818       buf.reset();
819       io.getByte(buf.buffer, buf.index, s2ccipher_size);
820       buf.index+=s2ccipher_size;
821       if(s2ccipher!=null){
822         s2ccipher.update(buf.buffer, 0, s2ccipher_size, buf.buffer, 0);
823       }
824       j=((buf.buffer[0]<<24)&0xff000000)|
825         ((buf.buffer[1]<<16)&0x00ff0000)|
826         ((buf.buffer[2]<< 8)&0x0000ff00)|
827         ((buf.buffer[3] )&0x000000ff);
828       // RFC 4253 6.1. Maximum Packet Length
829
if(j<5 || j>(32768-4)){
830         throw new IOException("invalid data");
831       }
832       j=j+4-s2ccipher_size;
833       //if(j<0){
834
// throw new IOException("invalid data");
835
//}
836
if((buf.index+j)>buf.buffer.length){
837         byte[] foo=new byte[buf.index+j];
838         System.arraycopy(buf.buffer, 0, foo, 0, buf.index);
839         buf.buffer=foo;
840       }
841       if(j>0){
842     io.getByte(buf.buffer, buf.index, j); buf.index+=(j);
843     if(s2ccipher!=null){
844       s2ccipher.update(buf.buffer, s2ccipher_size, j, buf.buffer, s2ccipher_size);
845     }
846       }
847
848       if(s2cmac!=null){
849     s2cmac.update(seqi);
850     s2cmac.update(buf.buffer, 0, buf.index);
851
852         s2cmac.doFinal(s2cmac_result1, 0);
853     io.getByte(s2cmac_result2, 0, s2cmac_result2.length);
854         if(!java.util.Arrays.equals(s2cmac_result1, s2cmac_result2)){
855           throw new IOException("MAC Error");
856     }
857       }
858
859       seqi++;
860
861       if(inflater!=null){
862         //inflater.uncompress(buf);
863
int pad=buf.buffer[4];
864     uncompress_len[0]=buf.index-5-pad;
865     byte[] foo=inflater.uncompress(buf.buffer, 5, uncompress_len);
866     if(foo!=null){
867       buf.buffer=foo;
868       buf.index=5+uncompress_len[0];
869     }
870     else{
871       System.err.println("fail in inflater");
872       break;
873     }
874       }
875
876       int type=buf.buffer[5]&0xff;
877       //System.err.println("read: "+type);
878
if(type==SSH_MSG_DISCONNECT){
879         buf.rewind();
880         buf.getInt();buf.getShort();
881     int reason_code=buf.getInt();
882     byte[] description=buf.getString();
883     byte[] language_tag=buf.getString();
884     throw new JSchException("SSH_MSG_DISCONNECT:"+
885                 " "+reason_code+
886                 " "+new String JavaDoc(description)+
887                 " "+new String JavaDoc(language_tag));
888     //break;
889
}
890       else if(type==SSH_MSG_IGNORE){
891       }
892       else if(type==SSH_MSG_UNIMPLEMENTED){
893         buf.rewind();
894         buf.getInt();buf.getShort();
895     int reason_id=buf.getInt();
896         if(JSch.getLogger().isEnabled(Logger.INFO)){
897           JSch.getLogger().log(Logger.INFO,
898                                "Received SSH_MSG_UNIMPLEMENTED for "+reason_id);
899         }
900       }
901       else if(type==SSH_MSG_DEBUG){
902         buf.rewind();
903         buf.getInt();buf.getShort();
904 /*
905     byte always_display=(byte)buf.getByte();
906     byte[] message=buf.getString();
907     byte[] language_tag=buf.getString();
908     System.err.println("SSH_MSG_DEBUG:"+
909                " "+new String(message)+
910                " "+new String(language_tag));
911 */

912       }
913       else if(type==SSH_MSG_CHANNEL_WINDOW_ADJUST){
914           buf.rewind();
915           buf.getInt();buf.getShort();
916       Channel c=Channel.getChannel(buf.getInt(), this);
917       if(c==null){
918       }
919       else{
920         c.addRemoteWindowSize(buf.getInt());
921       }
922       }
923       else if(type==52/*SSH_MSG_USERAUTH_SUCCESS*/){
924         isAuthed=true;
925         if(inflater==null && deflater==null){
926           String JavaDoc method;
927           method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];
928           initDeflater(method);
929
930           method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];
931           initInflater(method);
932         }
933         break;
934       }
935       else{
936         break;
937       }
938     }
939     buf.rewind();
940     return buf;
941   }
942
943   byte[] getSessionId(){
944     return session_id;
945   }
946
947   private void receive_newkeys(Buffer buf, KeyExchange kex) throws Exception JavaDoc {
948     updateKeys(kex);
949     in_kex=false;
950   }
951   private void updateKeys(KeyExchange kex) throws Exception JavaDoc{
952     byte[] K=kex.getK();
953     byte[] H=kex.getH();
954     HASH hash=kex.getHash();
955
956 // String[] guess=kex.guess;
957

958     if(session_id==null){
959       session_id=new byte[H.length];
960       System.arraycopy(H, 0, session_id, 0, H.length);
961     }
962
963     /*
964       Initial IV client to server: HASH (K || H || "A" || session_id)
965       Initial IV server to client: HASH (K || H || "B" || session_id)
966       Encryption key client to server: HASH (K || H || "C" || session_id)
967       Encryption key server to client: HASH (K || H || "D" || session_id)
968       Integrity key client to server: HASH (K || H || "E" || session_id)
969       Integrity key server to client: HASH (K || H || "F" || session_id)
970     */

971
972     buf.reset();
973     buf.putMPInt(K);
974     buf.putByte(H);
975     buf.putByte((byte)0x41);
976     buf.putByte(session_id);
977     hash.update(buf.buffer, 0, buf.index);
978     IVc2s=hash.digest();
979
980     int j=buf.index-session_id.length-1;
981
982     buf.buffer[j]++;
983     hash.update(buf.buffer, 0, buf.index);
984     IVs2c=hash.digest();
985
986     buf.buffer[j]++;
987     hash.update(buf.buffer, 0, buf.index);
988     Ec2s=hash.digest();
989
990     buf.buffer[j]++;
991     hash.update(buf.buffer, 0, buf.index);
992     Es2c=hash.digest();
993
994     buf.buffer[j]++;
995     hash.update(buf.buffer, 0, buf.index);
996     MACc2s=hash.digest();
997
998     buf.buffer[j]++;
999     hash.update(buf.buffer, 0, buf.index);
1000    MACs2c=hash.digest();
1001
1002    try{
1003      Class JavaDoc c;
1004      String JavaDoc method;
1005  
1006      method=guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC];
1007      c=Class.forName(getConfig(method));
1008      s2ccipher=(Cipher)(c.newInstance());
1009      while(s2ccipher.getBlockSize()>Es2c.length){
1010        buf.reset();
1011        buf.putMPInt(K);
1012        buf.putByte(H);
1013        buf.putByte(Es2c);
1014        hash.update(buf.buffer, 0, buf.index);
1015        byte[] foo=hash.digest();
1016        byte[] bar=new byte[Es2c.length+foo.length];
1017    System.arraycopy(Es2c, 0, bar, 0, Es2c.length);
1018    System.arraycopy(foo, 0, bar, Es2c.length, foo.length);
1019    Es2c=bar;
1020      }
1021      s2ccipher.init(Cipher.DECRYPT_MODE, Es2c, IVs2c);
1022      s2ccipher_size=s2ccipher.getIVSize();
1023
1024      method=guess[KeyExchange.PROPOSAL_MAC_ALGS_STOC];
1025      c=Class.forName(getConfig(method));
1026      s2cmac=(MAC)(c.newInstance());
1027      s2cmac.init(MACs2c);
1028      //mac_buf=new byte[s2cmac.getBlockSize()];
1029
s2cmac_result1=new byte[s2cmac.getBlockSize()];
1030      s2cmac_result2=new byte[s2cmac.getBlockSize()];
1031
1032      method=guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS];
1033      c=Class.forName(getConfig(method));
1034      c2scipher=(Cipher)(c.newInstance());
1035      while(c2scipher.getBlockSize()>Ec2s.length){
1036        buf.reset();
1037        buf.putMPInt(K);
1038        buf.putByte(H);
1039        buf.putByte(Ec2s);
1040        hash.update(buf.buffer, 0, buf.index);
1041        byte[] foo=hash.digest();
1042        byte[] bar=new byte[Ec2s.length+foo.length];
1043    System.arraycopy(Ec2s, 0, bar, 0, Ec2s.length);
1044    System.arraycopy(foo, 0, bar, Ec2s.length, foo.length);
1045    Ec2s=bar;
1046      }
1047      c2scipher.init(Cipher.ENCRYPT_MODE, Ec2s, IVc2s);
1048      c2scipher_size=s2ccipher.getIVSize();
1049
1050      method=guess[KeyExchange.PROPOSAL_MAC_ALGS_CTOS];
1051      c=Class.forName(getConfig(method));
1052      c2smac=(MAC)(c.newInstance());
1053      c2smac.init(MACc2s);
1054
1055      method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];
1056      initDeflater(method);
1057
1058      method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];
1059      initInflater(method);
1060    }
1061    catch(Exception JavaDoc e){
1062      if(e instanceof JSchException)
1063        throw e;
1064      throw new JSchException(e.toString(), e);
1065      //System.err.println("updatekeys: "+e);
1066
}
1067  }
1068
1069  /*public*/ /*synchronized*/ void write(Packet packet, Channel c, int length) throws Exception JavaDoc{
1070    while(true){
1071      if(in_kex){
1072        try{Thread.sleep(10);}
1073        catch(java.lang.InterruptedException JavaDoc e){};
1074        continue;
1075      }
1076      synchronized(c){
1077        if(c.rwsize>=length){
1078          c.rwsize-=length;
1079          break;
1080        }
1081      }
1082      if(c.close || !c.isConnected()){
1083    throw new IOException("channel is broken");
1084      }
1085
1086      boolean sendit=false;
1087      int s=0;
1088      byte command=0;
1089      int recipient=-1;
1090      synchronized(c){
1091    if(c.rwsize>0){
1092      int len=c.rwsize;
1093          if(len>length){
1094            len=length;
1095          }
1096          if(len!=length){
1097            s=packet.shift(len, (c2smac!=null ? c2smac.getBlockSize() : 0));
1098          }
1099      command=packet.buffer.buffer[5];
1100      recipient=c.getRecipient();
1101      length-=len;
1102      c.rwsize-=len;
1103      sendit=true;
1104    }
1105      }
1106      if(sendit){
1107    _write(packet);
1108        if(length==0){
1109          return;
1110        }
1111    packet.unshift(command, recipient, s, length);
1112
1113        synchronized(c){
1114          if(c.rwsize>=length){
1115            c.rwsize-=length;
1116            break;
1117          }
1118        }
1119
1120      }
1121
1122
1123// try{Thread.sleep(10);}
1124
try{ Thread.sleep(100); }
1125      catch(java.lang.InterruptedException JavaDoc e){};
1126    }
1127    _write(packet);
1128  }
1129
1130  public void write(Packet packet) throws Exception JavaDoc{
1131    // System.err.println("in_kex="+in_kex+" "+(packet.buffer.buffer[5]));
1132
while(in_kex){
1133      byte command=packet.buffer.buffer[5];
1134      //System.err.println("command: "+command);
1135
if(command==SSH_MSG_KEXINIT ||
1136         command==SSH_MSG_NEWKEYS ||
1137         command==SSH_MSG_KEXDH_INIT ||
1138         command==SSH_MSG_KEXDH_REPLY ||
1139         command==SSH_MSG_KEX_DH_GEX_GROUP ||
1140         command==SSH_MSG_KEX_DH_GEX_INIT ||
1141         command==SSH_MSG_KEX_DH_GEX_REPLY ||
1142         command==SSH_MSG_KEX_DH_GEX_REQUEST ||
1143         command==SSH_MSG_DISCONNECT){
1144        break;
1145      }
1146      try{Thread.sleep(10);}
1147      catch(java.lang.InterruptedException JavaDoc e){};
1148    }
1149    _write(packet);
1150  }
1151  private synchronized void _write(Packet packet) throws Exception JavaDoc{
1152     encode(packet);
1153     if(io!=null){
1154       io.put(packet);
1155       seqo++;
1156     }
1157  }
1158
1159  Runnable JavaDoc thread;
1160  public void run(){
1161    thread=this;
1162
1163    byte[] foo;
1164    Buffer buf=new Buffer();
1165    Packet packet=new Packet(buf);
1166    int i=0;
1167    Channel channel;
1168    int[] start=new int[1];
1169    int[] length=new int[1];
1170    KeyExchange kex=null;
1171
1172    int stimeout=0;
1173    try{
1174      while(isConnected &&
1175        thread!=null){
1176        try{
1177          buf=read(buf);
1178          stimeout=0;
1179        }
1180        catch(InterruptedIOException/*SocketTimeoutException*/ ee){
1181          if(!in_kex && stimeout<serverAliveCountMax){
1182            sendKeepAliveMsg();
1183            stimeout++;
1184            continue;
1185          }
1186          throw ee;
1187        }
1188
1189    int msgType=buf.buffer[5]&0xff;
1190// if(msgType!=94)
1191
//System.err.println("read: 94 ? "+msgType);
1192

1193    if(kex!=null && kex.getState()==msgType){
1194      boolean result=kex.next(buf);
1195      if(!result){
1196        throw new JSchException("verify: "+result);
1197      }
1198      continue;
1199    }
1200
1201        switch(msgType){
1202    case SSH_MSG_KEXINIT:
1203//System.err.println("KEXINIT");
1204
kex=receive_kexinit(buf);
1205      break;
1206
1207    case SSH_MSG_NEWKEYS:
1208//System.err.println("NEWKEYS");
1209
send_newkeys();
1210      receive_newkeys(buf, kex);
1211      kex=null;
1212      break;
1213
1214    case SSH_MSG_CHANNEL_DATA:
1215          buf.getInt();
1216          buf.getByte();
1217          buf.getByte();
1218          i=buf.getInt();
1219      channel=Channel.getChannel(i, this);
1220      foo=buf.getString(start, length);
1221      if(channel==null){
1222        break;
1223      }
1224try{
1225      channel.write(foo, start[0], length[0]);
1226}
1227catch(Exception JavaDoc e){
1228//System.err.println(e);
1229
try{channel.disconnect();}catch(Exception JavaDoc ee){}
1230break;
1231}
1232      int len=length[0];
1233      channel.setLocalWindowSize(channel.lwsize-len);
1234      if(channel.lwsize<channel.lwsize_max/2){
1235            packet.reset();
1236        buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
1237        buf.putInt(channel.getRecipient());
1238        buf.putInt(channel.lwsize_max-channel.lwsize);
1239        write(packet);
1240        channel.setLocalWindowSize(channel.lwsize_max);
1241      }
1242      break;
1243
1244        case SSH_MSG_CHANNEL_EXTENDED_DATA:
1245          buf.getInt();
1246      buf.getShort();
1247      i=buf.getInt();
1248      channel=Channel.getChannel(i, this);
1249      buf.getInt(); // data_type_code == 1
1250
foo=buf.getString(start, length);
1251      //System.err.println("stderr: "+new String(foo,start[0],length[0]));
1252
if(channel==null){
1253        break;
1254      }
1255      //channel.write(foo, start[0], length[0]);
1256
channel.write_ext(foo, start[0], length[0]);
1257
1258      len=length[0];
1259      channel.setLocalWindowSize(channel.lwsize-len);
1260      if(channel.lwsize<channel.lwsize_max/2){
1261            packet.reset();
1262        buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
1263        buf.putInt(channel.getRecipient());
1264        buf.putInt(channel.lwsize_max-channel.lwsize);
1265        write(packet);
1266        channel.setLocalWindowSize(channel.lwsize_max);
1267      }
1268      break;
1269
1270    case SSH_MSG_CHANNEL_WINDOW_ADJUST:
1271          buf.getInt();
1272      buf.getShort();
1273      i=buf.getInt();
1274      channel=Channel.getChannel(i, this);
1275      if(channel==null){
1276        break;
1277      }
1278      channel.addRemoteWindowSize(buf.getInt());
1279      break;
1280
1281    case SSH_MSG_CHANNEL_EOF:
1282          buf.getInt();
1283          buf.getShort();
1284          i=buf.getInt();
1285      channel=Channel.getChannel(i, this);
1286      if(channel!=null){
1287        //channel.eof_remote=true;
1288
//channel.eof();
1289
channel.eof_remote();
1290      }
1291      /*
1292      packet.reset();
1293      buf.putByte((byte)SSH_MSG_CHANNEL_EOF);
1294      buf.putInt(channel.getRecipient());
1295      write(packet);
1296      */

1297      break;
1298    case SSH_MSG_CHANNEL_CLOSE:
1299          buf.getInt();
1300      buf.getShort();
1301      i=buf.getInt();
1302      channel=Channel.getChannel(i, this);
1303      if(channel!=null){
1304// channel.close();
1305
channel.disconnect();
1306      }
1307      /*
1308          if(Channel.pool.size()==0){
1309        thread=null;
1310      }
1311      */

1312      break;
1313    case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
1314          buf.getInt();
1315      buf.getShort();
1316      i=buf.getInt();
1317      channel=Channel.getChannel(i, this);
1318      if(channel==null){
1319        //break;
1320
}
1321      channel.setRecipient(buf.getInt());
1322      channel.setRemoteWindowSize(buf.getInt());
1323      channel.setRemotePacketSize(buf.getInt());
1324      break;
1325    case SSH_MSG_CHANNEL_OPEN_FAILURE:
1326          buf.getInt();
1327      buf.getShort();
1328      i=buf.getInt();
1329      channel=Channel.getChannel(i, this);
1330      if(channel==null){
1331        //break;
1332
}
1333      int reason_code=buf.getInt();
1334      //foo=buf.getString(); // additional textual information
1335
//foo=buf.getString(); // language tag
1336
channel.exitstatus=reason_code;
1337      channel.close=true;
1338      channel.eof_remote=true;
1339      channel.setRecipient(0);
1340      break;
1341    case SSH_MSG_CHANNEL_REQUEST:
1342          buf.getInt();
1343      buf.getShort();
1344      i=buf.getInt();
1345      foo=buf.getString();
1346          boolean reply=(buf.getByte()!=0);
1347      channel=Channel.getChannel(i, this);
1348      if(channel!=null){
1349        byte reply_type=(byte)SSH_MSG_CHANNEL_FAILURE;
1350        if((new String JavaDoc(foo)).equals("exit-status")){
1351          i=buf.getInt(); // exit-status
1352
channel.setExitStatus(i);
1353// System.err.println("exit-stauts: "+i);
1354
// channel.close();
1355
reply_type=(byte)SSH_MSG_CHANNEL_SUCCESS;
1356        }
1357        if(reply){
1358          packet.reset();
1359          buf.putByte(reply_type);
1360          buf.putInt(channel.getRecipient());
1361          write(packet);
1362        }
1363      }
1364      else{
1365      }
1366      break;
1367    case SSH_MSG_CHANNEL_OPEN:
1368          buf.getInt();
1369      buf.getShort();
1370      foo=buf.getString();
1371      String JavaDoc ctyp=new String JavaDoc(foo);
1372          if(!"forwarded-tcpip".equals(ctyp) &&
1373         !("x11".equals(ctyp) && x11_forwarding) &&
1374         !("auth-agent@openssh.com".equals(ctyp) && agent_forwarding)){
1375            //System.err.println("Session.run: CHANNEL OPEN "+ctyp);
1376
//throw new IOException("Session.run: CHANNEL OPEN "+ctyp);
1377
packet.reset();
1378        buf.putByte((byte)SSH_MSG_CHANNEL_OPEN_FAILURE);
1379        buf.putInt(buf.getInt());
1380        buf.putInt(Channel.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED);
1381        buf.putString("".getBytes());
1382        buf.putString("".getBytes());
1383        write(packet);
1384      }
1385      else{
1386        channel=Channel.getChannel(ctyp);
1387        addChannel(channel);
1388        channel.getData(buf);
1389        channel.init();
1390
1391        Thread JavaDoc tmp=new Thread JavaDoc(channel);
1392        tmp.setName("Channel "+ctyp+" "+host);
1393            if(daemon_thread){
1394              tmp.setDaemon(daemon_thread);
1395            }
1396        tmp.start();
1397        break;
1398      }
1399    case SSH_MSG_CHANNEL_SUCCESS:
1400          buf.getInt();
1401      buf.getShort();
1402      i=buf.getInt();
1403      channel=Channel.getChannel(i, this);
1404      if(channel==null){
1405        break;
1406      }
1407      channel.reply=1;
1408      break;
1409    case SSH_MSG_CHANNEL_FAILURE:
1410      buf.getInt();
1411      buf.getShort();
1412      i=buf.getInt();
1413      channel=Channel.getChannel(i, this);
1414      if(channel==null){
1415        break;
1416      }
1417      channel.reply=0;
1418      break;
1419    case SSH_MSG_GLOBAL_REQUEST:
1420      buf.getInt();
1421      buf.getShort();
1422      foo=buf.getString(); // request name
1423
reply=(buf.getByte()!=0);
1424      if(reply){
1425        packet.reset();
1426        buf.putByte((byte)SSH_MSG_REQUEST_FAILURE);
1427        write(packet);
1428      }
1429      break;
1430    case SSH_MSG_REQUEST_FAILURE:
1431    case SSH_MSG_REQUEST_SUCCESS:
1432          Thread JavaDoc t=grr.getThread();
1433          if(t!=null){
1434            grr.setReply(msgType==SSH_MSG_REQUEST_SUCCESS? 1 : 0);
1435            t.interrupt();
1436          }
1437      break;
1438    default:
1439          //System.err.println("Session.run: unsupported type "+msgType);
1440
throw new IOException("Unknown SSH message type "+msgType);
1441    }
1442      }
1443    }
1444    catch(Exception JavaDoc e){
1445      //System.err.println("# Session.run");
1446
//e.printStackTrace();
1447
}
1448    try{
1449      disconnect();
1450    }
1451    catch(NullPointerException JavaDoc e){
1452      //System.err.println("@1");
1453
//e.printStackTrace();
1454
}
1455    catch(Exception JavaDoc e){
1456      //System.err.println("@2");
1457
//e.printStackTrace();
1458
}
1459    isConnected=false;
1460  }
1461
1462  public void disconnect(){
1463    if(!isConnected) return;
1464    //System.err.println(this+": disconnect");
1465
//Thread.dumpStack();
1466
/*
1467    for(int i=0; i<Channel.pool.size(); i++){
1468      try{
1469        Channel c=((Channel)(Channel.pool.elementAt(i)));
1470    if(c.session==this) c.eof();
1471      }
1472      catch(Exception e){
1473      }
1474    }
1475    */

1476
1477    Channel.disconnect(this);
1478
1479    isConnected=false;
1480
1481    PortWatcher.delPort(this);
1482    ChannelForwardedTCPIP.delPort(this);
1483
1484    synchronized(connectThread){
1485      Thread.yield();
1486      connectThread.interrupt();
1487      connectThread=null;
1488    }
1489    thread=null;
1490    try{
1491      if(io!=null){
1492    if(io.in!=null) io.in.close();
1493    if(io.out!=null) io.out.close();
1494    if(io.out_ext!=null) io.out_ext.close();
1495      }
1496      if(proxy==null){
1497        if(socket!=null)
1498      socket.close();
1499      }
1500      else{
1501    synchronized(proxy){
1502      proxy.close();
1503    }
1504    proxy=null;
1505      }
1506    }
1507    catch(Exception JavaDoc e){
1508// e.printStackTrace();
1509
}
1510    io=null;
1511    socket=null;
1512// synchronized(jsch.pool){
1513
// jsch.pool.removeElement(this);
1514
// }
1515

1516    jsch.removeSession(this);
1517
1518    //System.gc();
1519
}
1520
1521  public int setPortForwardingL(int lport, String JavaDoc host, int rport) throws JSchException{
1522    return setPortForwardingL("127.0.0.1", lport, host, rport);
1523  }
1524  public int setPortForwardingL(String JavaDoc boundaddress, int lport, String JavaDoc host, int rport) throws JSchException{
1525    return setPortForwardingL(boundaddress, lport, host, rport, null);
1526  }
1527  public int setPortForwardingL(String JavaDoc boundaddress, int lport, String JavaDoc host, int rport, ServerSocketFactory ssf) throws JSchException{
1528    PortWatcher pw=PortWatcher.addPort(this, boundaddress, lport, host, rport, ssf);
1529    Thread JavaDoc tmp=new Thread JavaDoc(pw);
1530    tmp.setName("PortWatcher Thread for "+host);
1531    if(daemon_thread){
1532      tmp.setDaemon(daemon_thread);
1533    }
1534    tmp.start();
1535    return pw.lport;
1536  }
1537  public void delPortForwardingL(int lport) throws JSchException{
1538    delPortForwardingL("127.0.0.1", lport);
1539  }
1540  public void delPortForwardingL(String JavaDoc boundaddress, int lport) throws JSchException{
1541    PortWatcher.delPort(this, boundaddress, lport);
1542  }
1543  public String JavaDoc[] getPortForwardingL() throws JSchException{
1544    return PortWatcher.getPortForwarding(this);
1545  }
1546
1547  public void setPortForwardingR(int rport, String JavaDoc host, int lport) throws JSchException{
1548    setPortForwardingR(null, rport, host, lport, (SocketFactory)null);
1549  }
1550  public void setPortForwardingR(String JavaDoc bind_address, int rport, String JavaDoc host, int lport) throws JSchException{
1551    setPortForwardingR(bind_address, rport, host, lport, (SocketFactory)null);
1552  }
1553  public void setPortForwardingR(int rport, String JavaDoc host, int lport, SocketFactory sf) throws JSchException{
1554    setPortForwardingR(null, rport, host, lport, sf);
1555  }
1556  public void setPortForwardingR(String JavaDoc bind_address, int rport, String JavaDoc host, int lport, SocketFactory sf) throws JSchException{
1557    ChannelForwardedTCPIP.addPort(this, rport, host, lport, sf);
1558    setPortForwarding(bind_address, rport);
1559  }
1560
1561  public void setPortForwardingR(int rport, String JavaDoc daemon) throws JSchException{
1562    setPortForwardingR(null, rport, daemon, null);
1563  }
1564  public void setPortForwardingR(int rport, String JavaDoc daemon, Object JavaDoc[] arg) throws JSchException{
1565    setPortForwardingR(null, rport, daemon, arg);
1566  }
1567  public void setPortForwardingR(String JavaDoc bind_address, int rport, String JavaDoc daemon, Object JavaDoc[] arg) throws JSchException{
1568    ChannelForwardedTCPIP.addPort(this, rport, daemon, arg);
1569    setPortForwarding(bind_address, rport);
1570  }
1571
1572  private class GlobalRequestReply{
1573    private Thread JavaDoc thread=null;
1574    private int reply=-1;
1575    void setThread(Thread JavaDoc thread){
1576      this.thread=thread;
1577      this.reply=-1;
1578    }
1579    Thread JavaDoc getThread(){ return thread; }
1580    void setReply(int reply){ this.reply=reply; }
1581    int getReply(){ return this.reply; }
1582  }
1583  private GlobalRequestReply grr=new GlobalRequestReply();
1584  private void setPortForwarding(String JavaDoc bind_address, int rport) throws JSchException{
1585    synchronized(grr){
1586    Buffer buf=new Buffer(100); // ??
1587
Packet packet=new Packet(buf);
1588
1589    String JavaDoc address_to_bind="localhost";
1590    if(bind_address==null){
1591      //address_to_bind="localhost";
1592
}
1593    else if(bind_address.length()==0 ||
1594            bind_address.equals("*")){
1595      address_to_bind="";
1596    }
1597    else{
1598      address_to_bind=bind_address;
1599    }
1600
1601    try{
1602      // byte SSH_MSG_GLOBAL_REQUEST 80
1603
// string "tcpip-forward"
1604
// boolean want_reply
1605
// string address_to_bind
1606
// uint32 port number to bind
1607
packet.reset();
1608      buf.putByte((byte) SSH_MSG_GLOBAL_REQUEST);
1609      buf.putString("tcpip-forward".getBytes());
1610// buf.putByte((byte)0);
1611
buf.putByte((byte)1);
1612      buf.putString(address_to_bind.getBytes());
1613      //buf.putString("0.0.0.0".getBytes());
1614
buf.putInt(rport);
1615      write(packet);
1616    }
1617    catch(Exception JavaDoc e){
1618      if(e instanceof Throwable JavaDoc)
1619        throw new JSchException(e.toString(), (Throwable JavaDoc)e);
1620      throw new JSchException(e.toString());
1621    }
1622
1623    grr.setThread(Thread.currentThread());
1624    try{ Thread.sleep(10000);}
1625    catch(Exception JavaDoc e){
1626    }
1627    int reply=grr.getReply();
1628    grr.setThread(null);
1629    if(reply==0){
1630      throw new JSchException("remote port forwarding failed for listen port "+rport);
1631    }
1632    }
1633  }
1634  public void delPortForwardingR(int rport) throws JSchException{
1635    ChannelForwardedTCPIP.delPort(this, rport);
1636  }
1637
1638  private void initDeflater(String JavaDoc method) throws JSchException{
1639    if(method.equals("none")){
1640      deflater=null;
1641      return;
1642    }
1643    String JavaDoc foo=getConfig(method);
1644    if(foo!=null){
1645      if(method.equals("zlib") ||
1646         (isAuthed && method.equals("zlib@openssh.com"))){
1647        try{
1648          Class JavaDoc c=Class.forName(foo);
1649          deflater=(Compression)(c.newInstance());
1650          int level=6;
1651          try{ level=Integer.parseInt(getConfig("compression_level"));}
1652          catch(Exception JavaDoc ee){ }
1653          deflater.init(Compression.DEFLATER, level);
1654        }
1655        catch(Exception JavaDoc ee){
1656          throw new JSchException(ee.toString(), ee);
1657          //System.err.println(foo+" isn't accessible.");
1658
}
1659      }
1660    }
1661  }
1662  private void initInflater(String JavaDoc method) throws JSchException{
1663    if(method.equals("none")){
1664      inflater=null;
1665      return;
1666    }
1667    String JavaDoc foo=getConfig(method);
1668    if(foo!=null){
1669      if(method.equals("zlib") ||
1670         (isAuthed && method.equals("zlib@openssh.com"))){
1671        try{
1672          Class JavaDoc c=Class.forName(foo);
1673          inflater=(Compression)(c.newInstance());
1674          inflater.init(Compression.INFLATER, 0);
1675        }
1676        catch(Exception JavaDoc ee){
1677          throw new JSchException(ee.toString(), ee);
1678        //System.err.println(foo+" isn't accessible.");
1679
}
1680      }
1681    }
1682  }
1683
1684  void addChannel(Channel channel){
1685    channel.session=this;
1686  }
1687  public String JavaDoc getConfig(String JavaDoc name){
1688    Object JavaDoc foo=null;
1689    if(config!=null){
1690      foo=config.get(name);
1691      if(foo instanceof String JavaDoc) return (String JavaDoc)foo;
1692    }
1693    foo=jsch.getConfig(name);
1694    if(foo instanceof String JavaDoc) return (String JavaDoc)foo;
1695    return null;
1696  }
1697// public Channel getChannel(){ return channel; }
1698
public void setProxy(Proxy proxy){ this.proxy=proxy; }
1699  public void setHost(String JavaDoc host){ this.host=host; }
1700  public void setPort(int port){ this.port=port; }
1701  void setUserName(String JavaDoc username){ this.username=username; }
1702  public void setUserInfo(UserInfo userinfo){ this.userinfo=userinfo; }
1703  public UserInfo getUserInfo(){ return userinfo; }
1704  public void setInputStream(InputStream in){ this.in=in; }
1705  public void setOutputStream(OutputStream out){ this.out=out; }
1706  public void setX11Host(String JavaDoc host){ ChannelX11.setHost(host); }
1707  public void setX11Port(int port){ ChannelX11.setPort(port); }
1708  public void setX11Cookie(String JavaDoc cookie){ ChannelX11.setCookie(cookie); }
1709  public void setPassword(String JavaDoc password){
1710    if(password!=null)
1711      this.password=Util.str2byte(password);
1712  }
1713  public void setPassword(byte[] password){
1714    if(password!=null){
1715      this.password=new byte[password.length];
1716      System.arraycopy(password, 0, this.password, 0, password.length);
1717    }
1718  }
1719
1720  public void setConfig(java.util.Properties JavaDoc newconf){
1721    setConfig((java.util.Hashtable JavaDoc)newconf);
1722  }
1723 
1724  public void setConfig(java.util.Hashtable JavaDoc newconf){
1725    if(config==null) config=new java.util.Hashtable JavaDoc();
1726    for(java.util.Enumeration JavaDoc e=newconf.keys() ; e.hasMoreElements() ;) {
1727      String JavaDoc key=(String JavaDoc)(e.nextElement());
1728      config.put(key, (String JavaDoc)(newconf.get(key)));
1729    }
1730  }
1731  public void setSocketFactory(SocketFactory sfactory){
1732    socket_factory=sfactory;
1733  }
1734  public boolean isConnected(){ return isConnected; }
1735  public int getTimeout(){ return timeout; }
1736  public void setTimeout(int timeout) throws JSchException {
1737    if(socket==null){
1738      if(timeout<0){
1739        throw new JSchException("invalid timeout value");
1740      }
1741      this.timeout=timeout;
1742      return;
1743    }
1744    try{
1745      socket.setSoTimeout(timeout);
1746      this.timeout=timeout;
1747    }
1748    catch(Exception JavaDoc e){
1749      if(e instanceof Throwable JavaDoc)
1750        throw new JSchException(e.toString(), (Throwable JavaDoc)e);
1751      throw new JSchException(e.toString());
1752    }
1753  }
1754  public String JavaDoc getServerVersion(){
1755    return new String JavaDoc(V_S);
1756  }
1757  public String JavaDoc getClientVersion(){
1758    return new String JavaDoc(V_C);
1759  }
1760  public void setClientVersion(String JavaDoc cv){
1761    V_C=cv.getBytes();
1762  }
1763
1764  public void sendIgnore() throws Exception JavaDoc{
1765    Buffer buf=new Buffer();
1766    Packet packet=new Packet(buf);
1767    packet.reset();
1768    buf.putByte((byte)SSH_MSG_IGNORE);
1769    write(packet);
1770  }
1771
1772  private static final byte[] keepalivemsg="keepalive@jcraft.com".getBytes();
1773  public void sendKeepAliveMsg() throws Exception JavaDoc{
1774    Buffer buf=new Buffer();
1775    Packet packet=new Packet(buf);
1776    packet.reset();
1777    buf.putByte((byte)SSH_MSG_GLOBAL_REQUEST);
1778    buf.putString(keepalivemsg);
1779    buf.putByte((byte)1);
1780    write(packet);
1781  }
1782  
1783  private HostKey hostkey=null;
1784  public HostKey getHostKey(){ return hostkey; }
1785  public String JavaDoc getHost(){return host;}
1786  public String JavaDoc getUserName(){return username;}
1787  public int getPort(){return port;}
1788  public void setHostKeyAlias(String JavaDoc hostKeyAlias){
1789    this.hostKeyAlias=hostKeyAlias;
1790  }
1791  public String JavaDoc getHostKeyAlias(){
1792    return hostKeyAlias;
1793  }
1794  public void setServerAliveInterval(int interval) throws JSchException {
1795    setTimeout(interval);
1796    this.serverAliveInterval=interval;
1797  }
1798  public void setServerAliveCountMax(int count){
1799    this.serverAliveCountMax=count;
1800  }
1801  public void setDaemonThread(boolean enable){
1802    this.daemon_thread=enable;
1803  }
1804}
1805
Popular Tags