]> Joshua Wise's Git repositories - dumload.git/blame - src/com/jcraft/jsch/Session.java
Initial commit.
[dumload.git] / src / com / jcraft / jsch / Session.java
CommitLineData
0763e16d
JW
1/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
2/*
3Copyright (c) 2002-2010 ymnk, JCraft,Inc. All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, 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
18THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
19INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
21INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
22INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30package com.jcraft.jsch;
31
32import java.io.*;
33import java.net.*;
34
35public class Session implements Runnable{
36 static private final String version="JSCH-0.1.43";
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 static final int PACKET_MAX_SIZE = 256 * 1024;
69
70 private byte[] V_S; // server version
71 private byte[] V_C=Util.str2byte("SSH-2.0-"+version); // client version
72
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
76
77 private byte[] session_id;
78
79 private byte[] IVc2s;
80 private byte[] IVs2c;
81 private byte[] Ec2s;
82 private byte[] Es2c;
83 private byte[] MACc2s;
84 private byte[] MACs2c;
85
86 private int seqi=0;
87 private int seqo=0;
88
89 String[] guess=null;
90 private Cipher s2ccipher;
91 private Cipher c2scipher;
92 private MAC s2cmac;
93 private MAC c2smac;
94 //private byte[] mac_buf;
95 private byte[] s2cmac_result1;
96 private byte[] s2cmac_result2;
97
98 private Compression deflater;
99 private Compression inflater;
100
101 private IO io;
102 private Socket socket;
103 private int timeout=0;
104
105 private boolean isConnected=false;
106
107 private boolean isAuthed=false;
108
109 private Thread connectThread=null;
110 private Object lock=new Object();
111
112 boolean x11_forwarding=false;
113 boolean agent_forwarding=false;
114
115 InputStream in=null;
116 OutputStream out=null;
117
118 static Random random;
119
120 Buffer buf;
121 Packet packet;
122
123 SocketFactory socket_factory=null;
124
125 private java.util.Hashtable config=null;
126
127 private Proxy proxy=null;
128 private UserInfo userinfo;
129
130 private String hostKeyAlias=null;
131 private int serverAliveInterval=0;
132 private int serverAliveCountMax=1;
133
134 protected boolean daemon_thread=false;
135
136 private long kex_start_time=0L;
137
138 String host="127.0.0.1";
139 int port=22;
140
141 String username=null;
142 byte[] password=null;
143
144 JSch jsch;
145
146 Session(JSch jsch) throws JSchException{
147 super();
148 this.jsch=jsch;
149 buf=new Buffer();
150 packet=new Packet(buf);
151 }
152
153 public void connect() throws JSchException{
154 connect(timeout);
155 }
156
157 public void connect(int connectTimeout) throws JSchException{
158 if(isConnected){
159 throw new JSchException("session is already connected");
160 }
161
162 io=new IO();
163 if(random==null){
164 try{
165 Class c=Class.forName(getConfig("random"));
166 random=(Random)(c.newInstance());
167 }
168 catch(Exception e){
169 throw new JSchException(e.toString(), e);
170 }
171 }
172 Packet.setRandom(random);
173
174 if(JSch.getLogger().isEnabled(Logger.INFO)){
175 JSch.getLogger().log(Logger.INFO,
176 "Connecting to "+host+" port "+port);
177 }
178
179 try {
180 int i, j;
181
182 if(proxy==null){
183 InputStream in;
184 OutputStream out;
185 if(socket_factory==null){
186 socket=Util.createSocket(host, port, connectTimeout);
187 in=socket.getInputStream();
188 out=socket.getOutputStream();
189 }
190 else{
191 socket=socket_factory.createSocket(host, port);
192 in=socket_factory.getInputStream(socket);
193 out=socket_factory.getOutputStream(socket);
194 }
195 //if(timeout>0){ socket.setSoTimeout(timeout); }
196 socket.setTcpNoDelay(true);
197 io.setInputStream(in);
198 io.setOutputStream(out);
199 }
200 else{
201 synchronized(proxy){
202 proxy.connect(socket_factory, host, port, connectTimeout);
203 io.setInputStream(proxy.getInputStream());
204 io.setOutputStream(proxy.getOutputStream());
205 socket=proxy.getSocket();
206 }
207 }
208
209 if(connectTimeout>0 && socket!=null){
210 socket.setSoTimeout(connectTimeout);
211 }
212
213 isConnected=true;
214
215 if(JSch.getLogger().isEnabled(Logger.INFO)){
216 JSch.getLogger().log(Logger.INFO,
217 "Connection established");
218 }
219
220 jsch.addSession(this);
221
222 {
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);
228 }
229
230 while(true){
231 i=0;
232 j=0;
233 while(i<buf.buffer.length){
234 j=io.getByte();
235 if(j<0)break;
236 buf.buffer[i]=(byte)j; i++;
237 if(j==10)break;
238 }
239 if(j<0){
240 throw new JSchException("connection is closed by foreign host");
241 }
242
243 if(buf.buffer[i-1]==10){ // 0x0a
244 i--;
245 if(i>0 && buf.buffer[i-1]==13){ // 0x0d
246 i--;
247 }
248 }
249
250 if(i<=3 ||
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);
256 continue;
257 }
258
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
262 ){
263 throw new JSchException("invalid server's version string");
264 }
265 break;
266 }
267
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)+"]");
270
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));
276 }
277
278 send_kexinit();
279
280 buf=read(buf);
281 if(buf.getCommand()!=SSH_MSG_KEXINIT){
282 in_kex=false;
283 throw new JSchException("invalid protocol: "+buf.getCommand());
284 }
285
286 if(JSch.getLogger().isEnabled(Logger.INFO)){
287 JSch.getLogger().log(Logger.INFO,
288 "SSH_MSG_KEXINIT received");
289 }
290
291 KeyExchange kex=receive_kexinit(buf);
292
293 while(true){
294 buf=read(buf);
295 if(kex.getState()==buf.getCommand()){
296 kex_start_time=System.currentTimeMillis();
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.getCommand());
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.getCommand());
324 if(buf.getCommand()==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.getCommand());
336 }
337
338 boolean auth=false;
339 boolean auth_cancel=false;
340
341 UserAuth ua=null;
342 try{
343 Class c=Class.forName(getConfig("userauth.none"));
344 ua=(UserAuth)(c.newInstance());
345 }
346 catch(Exception e){
347 throw new JSchException(e.toString(), e);
348 }
349
350 auth=ua.start(this);
351
352 String cmethods=getConfig("PreferredAuthentications");
353 String[] cmethoda=Util.split(cmethods, ",");
354
355 String smethods=null;
356 if(!auth){
357 smethods=((UserAuthNone)ua).getMethods();
358 if(smethods!=null){
359 smethods=smethods.toLowerCase();
360 }
361 else{
362 // methods: publickey,password,keyboard-interactive
363 //smethods="publickey,password,keyboard-interactive";
364 smethods=cmethods;
365 }
366 }
367
368 String[] smethoda=Util.split(smethods, ",");
369
370 int methodi=0;
371
372 loop:
373 while(true){
374
375//System.err.println("methods: "+methods);
376
377 while(!auth &&
378 cmethoda!=null && methodi<cmethoda.length){
379
380 String method=cmethoda[methodi++];
381 boolean acceptable=false;
382 for(int k=0; k<smethoda.length; k++){
383 if(smethoda[k].equals(method)){
384 acceptable=true;
385 break;
386 }
387 }
388 if(!acceptable){
389 continue;
390 }
391
392 //System.err.println(" method: "+method);
393
394 if(JSch.getLogger().isEnabled(Logger.INFO)){
395 String str="Authentications that can continue: ";
396 for(int k=methodi-1; k<cmethoda.length; k++){
397 str+=cmethoda[k];
398 if(k+1<cmethoda.length)
399 str+=",";
400 }
401 JSch.getLogger().log(Logger.INFO,
402 str);
403 JSch.getLogger().log(Logger.INFO,
404 "Next authentication method: "+method);
405 }
406
407 ua=null;
408 try{
409 Class c=null;
410 if(getConfig("userauth."+method)!=null){
411 c=Class.forName(getConfig("userauth."+method));
412 ua=(UserAuth)(c.newInstance());
413 }
414 }
415 catch(Exception e){
416 if(JSch.getLogger().isEnabled(Logger.WARN)){
417 JSch.getLogger().log(Logger.WARN,
418 "failed to load "+method+" method");
419 }
420 }
421
422 if(ua!=null){
423 auth_cancel=false;
424 try{
425 auth=ua.start(this);
426 if(auth &&
427 JSch.getLogger().isEnabled(Logger.INFO)){
428 JSch.getLogger().log(Logger.INFO,
429 "Authentication succeeded ("+method+").");
430 }
431 }
432 catch(JSchAuthCancelException ee){
433 auth_cancel=true;
434 }
435 catch(JSchPartialAuthException ee){
436 String tmp = smethods;
437 smethods=ee.getMethods();
438 smethoda=Util.split(smethods, ",");
439 if(!tmp.equals(smethods)){
440 methodi=0;
441 }
442 //System.err.println("PartialAuth: "+methods);
443 auth_cancel=false;
444 continue loop;
445 }
446 catch(RuntimeException ee){
447 throw ee;
448 }
449 catch(Exception ee){
450 //System.err.println("ee: "+ee); // SSH_MSG_DISCONNECT: 2 Too many authentication failures
451 break loop;
452 }
453 }
454 }
455 break;
456 }
457
458 if(!auth){
459 if(auth_cancel)
460 throw new JSchException("Auth cancel");
461 throw new JSchException("Auth fail");
462 }
463
464 if(connectTimeout>0 || timeout>0){
465 socket.setSoTimeout(timeout);
466 }
467
468 isAuthed=true;
469
470 synchronized(lock){
471 if(isConnected){
472 connectThread=new Thread(this);
473 connectThread.setName("Connect thread "+host+" session");
474 if(daemon_thread){
475 connectThread.setDaemon(daemon_thread);
476 }
477 connectThread.start();
478 }
479 else{
480 // The session has been already down and
481 // we don't have to start new thread.
482 }
483 }
484 }
485 catch(Exception e) {
486 in_kex=false;
487 if(isConnected){
488 try{
489 packet.reset();
490 buf.putByte((byte)SSH_MSG_DISCONNECT);
491 buf.putInt(3);
492 buf.putString(Util.str2byte(e.toString()));
493 buf.putString(Util.str2byte("en"));
494 write(packet);
495 disconnect();
496 }
497 catch(Exception ee){
498 }
499 }
500 isConnected=false;
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);
505 }
506 finally{
507 Util.bzero(this.password);
508 this.password=null;
509 }
510 }
511
512 private KeyExchange receive_kexinit(Buffer buf) throws Exception {
513 int j=buf.getInt();
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];
517 }
518 else{
519 I_S=new byte[j-1-buf.getByte()];
520 }
521 System.arraycopy(buf.buffer, buf.s, I_S, 0, I_S.length);
522
523 if(!in_kex){ // We are in rekeying activated by the remote!
524 send_kexinit();
525 }
526
527 guess=KeyExchange.guess(I_S, I_C);
528 if(guess==null){
529 throw new JSchException("Algorithm negotiation fail");
530 }
531
532 if(!isAuthed &&
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.");
536 }
537
538 KeyExchange kex=null;
539 try{
540 Class c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_KEX_ALGS]));
541 kex=(KeyExchange)(c.newInstance());
542 }
543 catch(Exception e){
544 throw new JSchException(e.toString(), e);
545 }
546
547 kex.init(this, V_S, V_C, I_S, I_C);
548 return kex;
549 }
550
551 private boolean in_kex=false;
552 public void rekey() throws Exception {
553 send_kexinit();
554 }
555 private void send_kexinit() throws Exception {
556 if(in_kex)
557 return;
558
559 String cipherc2s=getConfig("cipher.c2s");
560 String ciphers2c=getConfig("cipher.s2c");
561
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.");
568 }
569 }
570
571 in_kex=true;
572 kex_start_time=System.currentTimeMillis();
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 Buffer buf = new Buffer(); // send_kexinit may be invoked
587 Packet packet = new Packet(buf); // by user thread.
588 packet.reset();
589 buf.putByte((byte) SSH_MSG_KEXINIT);
590 synchronized(random){
591 random.fill(buf.buffer, buf.index, 16); buf.skip(16);
592 }
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);
604 buf.putInt(0);
605
606 buf.setOffSet(5);
607 I_C=new byte[buf.getLength()];
608 buf.getByte(I_C);
609
610 write(packet);
611
612 if(JSch.getLogger().isEnabled(Logger.INFO)){
613 JSch.getLogger().log(Logger.INFO,
614 "SSH_MSG_KEXINIT sent");
615 }
616 }
617
618 private void send_newkeys() throws Exception {
619 // send SSH_MSG_NEWKEYS(21)
620 packet.reset();
621 buf.putByte((byte)SSH_MSG_NEWKEYS);
622 write(packet);
623
624 if(JSch.getLogger().isEnabled(Logger.INFO)){
625 JSch.getLogger().log(Logger.INFO,
626 "SSH_MSG_NEWKEYS sent");
627 }
628 }
629
630 private void checkHost(String chost, int port, KeyExchange kex) throws JSchException {
631 String shkc=getConfig("StrictHostKeyChecking");
632
633 if(hostKeyAlias!=null){
634 chost=hostKeyAlias;
635 }
636
637 //System.err.println("shkc: "+shkc);
638
639 byte[] K_S=kex.getHostKey();
640 String key_type=kex.getKeyType();
641 String key_fprint=kex.getFingerPrint();
642
643 if(hostKeyAlias==null && port!=22){
644 chost=("["+chost+"]:"+port);
645 }
646
647// hostkey=new HostKey(chost, K_S);
648
649 HostKeyRepository hkr=jsch.getHostKeyRepository();
650 int i=0;
651 synchronized(hkr){
652 i=hkr.check(chost, K_S);
653 }
654
655 boolean insert=false;
656
657 if((shkc.equals("ask") || shkc.equals("yes")) &&
658 i==HostKeyRepository.CHANGED){
659 String file=null;
660 synchronized(hkr){
661 file=hkr.getKnownHostsRepositoryID();
662 }
663 if(file==null){file="known_hosts";}
664
665 boolean b=false;
666
667 if(userinfo!=null){
668 String message=
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"+
674key_fprint+".\n"+
675"Please contact your system administrator.\n"+
676"Add correct host key in "+file+" to get rid of this message.";
677
678 if(shkc.equals("ask")){
679 b=userinfo.promptYesNo(message+
680 "\nDo you want to delete the old key and insert the new key?");
681 }
682 else{ // shkc.equals("yes")
683 userinfo.showMessage(message);
684 }
685 }
686
687 if(!b){
688 throw new JSchException("HostKey has been changed: "+chost);
689 }
690
691 synchronized(hkr){
692 hkr.remove(chost,
693 (key_type.equals("DSA") ? "ssh-dss" : "ssh-rsa"),
694 null);
695 insert=true;
696 }
697 }
698
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);
703 }
704 //System.err.println("finger-print: "+key_fprint);
705 if(userinfo!=null){
706 boolean foo=userinfo.promptYesNo(
707"The authenticity of host '"+host+"' can't be established.\n"+
708key_type+" key fingerprint is "+key_fprint+".\n"+
709"Are you sure you want to continue connecting?"
710 );
711 if(!foo){
712 throw new JSchException("reject HostKey: "+host);
713 }
714 insert=true;
715 }
716 else{
717 if(i==HostKeyRepository.NOT_INCLUDED)
718 throw new JSchException("UnknownHostKey: "+host+". "+key_type+" key fingerprint is "+key_fprint);
719 else
720 throw new JSchException("HostKey has been changed: "+host);
721 }
722 }
723
724 if(shkc.equals("no") &&
725 HostKeyRepository.NOT_INCLUDED==i){
726 insert=true;
727 }
728
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");
733 }
734
735 if(insert &&
736 JSch.getLogger().isEnabled(Logger.WARN)){
737 JSch.getLogger().log(Logger.WARN,
738 "Permanently added '"+host+"' ("+key_type+") to the list of known hosts.");
739 }
740
741 String hkh=getConfig("HashKnownHosts");
742 if(hkh.equals("yes") && (hkr instanceof KnownHosts)){
743 hostkey=((KnownHosts)hkr).createHashedHostKey(chost, K_S);
744 }
745 else{
746 hostkey=new HostKey(chost, K_S);
747 }
748
749 if(insert){
750 synchronized(hkr){
751 hkr.add(hostkey, userinfo);
752 }
753
754 }
755
756 }
757
758//public void start(){ (new Thread(this)).start(); }
759
760 public Channel openChannel(String type) throws JSchException{
761 if(!isConnected){
762 throw new JSchException("session is down");
763 }
764 try{
765 Channel channel=Channel.getChannel(type);
766 addChannel(channel);
767 channel.init();
768 return channel;
769 }
770 catch(Exception e){
771 //e.printStackTrace();
772 }
773 return null;
774 }
775
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();
782//}
783 if(deflater!=null){
784 packet.buffer.index=deflater.compress(packet.buffer.buffer,
785 5, packet.buffer.index);
786 }
787 if(c2scipher!=null){
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);
793 }
794 }
795 else{
796 packet.padding(8);
797 }
798
799 if(c2smac!=null){
800 c2smac.update(seqo);
801 c2smac.update(packet.buffer.buffer, 0, packet.buffer.index);
802 c2smac.doFinal(packet.buffer.buffer, packet.buffer.index);
803 }
804 if(c2scipher!=null){
805 byte[] buf=packet.buffer.buffer;
806 c2scipher.update(buf, 0, packet.buffer.index, buf, 0);
807 }
808 if(c2smac!=null){
809 packet.buffer.skip(c2smac.getBlockSize());
810 }
811 }
812
813 int[] uncompress_len=new int[1];
814
815 private int s2ccipher_size=8;
816 private int c2scipher_size=8;
817 public Buffer read(Buffer buf) throws Exception{
818 int j=0;
819 while(true){
820 buf.reset();
821 io.getByte(buf.buffer, buf.index, s2ccipher_size);
822 buf.index+=s2ccipher_size;
823 if(s2ccipher!=null){
824 s2ccipher.update(buf.buffer, 0, s2ccipher_size, buf.buffer, 0);
825 }
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);
833 }
834 int need = j+4-s2ccipher_size;
835 //if(need<0){
836 // throw new IOException("invalid data");
837 //}
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);
841 buf.buffer=foo;
842 }
843
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);
848 }
849 start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-s2ccipher_size);
850 }
851
852 if(need>0){
853 io.getByte(buf.buffer, buf.index, need); buf.index+=(need);
854 if(s2ccipher!=null){
855 s2ccipher.update(buf.buffer, s2ccipher_size, need, buf.buffer, s2ccipher_size);
856 }
857 }
858
859 if(s2cmac!=null){
860 s2cmac.update(seqi);
861 s2cmac.update(buf.buffer, 0, buf.index);
862
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");
868 }
869 start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-need);
870 continue;
871 }
872 }
873
874 seqi++;
875
876 if(inflater!=null){
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);
881 if(foo!=null){
882 buf.buffer=foo;
883 buf.index=5+uncompress_len[0];
884 }
885 else{
886 System.err.println("fail in inflater");
887 break;
888 }
889 }
890
891 int type=buf.getCommand()&0xff;
892 //System.err.println("read: "+type);
893 if(type==SSH_MSG_DISCONNECT){
894 buf.rewind();
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: "+
900 reason_code+
901 " "+Util.byte2str(description)+
902 " "+Util.byte2str(language_tag));
903 //break;
904 }
905 else if(type==SSH_MSG_IGNORE){
906 }
907 else if(type==SSH_MSG_UNIMPLEMENTED){
908 buf.rewind();
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);
914 }
915 }
916 else if(type==SSH_MSG_DEBUG){
917 buf.rewind();
918 buf.getInt();buf.getShort();
919/*
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));
926*/
927 }
928 else if(type==SSH_MSG_CHANNEL_WINDOW_ADJUST){
929 buf.rewind();
930 buf.getInt();buf.getShort();
931 Channel c=Channel.getChannel(buf.getInt(), this);
932 if(c==null){
933 }
934 else{
935 c.addRemoteWindowSize(buf.getInt());
936 }
937 }
938 else if(type==UserAuth.SSH_MSG_USERAUTH_SUCCESS){
939 isAuthed=true;
940 if(inflater==null && deflater==null){
941 String method;
942 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];
943 initDeflater(method);
944
945 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];
946 initInflater(method);
947 }
948 break;
949 }
950 else{
951 break;
952 }
953 }
954 buf.rewind();
955 return buf;
956 }
957
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;
961
962 if(!cipher.isCBC()){
963 throw new JSchException("Packet corrupt");
964 }
965
966 if(packet_length!=PACKET_MAX_SIZE && mac != null){
967 discard_mac = mac;
968 }
969
970 discard -= buf.index;
971
972 while(discard>0){
973 buf.reset();
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);
978 }
979 discard -= len;
980 }
981
982 if(discard_mac!=null){
983 discard_mac.doFinal(buf.buffer, 0);
984 }
985
986 throw new JSchException("Packet corrupt");
987 }
988
989 byte[] getSessionId(){
990 return session_id;
991 }
992
993 private void receive_newkeys(Buffer buf, KeyExchange kex) throws Exception {
994 updateKeys(kex);
995 in_kex=false;
996 }
997 private void updateKeys(KeyExchange kex) throws Exception{
998 byte[] K=kex.getK();
999 byte[] H=kex.getH();
1000 HASH hash=kex.getHash();
1001
1002// String[] guess=kex.guess;
1003
1004 if(session_id==null){
1005 session_id=new byte[H.length];
1006 System.arraycopy(H, 0, session_id, 0, H.length);
1007 }
1008
1009 /*
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)
1016 */
1017
1018 buf.reset();
1019 buf.putMPInt(K);
1020 buf.putByte(H);
1021 buf.putByte((byte)0x41);
1022 buf.putByte(session_id);
1023 hash.update(buf.buffer, 0, buf.index);
1024 IVc2s=hash.digest();
1025
1026 int j=buf.index-session_id.length-1;
1027
1028 buf.buffer[j]++;
1029 hash.update(buf.buffer, 0, buf.index);
1030 IVs2c=hash.digest();
1031
1032 buf.buffer[j]++;
1033 hash.update(buf.buffer, 0, buf.index);
1034 Ec2s=hash.digest();
1035
1036 buf.buffer[j]++;
1037 hash.update(buf.buffer, 0, buf.index);
1038 Es2c=hash.digest();
1039
1040 buf.buffer[j]++;
1041 hash.update(buf.buffer, 0, buf.index);
1042 MACc2s=hash.digest();
1043
1044 buf.buffer[j]++;
1045 hash.update(buf.buffer, 0, buf.index);
1046 MACs2c=hash.digest();
1047
1048 try{
1049 Class c;
1050 String method;
1051
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){
1056 buf.reset();
1057 buf.putMPInt(K);
1058 buf.putByte(H);
1059 buf.putByte(Es2c);
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);
1065 Es2c=bar;
1066 }
1067 s2ccipher.init(Cipher.DECRYPT_MODE, Es2c, IVs2c);
1068 s2ccipher_size=s2ccipher.getIVSize();
1069
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()];
1077
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){
1082 buf.reset();
1083 buf.putMPInt(K);
1084 buf.putByte(H);
1085 buf.putByte(Ec2s);
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);
1091 Ec2s=bar;
1092 }
1093 c2scipher.init(Cipher.ENCRYPT_MODE, Ec2s, IVc2s);
1094 c2scipher_size=c2scipher.getIVSize();
1095
1096 method=guess[KeyExchange.PROPOSAL_MAC_ALGS_CTOS];
1097 c=Class.forName(getConfig(method));
1098 c2smac=(MAC)(c.newInstance());
1099 c2smac.init(MACc2s);
1100
1101 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];
1102 initDeflater(method);
1103
1104 method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];
1105 initInflater(method);
1106 }
1107 catch(Exception e){
1108 if(e instanceof JSchException)
1109 throw e;
1110 throw new JSchException(e.toString(), e);
1111 //System.err.println("updatekeys: "+e);
1112 }
1113 }
1114
1115 /*public*/ /*synchronized*/ void write(Packet packet, Channel c, int length) throws Exception{
1116 long t = getTimeout();
1117 while(true){
1118 if(in_kex){
1119 if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){
1120 throw new JSchException("timeout in wating for rekeying process.");
1121 }
1122 try{Thread.sleep(10);}
1123 catch(java.lang.InterruptedException e){};
1124 continue;
1125 }
1126 synchronized(c){
1127 if(c.rwsize>=length){
1128 c.rwsize-=length;
1129 break;
1130 }
1131 }
1132 if(c.close || !c.isConnected()){
1133 throw new IOException("channel is broken");
1134 }
1135
1136 boolean sendit=false;
1137 int s=0;
1138 byte command=0;
1139 int recipient=-1;
1140 synchronized(c){
1141 if(c.rwsize>0){
1142 long len=c.rwsize;
1143 if(len>length){
1144 len=length;
1145 }
1146 if(len!=length){
1147 s=packet.shift((int)len, (c2smac!=null ? c2smac.getBlockSize() : 0));
1148 }
1149 command=packet.buffer.getCommand();
1150 recipient=c.getRecipient();
1151 length-=len;
1152 c.rwsize-=len;
1153 sendit=true;
1154 }
1155 }
1156 if(sendit){
1157 _write(packet);
1158 if(length==0){
1159 return;
1160 }
1161 packet.unshift(command, recipient, s, length);
1162 }
1163
1164 synchronized(c){
1165 if(in_kex){
1166 continue;
1167 }
1168 if(c.rwsize>=length){
1169 c.rwsize-=length;
1170 break;
1171 }
1172 try{
1173 c.notifyme++;
1174 c.wait(100);
1175 }
1176 catch(java.lang.InterruptedException e){
1177 }
1178 finally{
1179 c.notifyme--;
1180 }
1181 }
1182
1183 }
1184 _write(packet);
1185 }
1186
1187 public void write(Packet packet) throws Exception{
1188 // System.err.println("in_kex="+in_kex+" "+(packet.buffer.getCommand()));
1189 long t = getTimeout();
1190 while(in_kex){
1191 if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){
1192 throw new JSchException("timeout in wating for rekeying process.");
1193 }
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){
1205 break;
1206 }
1207 try{Thread.sleep(10);}
1208 catch(java.lang.InterruptedException e){};
1209 }
1210 _write(packet);
1211 }
1212
1213 private void _write(Packet packet) throws Exception{
1214 synchronized(lock){
1215 encode(packet);
1216 if(io!=null){
1217 io.put(packet);
1218 seqo++;
1219 }
1220 }
1221 }
1222
1223 Runnable thread;
1224 public void run(){
1225 thread=this;
1226
1227 byte[] foo;
1228 Buffer buf=new Buffer();
1229 Packet packet=new Packet(buf);
1230 int i=0;
1231 Channel channel;
1232 int[] start=new int[1];
1233 int[] length=new int[1];
1234 KeyExchange kex=null;
1235
1236 int stimeout=0;
1237 try{
1238 while(isConnected &&
1239 thread!=null){
1240 try{
1241 buf=read(buf);
1242 stimeout=0;
1243 }
1244 catch(InterruptedIOException/*SocketTimeoutException*/ ee){
1245 if(!in_kex && stimeout<serverAliveCountMax){
1246 sendKeepAliveMsg();
1247 stimeout++;
1248 continue;
1249 }
1250 throw ee;
1251 }
1252
1253 int msgType=buf.getCommand()&0xff;
1254
1255 if(kex!=null && kex.getState()==msgType){
1256 kex_start_time=System.currentTimeMillis();
1257 boolean result=kex.next(buf);
1258 if(!result){
1259 throw new JSchException("verify: "+result);
1260 }
1261 continue;
1262 }
1263
1264 switch(msgType){
1265 case SSH_MSG_KEXINIT:
1266//System.err.println("KEXINIT");
1267 kex=receive_kexinit(buf);
1268 break;
1269
1270 case SSH_MSG_NEWKEYS:
1271//System.err.println("NEWKEYS");
1272 send_newkeys();
1273 receive_newkeys(buf, kex);
1274 kex=null;
1275 break;
1276
1277 case SSH_MSG_CHANNEL_DATA:
1278 buf.getInt();
1279 buf.getByte();
1280 buf.getByte();
1281 i=buf.getInt();
1282 channel=Channel.getChannel(i, this);
1283 foo=buf.getString(start, length);
1284 if(channel==null){
1285 break;
1286 }
1287
1288 if(length[0]==0){
1289 break;
1290 }
1291
1292try{
1293 channel.write(foo, start[0], length[0]);
1294}
1295catch(Exception e){
1296//System.err.println(e);
1297 try{channel.disconnect();}catch(Exception ee){}
1298break;
1299}
1300 int len=length[0];
1301 channel.setLocalWindowSize(channel.lwsize-len);
1302 if(channel.lwsize<channel.lwsize_max/2){
1303 packet.reset();
1304 buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
1305 buf.putInt(channel.getRecipient());
1306 buf.putInt(channel.lwsize_max-channel.lwsize);
1307 write(packet);
1308 channel.setLocalWindowSize(channel.lwsize_max);
1309 }
1310 break;
1311
1312 case SSH_MSG_CHANNEL_EXTENDED_DATA:
1313 buf.getInt();
1314 buf.getShort();
1315 i=buf.getInt();
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]));
1320 if(channel==null){
1321 break;
1322 }
1323
1324 if(length[0]==0){
1325 break;
1326 }
1327
1328 channel.write_ext(foo, start[0], length[0]);
1329
1330 len=length[0];
1331 channel.setLocalWindowSize(channel.lwsize-len);
1332 if(channel.lwsize<channel.lwsize_max/2){
1333 packet.reset();
1334 buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
1335 buf.putInt(channel.getRecipient());
1336 buf.putInt(channel.lwsize_max-channel.lwsize);
1337 write(packet);
1338 channel.setLocalWindowSize(channel.lwsize_max);
1339 }
1340 break;
1341
1342 case SSH_MSG_CHANNEL_WINDOW_ADJUST:
1343 buf.getInt();
1344 buf.getShort();
1345 i=buf.getInt();
1346 channel=Channel.getChannel(i, this);
1347 if(channel==null){
1348 break;
1349 }
1350 channel.addRemoteWindowSize(buf.getInt());
1351 break;
1352
1353 case SSH_MSG_CHANNEL_EOF:
1354 buf.getInt();
1355 buf.getShort();
1356 i=buf.getInt();
1357 channel=Channel.getChannel(i, this);
1358 if(channel!=null){
1359 //channel.eof_remote=true;
1360 //channel.eof();
1361 channel.eof_remote();
1362 }
1363 /*
1364 packet.reset();
1365 buf.putByte((byte)SSH_MSG_CHANNEL_EOF);
1366 buf.putInt(channel.getRecipient());
1367 write(packet);
1368 */
1369 break;
1370 case SSH_MSG_CHANNEL_CLOSE:
1371 buf.getInt();
1372 buf.getShort();
1373 i=buf.getInt();
1374 channel=Channel.getChannel(i, this);
1375 if(channel!=null){
1376// channel.close();
1377 channel.disconnect();
1378 }
1379 /*
1380 if(Channel.pool.size()==0){
1381 thread=null;
1382 }
1383 */
1384 break;
1385 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
1386 buf.getInt();
1387 buf.getShort();
1388 i=buf.getInt();
1389 channel=Channel.getChannel(i, this);
1390 if(channel==null){
1391 //break;
1392 }
1393 int r=buf.getInt();
1394 long rws=buf.getUInt();
1395 int rps=buf.getInt();
1396
1397 channel.setRemoteWindowSize(rws);
1398 channel.setRemotePacketSize(rps);
1399 channel.setRecipient(r);
1400 break;
1401 case SSH_MSG_CHANNEL_OPEN_FAILURE:
1402 buf.getInt();
1403 buf.getShort();
1404 i=buf.getInt();
1405 channel=Channel.getChannel(i, this);
1406 if(channel==null){
1407 //break;
1408 }
1409 int reason_code=buf.getInt();
1410 //foo=buf.getString(); // additional textual information
1411 //foo=buf.getString(); // language tag
1412 channel.exitstatus=reason_code;
1413 channel.close=true;
1414 channel.eof_remote=true;
1415 channel.setRecipient(0);
1416 break;
1417 case SSH_MSG_CHANNEL_REQUEST:
1418 buf.getInt();
1419 buf.getShort();
1420 i=buf.getInt();
1421 foo=buf.getString();
1422 boolean reply=(buf.getByte()!=0);
1423 channel=Channel.getChannel(i, this);
1424 if(channel!=null){
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;
1430 }
1431 if(reply){
1432 packet.reset();
1433 buf.putByte(reply_type);
1434 buf.putInt(channel.getRecipient());
1435 write(packet);
1436 }
1437 }
1438 else{
1439 }
1440 break;
1441 case SSH_MSG_CHANNEL_OPEN:
1442 buf.getInt();
1443 buf.getShort();
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);
1451 packet.reset();
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);
1457 write(packet);
1458 }
1459 else{
1460 channel=Channel.getChannel(ctyp);
1461 addChannel(channel);
1462 channel.getData(buf);
1463 channel.init();
1464
1465 Thread tmp=new Thread(channel);
1466 tmp.setName("Channel "+ctyp+" "+host);
1467 if(daemon_thread){
1468 tmp.setDaemon(daemon_thread);
1469 }
1470 tmp.start();
1471 break;
1472 }
1473 case SSH_MSG_CHANNEL_SUCCESS:
1474 buf.getInt();
1475 buf.getShort();
1476 i=buf.getInt();
1477 channel=Channel.getChannel(i, this);
1478 if(channel==null){
1479 break;
1480 }
1481 channel.reply=1;
1482 break;
1483 case SSH_MSG_CHANNEL_FAILURE:
1484 buf.getInt();
1485 buf.getShort();
1486 i=buf.getInt();
1487 channel=Channel.getChannel(i, this);
1488 if(channel==null){
1489 break;
1490 }
1491 channel.reply=0;
1492 break;
1493 case SSH_MSG_GLOBAL_REQUEST:
1494 buf.getInt();
1495 buf.getShort();
1496 foo=buf.getString(); // request name
1497 reply=(buf.getByte()!=0);
1498 if(reply){
1499 packet.reset();
1500 buf.putByte((byte)SSH_MSG_REQUEST_FAILURE);
1501 write(packet);
1502 }
1503 break;
1504 case SSH_MSG_REQUEST_FAILURE:
1505 case SSH_MSG_REQUEST_SUCCESS:
1506 Thread t=grr.getThread();
1507 if(t!=null){
1508 grr.setReply(msgType==SSH_MSG_REQUEST_SUCCESS? 1 : 0);
1509 t.interrupt();
1510 }
1511 break;
1512 default:
1513 //System.err.println("Session.run: unsupported type "+msgType);
1514 throw new IOException("Unknown SSH message type "+msgType);
1515 }
1516 }
1517 }
1518 catch(Exception e){
1519 in_kex=false;
1520 if(JSch.getLogger().isEnabled(Logger.INFO)){
1521 JSch.getLogger().log(Logger.INFO,
1522 "Caught an exception, leaving main loop due to " + e.getMessage());
1523 }
1524 //System.err.println("# Session.run");
1525 //e.printStackTrace();
1526 }
1527 try{
1528 disconnect();
1529 }
1530 catch(NullPointerException e){
1531 //System.err.println("@1");
1532 //e.printStackTrace();
1533 }
1534 catch(Exception e){
1535 //System.err.println("@2");
1536 //e.printStackTrace();
1537 }
1538 isConnected=false;
1539 }
1540
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);
1548 }
1549 /*
1550 for(int i=0; i<Channel.pool.size(); i++){
1551 try{
1552 Channel c=((Channel)(Channel.pool.elementAt(i)));
1553 if(c.session==this) c.eof();
1554 }
1555 catch(Exception e){
1556 }
1557 }
1558 */
1559
1560 Channel.disconnect(this);
1561
1562 isConnected=false;
1563
1564 PortWatcher.delPort(this);
1565 ChannelForwardedTCPIP.delPort(this);
1566
1567 synchronized(lock){
1568 if(connectThread!=null){
1569 Thread.yield();
1570 connectThread.interrupt();
1571 connectThread=null;
1572 }
1573 }
1574 thread=null;
1575 try{
1576 if(io!=null){
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();
1580 }
1581 if(proxy==null){
1582 if(socket!=null)
1583 socket.close();
1584 }
1585 else{
1586 synchronized(proxy){
1587 proxy.close();
1588 }
1589 proxy=null;
1590 }
1591 }
1592 catch(Exception e){
1593// e.printStackTrace();
1594 }
1595 io=null;
1596 socket=null;
1597// synchronized(jsch.pool){
1598// jsch.pool.removeElement(this);
1599// }
1600
1601 jsch.removeSession(this);
1602
1603 //System.gc();
1604 }
1605
1606 public int setPortForwardingL(int lport, String host, int rport) throws JSchException{
1607 return setPortForwardingL("127.0.0.1", lport, host, rport);
1608 }
1609 public int setPortForwardingL(String boundaddress, int lport, String host, int rport) throws JSchException{
1610 return setPortForwardingL(boundaddress, lport, host, rport, null);
1611 }
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);
1616 if(daemon_thread){
1617 tmp.setDaemon(daemon_thread);
1618 }
1619 tmp.start();
1620 return pw.lport;
1621 }
1622 public void delPortForwardingL(int lport) throws JSchException{
1623 delPortForwardingL("127.0.0.1", lport);
1624 }
1625 public void delPortForwardingL(String boundaddress, int lport) throws JSchException{
1626 PortWatcher.delPort(this, boundaddress, lport);
1627 }
1628 public String[] getPortForwardingL() throws JSchException{
1629 return PortWatcher.getPortForwarding(this);
1630 }
1631
1632 public void setPortForwardingR(int rport, String host, int lport) throws JSchException{
1633 setPortForwardingR(null, rport, host, lport, (SocketFactory)null);
1634 }
1635 public void setPortForwardingR(String bind_address, int rport, String host, int lport) throws JSchException{
1636 setPortForwardingR(bind_address, rport, host, lport, (SocketFactory)null);
1637 }
1638 public void setPortForwardingR(int rport, String host, int lport, SocketFactory sf) throws JSchException{
1639 setPortForwardingR(null, rport, host, lport, sf);
1640 }
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);
1644 }
1645
1646 public void setPortForwardingR(int rport, String daemon) throws JSchException{
1647 setPortForwardingR(null, rport, daemon, null);
1648 }
1649 public void setPortForwardingR(int rport, String daemon, Object[] arg) throws JSchException{
1650 setPortForwardingR(null, rport, daemon, arg);
1651 }
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);
1655 }
1656
1657 private class GlobalRequestReply{
1658 private Thread thread=null;
1659 private int reply=-1;
1660 void setThread(Thread thread){
1661 this.thread=thread;
1662 this.reply=-1;
1663 }
1664 Thread getThread(){ return thread; }
1665 void setReply(int reply){ this.reply=reply; }
1666 int getReply(){ return this.reply; }
1667 }
1668 private GlobalRequestReply grr=new GlobalRequestReply();
1669 private void setPortForwarding(String bind_address, int rport) throws JSchException{
1670 synchronized(grr){
1671 Buffer buf=new Buffer(100); // ??
1672 Packet packet=new Packet(buf);
1673
1674 String address_to_bind=ChannelForwardedTCPIP.normalize(bind_address);
1675
1676 try{
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
1682 packet.reset();
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));
1688 buf.putInt(rport);
1689 write(packet);
1690 }
1691 catch(Exception e){
1692 if(e instanceof Throwable)
1693 throw new JSchException(e.toString(), (Throwable)e);
1694 throw new JSchException(e.toString());
1695 }
1696
1697 grr.setThread(Thread.currentThread());
1698 try{ Thread.sleep(10000);}
1699 catch(Exception e){
1700 }
1701 int reply=grr.getReply();
1702 grr.setThread(null);
1703 if(reply==0){
1704 throw new JSchException("remote port forwarding failed for listen port "+rport);
1705 }
1706 }
1707 }
1708 public void delPortForwardingR(int rport) throws JSchException{
1709 ChannelForwardedTCPIP.delPort(this, rport);
1710 }
1711
1712 private void initDeflater(String method) throws JSchException{
1713 if(method.equals("none")){
1714 deflater=null;
1715 return;
1716 }
1717 String foo=getConfig(method);
1718 if(foo!=null){
1719 if(method.equals("zlib") ||
1720 (isAuthed && method.equals("zlib@openssh.com"))){
1721 try{
1722 Class c=Class.forName(foo);
1723 deflater=(Compression)(c.newInstance());
1724 int level=6;
1725 try{ level=Integer.parseInt(getConfig("compression_level"));}
1726 catch(Exception ee){ }
1727 deflater.init(Compression.DEFLATER, level);
1728 }
1729 catch(Exception ee){
1730 throw new JSchException(ee.toString(), ee);
1731 //System.err.println(foo+" isn't accessible.");
1732 }
1733 }
1734 }
1735 }
1736 private void initInflater(String method) throws JSchException{
1737 if(method.equals("none")){
1738 inflater=null;
1739 return;
1740 }
1741 String foo=getConfig(method);
1742 if(foo!=null){
1743 if(method.equals("zlib") ||
1744 (isAuthed && method.equals("zlib@openssh.com"))){
1745 try{
1746 Class c=Class.forName(foo);
1747 inflater=(Compression)(c.newInstance());
1748 inflater.init(Compression.INFLATER, 0);
1749 }
1750 catch(Exception ee){
1751 throw new JSchException(ee.toString(), ee);
1752 //System.err.println(foo+" isn't accessible.");
1753 }
1754 }
1755 }
1756 }
1757
1758 void addChannel(Channel channel){
1759 channel.setSession(this);
1760 }
1761
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){
1774 if(password!=null)
1775 this.password=Util.str2byte(password);
1776 }
1777 public void setPassword(byte[] password){
1778 if(password!=null){
1779 this.password=new byte[password.length];
1780 System.arraycopy(password, 0, this.password, 0, password.length);
1781 }
1782 }
1783
1784 public void setConfig(java.util.Properties newconf){
1785 setConfig((java.util.Hashtable)newconf);
1786 }
1787
1788 public void setConfig(java.util.Hashtable newconf){
1789 synchronized(lock){
1790 if(config==null)
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)));
1795 }
1796 }
1797 }
1798
1799 public void setConfig(String key, String value){
1800 synchronized(lock){
1801 if(config==null){
1802 config=new java.util.Hashtable();
1803 }
1804 config.put(key, value);
1805 }
1806 }
1807
1808 public String getConfig(String key){
1809 Object foo=null;
1810 if(config!=null){
1811 foo=config.get(key);
1812 if(foo instanceof String) return (String)foo;
1813 }
1814 foo=jsch.getConfig(key);
1815 if(foo instanceof String) return (String)foo;
1816 return null;
1817 }
1818
1819 public void setSocketFactory(SocketFactory sfactory){
1820 socket_factory=sfactory;
1821 }
1822 public boolean isConnected(){ return isConnected; }
1823 public int getTimeout(){ return timeout; }
1824 public void setTimeout(int timeout) throws JSchException {
1825 if(socket==null){
1826 if(timeout<0){
1827 throw new JSchException("invalid timeout value");
1828 }
1829 this.timeout=timeout;
1830 return;
1831 }
1832 try{
1833 socket.setSoTimeout(timeout);
1834 this.timeout=timeout;
1835 }
1836 catch(Exception e){
1837 if(e instanceof Throwable)
1838 throw new JSchException(e.toString(), (Throwable)e);
1839 throw new JSchException(e.toString());
1840 }
1841 }
1842 public String getServerVersion(){
1843 return Util.byte2str(V_S);
1844 }
1845 public String getClientVersion(){
1846 return Util.byte2str(V_C);
1847 }
1848 public void setClientVersion(String cv){
1849 V_C=Util.str2byte(cv);
1850 }
1851
1852 public void sendIgnore() throws Exception{
1853 Buffer buf=new Buffer();
1854 Packet packet=new Packet(buf);
1855 packet.reset();
1856 buf.putByte((byte)SSH_MSG_IGNORE);
1857 write(packet);
1858 }
1859
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);
1864 packet.reset();
1865 buf.putByte((byte)SSH_MSG_GLOBAL_REQUEST);
1866 buf.putString(keepalivemsg);
1867 buf.putByte((byte)1);
1868 write(packet);
1869 }
1870
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;
1878 }
1879 public String getHostKeyAlias(){
1880 return hostKeyAlias;
1881 }
1882
1883 public void setServerAliveInterval(int interval) throws JSchException {
1884 setTimeout(interval);
1885 this.serverAliveInterval=interval;
1886 }
1887 public void setServerAliveCountMax(int count){
1888 this.serverAliveCountMax=count;
1889 }
1890
1891 public int getServerAliveInterval(){
1892 return this.serverAliveInterval;
1893 }
1894 public int getServerAliveCountMax(){
1895 return this.serverAliveCountMax;
1896 }
1897
1898 public void setDaemonThread(boolean enable){
1899 this.daemon_thread=enable;
1900 }
1901
1902 private String[] checkCiphers(String ciphers){
1903 if(ciphers==null || ciphers.length()==0)
1904 return null;
1905
1906 if(JSch.getLogger().isEnabled(Logger.INFO)){
1907 JSch.getLogger().log(Logger.INFO,
1908 "CheckCiphers: "+ciphers);
1909 }
1910
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]);
1916 }
1917 }
1918 if(result.size()==0)
1919 return null;
1920 String[] foo=new String[result.size()];
1921 System.arraycopy(result.toArray(), 0, foo, 0, result.size());
1922
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.");
1927 }
1928 }
1929
1930 return foo;
1931 }
1932
1933 static boolean checkCipher(String cipher){
1934 try{
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()]);
1940 return true;
1941 }
1942 catch(Exception e){
1943 return false;
1944 }
1945 }
1946}
This page took 0.297657 seconds and 4 git commands to generate.