diff -Nru jsch-0.1.37/build.xml jsch-0.1.41/build.xml --- jsch-0.1.37/build.xml 2008-01-08 21:57:25.000000000 +0300 +++ jsch-0.1.41/build.xml 2008-10-02 15:19:40.000000000 +0400 @@ -5,7 +5,7 @@ you can integrate its functionality into your own Java programs - + diff -Nru jsch-0.1.37/ChangeLog jsch-0.1.41/ChangeLog --- jsch-0.1.37/ChangeLog 2008-01-21 20:22:53.000000000 +0300 +++ jsch-0.1.41/ChangeLog 2008-12-28 05:55:20.000000000 +0300 @@ -1,8 +1,56 @@ ChangeLog of JSch ==================================================================== -Last modified: Mon Jan 21 07:57:03 UTC 2008 +Last modified: Wed Dec 31 07:44:52 UTC 2008 +Changes since version 0.1.40: +- bugfix: canceling the remote port-forwarding with the incorrect + bind-address. FIXED. +- bugfix: sftp had missed to close the file in some case. FIXED. +- bugfix: ls(sftp) will throw an exception for the empty directory + in connecting to some sftpd server. FIXED. +- change: dropping the session gently in accepting incorrect packets. +- change: by the default, aes128-ctr will be chosen if it is available + on the local and the remote. +- feature: adding the support for the private key ciphered in AES256. +- feature: new ciphers: aes128-ctr,aes192-ctr,aes256-ctr, + 3des-ctr,arcfour,arcfour128 ,arcfour256 + + +Changes since version 0.1.39: +- bugfix: ProxySOCKS4 had not been functional. FIXED. +- bugfix: NPE at closing the session when it is not opened. FIXED. +- change: JSch#getConfing has become public. + + +Changes since version 0.1.38: +- bugfix: session will be dropped at rekeying. FIXED. +- bugfix: NPE should not be thrown at unexpected session drop. FIXED. +- change: Channel#getSession() may throw JSchExecption. + + +Changes since version 0.1.37: +- bugfix: NPE should not be thrown at unexpected session drop. FIXED. +- bugfix: AIOOBE at Session#connect(). FIXED. +- bugfix: Even if 'true' is given for + Channel#setOutputStream(OutputStream out, boolean dontclose) + as the second paramter, 'out' will be closed. FIXED. +- change: 'examples/Sftp.java' has been modified to demonstrate + ChannelSftp#reaplpath(String path) +- change: setEnv(Hashtable env) for exec and shell channels have been + marked as @deprecated +- feature: setEnv(String name, String value) has been added to exec + and shell channels. +- feature: setEnv(byte[] name, byte[] value) has been added to exec + and shell channels. +- feature: ChannelSftp#realpath(String path) has been added. +- feature: ChannelExec#setCommand(byte[] command) has been added. +- feature: com.jcraft.jsch.ChannelSftp.LsEntry has implemented + java.lang.Comparable +- feature: Session#getServerAliveInterval(), Session#getServerAliveCountMaX() + have been added. + + Changes since version 0.1.36: - bugfix: some sftpd will send invalid data in sftp protocol point of view, and we need to work around such data. FIXED. @@ -58,7 +106,6 @@ String getClientVersion() void setFilenameEncoding(String encoding) String getExtension(String key) - Changes since version 0.1.33: - bugfix: there had a possibility that the session may be broken @@ -69,6 +116,9 @@ not been functional. FIXED. - bugfix: the remote port-forwarding to the daemon had been broken since 0.1.30. FIXED. +- change: the cipher "aes128-cbc" will be used if AES is available. +- change: the interface 'com.jcraft.jsch.ForwardedTCPIPDaemon' has been changed. +- change: the data transfer rate will be improved on some environment. - feature: ChannelExec can control the size of pty; ChannelExec#setPtySize(int col, int row, int wp, int hp) is added. @@ -76,9 +126,6 @@ Refer to 'examples/AES.java'. - feature: Session#setConfig(String key, String value), JSch#setConfig(String key, String value) have been added. -- change: the cipher "aes128-cbc" will be used if AES is available. -- change: the interface 'com.jcraft.jsch.ForwardedTCPIPDaemon' has been changed. -- change: the data transfer rate will be improved on some environment. Changes since version 0.1.32: @@ -105,13 +152,13 @@ a session will be terminated. FIXED. - bugfix: due to the cancel for keyboard-interactive auth method, a session will be terminated. FIXED. +- change: com.jcraft.jsch.jcraft.Compression#uncompress will respect + the argument "start". +- change: "gssapi-with-mic" will choose the default credential. - feature: Session#setPortForwardingL will return the assigned local TCP port number; TCP port will be assigned dynamically if lport==0. - feature: support for SSH_MSG_UNIMPLEMENTED. - feature: support for PASSWD_CHANGEREQ. -- change: com.jcraft.jsch.jcraft.Compression#uncompress will respect - the argument "start". -- change: "gssapi-with-mic" will choose the default credential. Changes since version 0.1.30: diff -Nru jsch-0.1.37/debian/changelog jsch-0.1.41/debian/changelog --- jsch-0.1.37/debian/changelog 2009-07-15 19:07:50.000000000 +0400 +++ jsch-0.1.41/debian/changelog 2009-07-15 19:07:50.000000000 +0400 @@ -1,3 +1,9 @@ +jsch (0.1.41-0ubuntu1) karmic; urgency=low + + * New upstream version (LP: #399323) + + -- Yulia Novozhilova Mon, 06 Jul 2009 16:18:58 +0400 + jsch (0.1.37-3ubuntu2) intrepid; urgency=low * Set java source version to 1.4. LP: #264808. diff -Nru jsch-0.1.37/debian/control jsch-0.1.41/debian/control --- jsch-0.1.37/debian/control 2009-07-15 19:07:50.000000000 +0400 +++ jsch-0.1.41/debian/control 2009-07-15 19:07:50.000000000 +0400 @@ -6,7 +6,7 @@ Uploaders: Jerry Haltom , Michael Koch Build-Depends: debhelper (>= 4.1.0), cdbs Build-Depends-Indep: default-jdk, ant (>= 1.6.5) -Standards-Version: 3.7.3 +Standards-Version: 3.8.0 Vcs-Svn: svn://svn.debian.org/svn/pkg-java/trunk/jsch Vcs-Browser: http://svn.debian.org/wsvn/pkg-java/trunk/jsch Homepage: http://www.jcraft.com/jsch/ @@ -14,7 +14,8 @@ Package: libjsch-java Architecture: all Section: libs -Depends: default-jre-headless | java2-runtime-headless +Depends: ${shlibs:Depends}, ${misc:Depends}, + default-jre-headless | java2-runtime-headless Description: java secure channel JSch is a pure Java implementation of SSH2. JSch allows you to connect to an sshd server and use port forwarding, X11 forwarding, @@ -25,6 +26,7 @@ Package: libjsch-java-doc Architecture: all Section: doc +Depends: ${misc:Depends} Description: java secure channel examples JSch is a pure Java implementation of SSH2. JSch allows you to connect to an sshd server and use port forwarding, X11 forwarding, diff -Nru jsch-0.1.37/debian/copyright jsch-0.1.41/debian/copyright --- jsch-0.1.37/debian/copyright 2009-07-15 19:07:50.000000000 +0400 +++ jsch-0.1.41/debian/copyright 2009-07-15 19:07:50.000000000 +0400 @@ -6,7 +6,7 @@ License: ------------------------------------------------------------------------------ -Copyright (c) 2002,2003,2004 Atsuhiko Yamanaka, JCraft,Inc. +Copyright (c) 2002,2003,2004,2005,2006,2007,2008 Atsuhiko Yamanaka, JCraft,Inc. All rights reserved. Redistribution and use in source and binary forms, with or without diff -Nru jsch-0.1.37/debian/manifest.mf jsch-0.1.41/debian/manifest.mf --- jsch-0.1.37/debian/manifest.mf 2009-07-15 19:07:50.000000000 +0400 +++ jsch-0.1.41/debian/manifest.mf 2009-07-15 19:07:50.000000000 +0400 @@ -1,5 +1,5 @@ Bundle-ManifestVersion: 2 -Bundle-Version: 0.1.37 +Bundle-Version: 0.1.41 Export-Package: com.jcraft.jsch, com.jcraft.jsch.jce;x-internal:=true, com.jcraft.jsch.jcraft;x-internal:=true Bundle-SymbolicName: com.jcraft.jsch Bundle-Name: %bundleName diff -Nru jsch-0.1.37/debian/orig-tar.sh jsch-0.1.41/debian/orig-tar.sh --- jsch-0.1.37/debian/orig-tar.sh 1970-01-01 03:00:00.000000000 +0300 +++ jsch-0.1.41/debian/orig-tar.sh 2009-07-15 19:07:50.000000000 +0400 @@ -0,0 +1,18 @@ +#!/bin/sh + +set -x + +# called by uscan with '--upstream-version' +package=`dpkg-parsechangelog | sed -n 's/^Source: //p'` +TAR=../"$package"_$2.orig.tar.gz +DIR=$package-$2.orig +TMP=tmp_dir + +# clean up the upstream tarball +unzip $3 -d $TMP +mkdir -p $DIR/src +unzip $TMP/ini4j-$2/ini4j-$2-sources.jar -d $DIR/src +mv $TMP/ini4j-$2/*.txt $DIR +rm -rf $DIR/src/META-INF +GZIP=--best tar -c -z -f $TAR $DIR +rm -rf $3 ./$DIR $TMP diff -Nru jsch-0.1.37/debian/rules jsch-0.1.41/debian/rules --- jsch-0.1.37/debian/rules 2009-07-15 19:07:50.000000000 +0400 +++ jsch-0.1.41/debian/rules 2009-07-15 19:07:50.000000000 +0400 @@ -15,3 +15,15 @@ binary-post-install/libjsch-java-doc:: install -d debian/libjsch-java-doc/usr/share/doc/libjsch-java-doc/examples install -m 644 examples/*.java debian/libjsch-java-doc/usr/share/doc/libjsch-java-doc/examples + +VERSION := $(shell dpkg-parsechangelog | egrep '^Version:' \ + | cut -f 2 -d ' ' | cut -f 2 -d ' '|sed 's/-[^-]*$$//') + +get-orig-source: + uscan \ + --verbose \ + --repack \ + --rename \ + --upstream-version $(VERSION) \ + --download-version $(VERSION) \ + --force-download diff -Nru jsch-0.1.37/examples/Sftp.java jsch-0.1.41/examples/Sftp.java --- jsch-0.1.37/examples/Sftp.java 2007-10-15 14:59:23.000000000 +0400 +++ jsch-0.1.41/examples/Sftp.java 2008-01-23 05:11:52.000000000 +0300 @@ -278,6 +278,19 @@ } continue; } + if(cmd.equals("realpath")){ + if(cmds.size()!=2) continue; + String p1=(String)cmds.elementAt(1); + String filename=null; + try{ + filename=c.realpath(p1); + out.println(filename); + } + catch(SftpException e){ + System.out.println(e.toString()); + } + continue; + } if(cmd.equals("version")){ out.println("SFTP protocol version "+c.version()); continue; @@ -491,6 +504,7 @@ "rm path Delete remote file\n"+ "symlink oldpath newpath Symlink remote file\n"+ "readlink path Check the target of a symbolic link\n"+ +"realpath path Canonicalize the path\n"+ "rekey Key re-exchanging\n"+ "compression level Packet compression will be enabled\n"+ "version Show SFTP version\n"+ diff -Nru jsch-0.1.37/examples/Shell.java jsch-0.1.41/examples/Shell.java --- jsch-0.1.37/examples/Shell.java 2007-10-15 15:02:11.000000000 +0400 +++ jsch-0.1.41/examples/Shell.java 2008-04-17 22:10:58.000000000 +0400 @@ -24,6 +24,7 @@ host=host.substring(host.indexOf('@')+1); Session session=jsch.getSession(user, host, 22); + //session.setPassword("your password"); // username and password will be given via UserInfo interface. @@ -41,13 +42,25 @@ //((ChannelShell)channel).setAgentForwarding(true); channel.setInputStream(System.in); + /* + // a hack for MS-DOS prompt on Windows. + channel.setInputStream(new FilterInputStream(System.in){ + public int read(byte[] b, int off, int len)throws IOException{ + return in.read(b, off, (len>1024?1024:len)); + } + }); + */ + channel.setOutputStream(System.out); /* + // Choose the pty-type "vt102". ((ChannelShell)channel).setPtyType("vt102"); - java.util.Hashtable env=new java.util.Hashtable(); - env.put("LANG", "ja_JP.eucJP"); - ((ChannelShell)channel).setEnv(env); + */ + + /* + // Set environment variable "LANG" as "ja_JP.eucJP". + ((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP"); */ //channel.connect(); diff -Nru jsch-0.1.37/README jsch-0.1.41/README --- jsch-0.1.37/README 2006-11-01 15:27:29.000000000 +0300 +++ jsch-0.1.41/README 2008-12-31 11:38:22.000000000 +0300 @@ -52,6 +52,8 @@ * SSH2 protocol support. * Key exchange: diffie-hellman-group-exchange-sha1, diffie-hellman-group1-sha1 * Cipher: blowfish-cbc,3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc + 3des-ctr,aes128-ctr,aes192-ctr,aes256-ctc, + arcfour,arcfour128,arcfour256 * MAC: hmac-md5,hmac-md5-96,hmac-sha1,hmac-sha1-96 * Host key type: ssh-dss, ssh-rsa * Userauth: password @@ -72,7 +74,7 @@ * generating DSA and RSA key pairs. * SSH File Transfer Protocol(version 0, 1, 2, 3) * partial authentication -* packet compression. +* packet compression: zlib, zlib@openssh.com JZlib(http://www.jcraft.com/jzlib/) has been used. * hashed known_hosts file. * NONE Cipher switching. @@ -92,8 +94,8 @@ AES cipher ========== -Since version 0.1.21, jsch can support aes128-cbc,aes192-cbc,aes256-cbc, -but you require AES support in your J2SE to choose some of them. +JSch supports aes128-cbc,aes192-cbc,aes256-cbc,aes128-ctr,aes192-ctr, +aes256-ctr but you require AES support in your J2SE to choose some of them. If you are using Sun's J2SE, J2SE 1.4.2 or later is required. And then, J2SE 1.4.2(or later) does not support aes256 by the default, because of 'import control restrictions of some countries'. @@ -102,7 +104,7 @@ Unlimited Strength Jurisdiction Policy Files 1.4.2" on http://java.sun.com/j2se/1.4.2/download.html#docs -we can enjoy 'aes256-cbc'. +we can enjoy 'aes256-cbc,aes256-ctr'. Stream Forwarding diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ChannelAgentForwarding.java jsch-0.1.41/src/com/jcraft/jsch/ChannelAgentForwarding.java --- jsch-0.1.37/src/com/jcraft/jsch/ChannelAgentForwarding.java 2008-01-21 08:46:02.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ChannelAgentForwarding.java 2008-06-11 07:55:20.000000000 +0400 @@ -103,8 +103,16 @@ int typ=rbuf.getByte(); - Vector identities=getSession().jsch.identities; - UserInfo userinfo=getSession().getUserInfo(); + Session _session=null; + try{ + _session=getSession(); + } + catch(JSchException e){ + throw new java.io.IOException(e.toString()); + } + + Vector identities=_session.jsch.identities; + UserInfo userinfo=_session.getUserInfo(); if(typ==SSH2_AGENTC_REQUEST_IDENTITIES){ mbuf.reset(); @@ -211,7 +219,7 @@ wbuf.putString(message); try{ - session.write(packet, this, 4+message.length); + getSession().write(packet, this, 4+message.length); } catch(Exception e){ } diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ChannelDirectTCPIP.java jsch-0.1.41/src/com/jcraft/jsch/ChannelDirectTCPIP.java --- jsch-0.1.37/src/com/jcraft/jsch/ChannelDirectTCPIP.java 2008-01-21 08:46:07.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ChannelDirectTCPIP.java 2008-06-11 03:27:19.000000000 +0400 @@ -60,7 +60,8 @@ public void connect() throws JSchException{ try{ - if(!session.isConnected()){ + Session _session=getSession(); + if(!_session.isConnected()){ throw new JSchException("session is down"); } Buffer buf=new Buffer(150); @@ -82,12 +83,12 @@ buf.putInt(port); buf.putString(originator_IP_address.getBytes()); buf.putInt(originator_port); - session.write(packet); + _session.write(packet); int retry=1000; try{ while(this.getRecipient()==-1 && - session.isConnected() && + _session.isConnected() && retry>0 && !eof_remote){ //Thread.sleep(500); @@ -97,7 +98,7 @@ } catch(Exception ee){ } - if(!session.isConnected()){ + if(!_session.isConnected()){ throw new JSchException("session is down"); } if(retry==0 || this.eof_remote){ @@ -114,9 +115,9 @@ if(io.in!=null){ thread=new Thread(this); - thread.setName("DirectTCPIP thread "+session.getHost()); - if(session.daemon_thread){ - thread.setDaemon(session.daemon_thread); + thread.setName("DirectTCPIP thread "+_session.getHost()); + if(_session.daemon_thread){ + thread.setDaemon(_session.daemon_thread); } thread.start(); } @@ -138,6 +139,7 @@ int i=0; try{ + Session _session=getSession(); while(isConnected() && thread!=null && io!=null && @@ -158,7 +160,7 @@ buf.putInt(recipient); buf.putInt(i); buf.skip(i); - session.write(packet, this, i); + _session.write(packet, this, i); } } catch(Exception e){ diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ChannelExec.java jsch-0.1.41/src/com/jcraft/jsch/ChannelExec.java --- jsch-0.1.37/src/com/jcraft/jsch/ChannelExec.java 2008-01-21 08:46:12.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ChannelExec.java 2008-06-11 08:09:11.000000000 +0400 @@ -33,13 +33,14 @@ public class ChannelExec extends ChannelSession{ - String command=""; + byte[] command=new byte[0]; public void start() throws JSchException{ + Session _session=getSession(); try{ sendRequests(); Request request=new RequestExec(command); - request.request(session, this); + request.request(_session, this); } catch(Exception e){ if(e instanceof JSchException) throw (JSchException)e; @@ -50,18 +51,24 @@ if(io.in!=null){ thread=new Thread(this); - thread.setName("Exec thread "+session.getHost()); - if(session.daemon_thread){ - thread.setDaemon(session.daemon_thread); + thread.setName("Exec thread "+_session.getHost()); + if(_session.daemon_thread){ + thread.setDaemon(_session.daemon_thread); } thread.start(); } } - public void setCommand(String foo){ command=foo;} - public void init(){ - io.setInputStream(session.in); - io.setOutputStream(session.out); + public void setCommand(String command){ + this.command=command.getBytes(); + } + public void setCommand(byte[] command){ + this.command=command; + } + + void init() throws JSchException { + io.setInputStream(getSession().in); + io.setOutputStream(getSession().out); } public void setErrStream(java.io.OutputStream out){ diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ChannelForwardedTCPIP.java jsch-0.1.41/src/com/jcraft/jsch/ChannelForwardedTCPIP.java --- jsch-0.1.37/src/com/jcraft/jsch/ChannelForwardedTCPIP.java 2008-01-21 08:46:17.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ChannelForwardedTCPIP.java 2008-12-15 10:59:25.000000000 +0300 @@ -70,7 +70,7 @@ ), false); daemon.setChannel(this, getInputStream(), out); - Object[] foo=getPort(session, rport); + Object[] foo=getPort(getSession(), rport); daemon.setArg((Object[])foo[3]); new Thread(daemon).start(); @@ -115,7 +115,7 @@ buf.putInt(recipient); buf.putInt(i); buf.skip(i); - session.write(packet, this, i); + getSession().write(packet, this, i); } } catch(Exception e){ @@ -125,6 +125,7 @@ //eof(); disconnect(); } + void getData(Buffer buf){ setRecipient(buf.getInt()); setRemoteWindowSize(buf.getInt()); @@ -141,22 +142,30 @@ System.err.println("orgport: "+orgport); */ + Session _session=null; + try{ + _session=getSession(); + } + catch(JSchException e){ + // session has been already down. + } + synchronized(pool){ for(int i=0; i=5){ - this.factory=((SocketFactory)foo[4]); + if(foo.length>=6){ + this.factory=((SocketFactory)foo[5]); } break; } if(target==null){ - System.err.println("??"); + //System.err.println("??"); } } } @@ -190,33 +199,54 @@ return bar; } - static void addPort(Session session, int port, String target, int lport, SocketFactory factory) throws JSchException{ + static String normalize(String address){ + if(address==null){ return "localhost"; } + else if(address.length()==0 || address.equals("*")){ return ""; } + else{ return address; } + } + + static void addPort(Session session, String _address_to_bind, int port, String target, int lport, SocketFactory factory) throws JSchException{ + String address_to_bind=normalize(_address_to_bind); synchronized(pool){ if(getPort(session, port)!=null){ throw new JSchException("PortForwardingR: remote port "+port+" is already registered."); } - Object[] foo=new Object[5]; + Object[] foo=new Object[6]; foo[0]=session; foo[1]=new Integer(port); foo[2]=target; foo[3]=new Integer(lport); - foo[4]=factory; + foo[4]=address_to_bind; + foo[5]=factory; pool.addElement(foo); } } - static void addPort(Session session, int port, String daemon, Object[] arg) throws JSchException{ + static void addPort(Session session, String _address_to_bind, int port, String daemon, Object[] arg) throws JSchException{ + String address_to_bind=normalize(_address_to_bind); synchronized(pool){ if(getPort(session, port)!=null){ throw new JSchException("PortForwardingR: remote port "+port+" is already registered."); } - Object[] foo=new Object[4]; + Object[] foo=new Object[5]; foo[0]=session; foo[1]=new Integer(port); foo[2]=daemon; foo[3]=arg; + foo[4]=address_to_bind; pool.addElement(foo); } } static void delPort(ChannelForwardedTCPIP c){ - delPort(c.session, c.rport); + Session _session=null; + try{ + _session=c.getSession(); + } + catch(JSchException e){ + // session has been already down. + } + if(_session!=null) + delPort(_session, c.rport); } static void delPort(Session session, int rport){ + delPort(session, null, rport); + } + static void delPort(Session session, String address_to_bind, int rport){ synchronized(pool){ Object[] foo=null; for(int i=0; i0){ if(timeout>0L){ if((System.currentTimeMillis()-start)>timeout){ @@ -180,7 +181,7 @@ try{Thread.sleep(50);}catch(Exception ee){} retry--; } - if(!session.isConnected()){ + if(!_session.isConnected()){ throw new JSchException("session is down"); } if(retry==0){ @@ -328,7 +329,7 @@ try{ int foo=dataLen; dataLen=0; - session.write(packet, channel, foo); + getSession().write(packet, channel, foo); } catch(Exception e){ close(); @@ -390,13 +391,11 @@ } void write(byte[] foo, int s, int l) throws IOException { try{ -// if(io.out!=null) io.put(foo, s, l); }catch(NullPointerException e){} } void write_ext(byte[] foo, int s, int l) throws IOException { try{ -// if(io.out_ext!=null) io.put_ext(foo, s, l); }catch(NullPointerException e){} } @@ -404,18 +403,13 @@ void eof_remote(){ eof_remote=true; try{ - if(io.out!=null){ - io.out.close(); - io.out=null; - } + io.out_close(); } catch(NullPointerException e){} - catch(IOException e){} } void eof(){ -//System.err.println("EOF!!!! "+this); -//Thread.dumpStack(); + //System.err.println("EOF!!!! "+this); if(close)return; if(eof_local)return; eof_local=true; @@ -426,7 +420,7 @@ packet.reset(); buf.putByte((byte)Session.SSH_MSG_CHANNEL_EOF); buf.putInt(getRecipient()); - session.write(packet); + getSession().write(packet); } catch(Exception e){ //System.err.println("Channel.eof"); @@ -486,7 +480,7 @@ packet.reset(); buf.putByte((byte)Session.SSH_MSG_CHANNEL_CLOSE); buf.putInt(getRecipient()); - session.write(packet); + getSession().write(packet); } catch(Exception e){ //e.printStackTrace(); @@ -546,16 +540,17 @@ } public boolean isConnected(){ - if(this.session!=null){ - return session.isConnected() && connected; + Session _session=this.session; + if(_session!=null){ + return _session.isConnected() && connected; } return false; } - public void sendSignal(String foo) throws Exception { + public void sendSignal(String signal) throws Exception { RequestSignal request=new RequestSignal(); - request.setSignal(foo); - request.request(session, this); + request.setSignal(signal); + request.request(getSession(), this); } // public String toString(){ @@ -593,15 +588,21 @@ } } - void setExitStatus(int foo){ exitstatus=foo; } + void setExitStatus(int status){ exitstatus=status; } public int getExitStatus(){ return exitstatus; } void setSession(Session session){ this.session=session; } - public Session getSession(){ return session; } + + public Session getSession() throws JSchException{ + Session _session=session; + if(_session==null){ + throw new JSchException("session is not available"); + } + return _session; + } public int getId(){ return id; } - //public int getRecipientId(){ return getRecipient(); } protected void sendOpenConfirmation() throws Exception{ Buffer buf=new Buffer(100); @@ -612,7 +613,7 @@ buf.putInt(id); buf.putInt(lwsize); buf.putInt(lmpsize); - session.write(packet); + getSession().write(packet); } protected void sendOpenFailure(int reasoncode){ @@ -625,7 +626,7 @@ buf.putInt(reasoncode); buf.putString("open failed".getBytes()); buf.putString("".getBytes()); - session.write(packet); + getSession().write(packet); } catch(Exception e){ } diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ChannelSession.java jsch-0.1.41/src/com/jcraft/jsch/ChannelSession.java --- jsch-0.1.37/src/com/jcraft/jsch/ChannelSession.java 2008-01-21 08:46:23.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ChannelSession.java 2008-06-11 03:12:36.000000000 +0400 @@ -53,41 +53,134 @@ io=new IO(); } + /** + * Enable the agent forwarding. + * + * @param enable + */ public void setAgentForwarding(boolean enable){ agent_forwarding=enable; } + + /** + * Enable the X11 forwarding. + * + * @param enable + * @see RFC4254 6.3.1. Requesting X11 Forwarding + */ public void setXForwarding(boolean enable){ xforwading=enable; } + + /** + * @deprecated Use {@link #setEnv(String, String)} or {@link #setEnv(byte[], byte[])} instead. + * @see #setEnv(String, String) + * @see #setEnv(byte[], byte[]) + */ public void setEnv(Hashtable env){ - this.env=env; + synchronized(this){ + this.env=env; + } + } + + /** + * Set the environment variable. + * If name and value are needed to be passed + * to the remote in your faivorite encoding,use + * {@link #setEnv(byte[], byte[])}. + * + * @param name A name for environment variable. + * @param value A value for environment variable. + * @see RFC4254 6.4 Environment Variable Passing + */ + public void setEnv(String name, String value){ + setEnv(name.getBytes(), value.getBytes()); + } + + /** + * Set the environment variable. + * + * @param name A name of environment variable. + * @param value A value of environment variable. + * @see #setEnv(String, String) + * @see RFC4254 6.4 Environment Variable Passing + */ + public void setEnv(byte[] name, byte[] value){ + synchronized(this){ + getEnv().put(name, value); + } } + private Hashtable getEnv(){ + if(env==null) + env=new Hashtable(); + return env; + } + + /** + * Allocate a Pseudo-Terminal. + * + * @param enable + * @see RFC4254 6.2. Requesting a Pseudo-Terminal + */ public void setPty(boolean enable){ pty=enable; } + /** + * Set the terminal mode. + * + * @param terminal_mode + */ public void setTerminalMode(byte[] terminal_mode){ this.terminal_mode=terminal_mode; } + + /** + * Change the window dimension interactively. + * + * @param col terminal width, columns + * @param row terminal height, rows + * @param wp terminal width, pixels + * @param hp terminal height, pixels + * @see RFC4254 6.7. Window Dimension Change Message + */ public void setPtySize(int col, int row, int wp, int hp){ - if(!pty){ + setPtyType(this.ttype, col, row, wp, hp); + if(!pty || !isConnected()){ return; } try{ RequestWindowChange request=new RequestWindowChange(); request.setSize(col, row, wp, hp); - request.request(session, this); + request.request(getSession(), this); } catch(Exception e){ //System.err.println("ChannelSessio.setPtySize: "+e); } } + /** + * Set the terminal type. + * This method is not effective after Channel#connect(). + * + * @param ttype terminal type(for example, "vt100") + * @see #setPtyType(String, int, int, int, int) + */ public void setPtyType(String ttype){ setPtyType(ttype, 80, 24, 640, 480); } + /** + * Set the terminal type. + * This method is not effective after Channel#connect(). + * + * @param ttype terminal type(for example, "vt100") + * @param col terminal width, columns + * @param row terminal height, rows + * @param wp terminal width, pixels + * @param hp terminal height, pixels + */ public void setPtyType(String ttype, int col, int row, int wp, int hp){ this.ttype=ttype; this.tcol=col; @@ -97,15 +190,16 @@ } protected void sendRequests() throws Exception{ + Session _session=getSession(); Request request; if(agent_forwarding){ request=new RequestAgentForwarding(); - request.request(session, this); + request.request(_session, this); } if(xforwading){ request=new RequestX11(); - request.request(session, this); + request.request(_session, this); } if(pty){ @@ -115,26 +209,30 @@ if(terminal_mode!=null){ ((RequestPtyReq)request).setTerminalMode(terminal_mode); } - request.request(session, this); + request.request(_session, this); } if(env!=null){ - for(Enumeration _env=env.keys() ; _env.hasMoreElements() ;) { - String name=(String)(_env.nextElement()); - String value=(String)(env.get(name)); + for(Enumeration _env=env.keys(); _env.hasMoreElements();){ + Object name=_env.nextElement(); + Object value=env.get(name); request=new RequestEnv(); - ((RequestEnv)request).setEnv(name, value); - request.request(session, this); + ((RequestEnv)request).setEnv(toByteArray(name), + toByteArray(value)); + request.request(_session, this); } } } + private byte[] toByteArray(Object o){ + if(o instanceof String){ + return ((String)o).getBytes(); + } + return (byte[])o; + } + public void run(){ //System.err.println(this+":run >"); -/* - if(thread!=null){ return; } - thread=Thread.currentThread(); -*/ Buffer buf=new Buffer(rmpsize); Packet packet=new Packet(buf); @@ -161,7 +259,7 @@ buf.putInt(recipient); buf.putInt(i); buf.skip(i); - session.write(packet, this, i); + getSession().write(packet, this, i); } } catch(Exception e){ diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ChannelSftp.java jsch-0.1.41/src/com/jcraft/jsch/ChannelSftp.java --- jsch-0.1.37/src/com/jcraft/jsch/ChannelSftp.java 2008-01-21 09:19:28.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ChannelSftp.java 2008-12-28 05:56:17.000000000 +0300 @@ -139,6 +139,7 @@ private String version=String.valueOf(client_version); private java.util.Hashtable extensions=null; + private InputStream io_in=null; /* 10. Changes from previous protocol versions @@ -168,7 +169,7 @@ private String fEncoding=UTF8; private boolean fEncoding_is_utf8=true; - public void init(){ + void init(){ } public void start() throws JSchException{ @@ -179,8 +180,14 @@ PipedInputStream pis=new MyPipedInputStream(pos, 32*1024); io.setInputStream(pis); + io_in=io.in; + + if(io_in==null){ + throw new JSchException("channel is down"); + } + Request request=new RequestSftp(); - request.request(session, this); + request.request(getSession(), this); /* System.err.println("lmpsize: "+lmpsize); @@ -204,7 +211,8 @@ header=header(buf, header); length=header.length; if(length > MAX_MSG_LENGTH){ - throw new SftpException(SSH_FX_FAILURE, "Received message is too long: " + length); + throw new SftpException(SSH_FX_FAILURE, + "Received message is too long: " + length); } type=header.type; // 2 -> SSH_FXP_VERSION server_version=header.rid; @@ -325,7 +333,8 @@ dstsb=new StringBuffer(dst); } else if(vsize>1){ - throw new SftpException(SSH_FX_FAILURE, "Copying multiple files, but the destination is missing or a file."); + throw new SftpException(SSH_FX_FAILURE, + "Copying multiple files, but the destination is missing or a file."); } for(int j=0; j0){ _i-=sendWRITE(handle, offset, data, 0, _i); if((seq-1)==startid || - io.in.available()>=1024){ - while(io.in.available()>0){ + io_in.available()>=1024){ + while(io_in.available()>0){ if(checkStatus(ackid, header)){ _ackid=ackid[0]; if(startid>_ackid || _ackid>seq-1){ @@ -563,7 +571,6 @@ } if(monitor!=null)monitor.end(); _sendCLOSE(handle, header); -//System.err.println("start end "+startid+" "+endid); } catch(Exception e){ if(e instanceof SftpException) throw (SftpException)e; @@ -624,7 +631,6 @@ } final byte[] handle=buf.getString(); // handle - //long offset=0; if(mode==RESUME || mode==APPEND){ offset+=skip; } @@ -665,8 +671,8 @@ s+=sent; _len-=sent; if((seq-1)==startid || - io.in.available()>=1024){ - while(io.in.available()>0){ + io_in.available()>=1024){ + while(io_in.available()>0){ if(checkStatus(ackid, header)){ _ackid=ackid[0]; if(startid>_ackid || _ackid>seq-1){ @@ -771,14 +777,16 @@ dstsb=new StringBuffer(dst); } else if(vsize>1){ - throw new SftpException(SSH_FX_FAILURE, "Copying multiple files, but destination is missing or a file."); + throw new SftpException(SSH_FX_FAILURE, + "Copying multiple files, but destination is missing or a file."); } for(int j=0; jsize_of_src){ - throw new SftpException(SSH_FX_FAILURE, "failed to resume for "+_dst); + throw new SftpException(SSH_FX_FAILURE, + "failed to resume for "+_dst); } if(size_of_dst==size_of_src){ return; @@ -812,15 +821,21 @@ } FileOutputStream fos=null; - if(mode==OVERWRITE){ - fos=new FileOutputStream(_dst); - } - else{ - fos=new FileOutputStream(_dst, true); // append - } - // System.err.println("_get: "+_src+", "+_dst); - _get(_src, fos, monitor, mode, new File(_dst).length()); - fos.close(); + try{ + if(mode==OVERWRITE){ + fos=new FileOutputStream(_dst); + } + else{ + fos=new FileOutputStream(_dst, true); // append + } + // System.err.println("_get: "+_src+", "+_dst); + _get(_src, fos, monitor, mode, new File(_dst).length()); + } + finally{ + if(fos!=null){ + fos.close(); + } + } } } catch(Exception e){ @@ -928,7 +943,7 @@ if(bar>buf.buffer.length){ bar=buf.buffer.length; } - i=io.in.read(buf.buffer, 0, bar); + i=io_in.read(buf.buffer, 0, bar); if(i<0){ break loop; } @@ -941,7 +956,7 @@ if(monitor!=null){ if(!monitor.count(data_len)){ while(foo>0){ - i=io.in.read(buf.buffer, + i=io_in.read(buf.buffer, 0, (buf.buffer.lengthlen){ bar=len; } - i=io.in.read(d, s, bar); + i=io_in.read(d, s, bar); if(i<0){ return -1; } @@ -1119,7 +1134,7 @@ int _len=rest_length; int j; while(_len>0){ - j=io.in.read(rest_byte, _s, _len); + j=io_in.read(rest_byte, _s, _len); if(j<=0)break; _s+=j; _len-=j; @@ -1140,16 +1155,6 @@ public void close() throws IOException{ if(closed)return; closed=true; - /* - while(rest_length>0){ - int foo=rest_length; - if(foo>buf.buffer.length){ - foo=buf.buffer.length; - } - io.in.read(buf.buffer, 0, foo); - rest_length-=foo; - } - */ if(monitor!=null)monitor.end(); try{_sendCLOSE(handle, header);} catch(Exception e){throw new IOException("error");} @@ -1314,10 +1319,6 @@ } _sendCLOSE(handle, header); - if(v.size()==0){ - throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such file: "+path); - } - /* if(v.size()==1 && pattern_has_wildcard){ LsEntry le=(LsEntry)v.elementAt(0); @@ -1910,7 +1911,7 @@ private void read(byte[] buf, int s, int l) throws IOException, SftpException{ int i=0; while(l>0){ - i=io.in.read(buf, s, l); + i=io_in.read(buf, s, l); if(i<=0){ throw new SftpException(SSH_FX_FAILURE, ""); } @@ -1946,7 +1947,7 @@ packet.reset(); putHEAD(SSH_FXP_INIT, 5); buf.putInt(3); // version 3 - session.write(packet, this, 5+4); + getSession().write(packet, this, 5+4); } private void sendREALPATH(byte[] path) throws Exception{ @@ -1967,7 +1968,7 @@ buf.putInt(seq++); buf.putString(path); // path attr.dump(buf); - session.write(packet, this, 9+path.length+attr.length()+4); + getSession().write(packet, this, 9+path.length+attr.length()+4); } private void sendREMOVE(byte[] path) throws Exception{ sendPacketPath(SSH_FXP_REMOVE, path); @@ -1979,7 +1980,7 @@ buf.putString(path); // path if(attr!=null) attr.dump(buf); else buf.putInt(0); - session.write(packet, this, 9+path.length+(attr!=null?attr.length():4)+4); + getSession().write(packet, this, 9+path.length+(attr!=null?attr.length():4)+4); } private void sendRMDIR(byte[] path) throws Exception{ sendPacketPath(SSH_FXP_RMDIR, path); @@ -2018,14 +2019,14 @@ buf.putString(path); buf.putInt(mode); buf.putInt(0); // attrs - session.write(packet, this, 17+path.length+4); + getSession().write(packet, this, 17+path.length+4); } private void sendPacketPath(byte fxp, byte[] path) throws Exception{ packet.reset(); putHEAD(fxp, 9+path.length); buf.putInt(seq++); buf.putString(path); // path - session.write(packet, this, 9+path.length+4); + getSession().write(packet, this, 9+path.length+4); } private void sendPacketPath(byte fxp, byte[] p1, byte[] p2) throws Exception{ packet.reset(); @@ -2033,7 +2034,7 @@ buf.putInt(seq++); buf.putString(p1); buf.putString(p2); - session.write(packet, this, 13+p1.length+p2.length+4); + getSession().write(packet, this, 13+p1.length+p2.length+4); } private int sendWRITE(byte[] handle, long offset, @@ -2060,7 +2061,7 @@ buf.putInt(_length); buf.skip(_length); } - session.write(packet, this, 21+handle.length+_length+4); + getSession().write(packet, this, 21+handle.length+_length+4); return _length; } @@ -2071,7 +2072,7 @@ buf.putString(handle); buf.putLong(offset); buf.putInt(length); - session.write(packet, this, 21+handle.length+4); + getSession().write(packet, this, 21+handle.length+4); } private void putHEAD(byte type, int length) throws Exception{ @@ -2157,7 +2158,7 @@ if(length>0){ buf.shift(); int j=(buf.buffer.length>(buf.index+length)) ? length : (buf.buffer.length-buf.index); - i=io.in.read(buf.buffer, buf.index, j); + i=io_in.read(buf.buffer, buf.index, j); if(i<=0)break; buf.index+=i; length-=i; @@ -2321,7 +2322,7 @@ int i=0; int foo=s; while(len>0){ - i=io.in.read(buf, s, len); + i=io_in.read(buf, s, len); if(i<=0){ throw new IOException("inputstream is closed"); //return (s-foo)==0 ? i : s-foo; @@ -2333,7 +2334,7 @@ } private void skip(long foo) throws IOException{ while(foo>0){ - long bar=io.in.skip(foo); + long bar=io_in.skip(foo); if(bar<=0) break; foo-=bar; @@ -2408,7 +2409,20 @@ return (String)extensions.get(key); } - public class LsEntry { + public String realpath(String path) throws SftpException{ + try{ + byte[] _path=_realpath(remoteAbsolutePath(path)); + return Util.byte2str(_path, fEncoding); + } + catch(Exception e){ + if(e instanceof SftpException) throw (SftpException)e; + if(e instanceof Throwable) + throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e); + throw new SftpException(SSH_FX_FAILURE, ""); + } + } + + public class LsEntry implements Comparable{ private String filename; private String longname; private SftpATTRS attrs; @@ -2424,5 +2438,11 @@ public SftpATTRS getAttrs(){return attrs;}; void setAttrs(SftpATTRS attrs) {this.attrs = attrs;}; public String toString(){ return longname; } + public int compareTo(Object o) throws ClassCastException{ + if(o instanceof LsEntry){ + return filename.compareTo(((LsEntry)o).getFilename()); + } + throw new ClassCastException("a decendent of LsEntry must be given."); + } } } diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ChannelShell.java jsch-0.1.41/src/com/jcraft/jsch/ChannelShell.java --- jsch-0.1.37/src/com/jcraft/jsch/ChannelShell.java 2008-01-21 08:46:33.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ChannelShell.java 2008-06-11 08:09:37.000000000 +0400 @@ -39,11 +39,12 @@ } public void start() throws JSchException{ + Session _session=getSession(); try{ sendRequests(); Request request=new RequestShell(); - request.request(session, this); + request.request(_session, this); } catch(Exception e){ if(e instanceof JSchException) throw (JSchException)e; @@ -54,16 +55,16 @@ if(io.in!=null){ thread=new Thread(this); - thread.setName("Shell for "+session.host); - if(session.daemon_thread){ - thread.setDaemon(session.daemon_thread); + thread.setName("Shell for "+_session.host); + if(_session.daemon_thread){ + thread.setDaemon(_session.daemon_thread); } thread.start(); } } - public void init(){ - io.setInputStream(session.in); - io.setOutputStream(session.out); + void init() throws JSchException { + io.setInputStream(getSession().in); + io.setOutputStream(getSession().out); } } diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ChannelSubsystem.java jsch-0.1.41/src/com/jcraft/jsch/ChannelSubsystem.java --- jsch-0.1.37/src/com/jcraft/jsch/ChannelSubsystem.java 2008-01-21 08:46:38.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ChannelSubsystem.java 2008-06-11 08:09:27.000000000 +0400 @@ -39,18 +39,19 @@ public void setWantReply(boolean foo){ want_reply=foo; } public void setSubsystem(String foo){ subsystem=foo; } public void start() throws JSchException{ + Session _session=getSession(); try{ Request request; if(xforwading){ request=new RequestX11(); - request.request(session, this); + request.request(_session, this); } if(pty){ request=new RequestPtyReq(); - request.request(session, this); + request.request(_session, this); } request=new RequestSubsystem(); - ((RequestSubsystem)request).request(session, this, subsystem, want_reply); + ((RequestSubsystem)request).request(_session, this, subsystem, want_reply); } catch(Exception e){ if(e instanceof JSchException){ throw (JSchException)e; } @@ -60,18 +61,19 @@ } if(io.in!=null){ thread=new Thread(this); - thread.setName("Subsystem for "+session.host); - if(session.daemon_thread){ - thread.setDaemon(session.daemon_thread); + thread.setName("Subsystem for "+_session.host); + if(_session.daemon_thread){ + thread.setDaemon(_session.daemon_thread); } thread.start(); } } - //public void finalize() throws Throwable{ super.finalize(); } - public void init(){ - io.setInputStream(session.in); - io.setOutputStream(session.out); + + void init() throws JSchException { + io.setInputStream(getSession().in); + io.setOutputStream(getSession().out); } + public void setErrStream(java.io.OutputStream out){ setExtOutputStream(out); } diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ChannelX11.java jsch-0.1.41/src/com/jcraft/jsch/ChannelX11.java --- jsch-0.1.37/src/com/jcraft/jsch/ChannelX11.java 2008-01-21 08:46:45.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ChannelX11.java 2008-06-11 08:03:15.000000000 +0400 @@ -163,7 +163,7 @@ buf.putInt(recipient); buf.putInt(i); buf.skip(i); - session.write(packet, this, i); + getSession().write(packet, this, i); } } catch(Exception e){ @@ -187,6 +187,14 @@ if(init){ + Session _session=null; + try{ + _session=getSession(); + } + catch(JSchException e){ + throw new java.io.IOException(e.toString()); + } + foo=addCache(foo, s, l); s=0; l=foo.length; @@ -215,7 +223,7 @@ byte[] faked_cookie=null; synchronized(faked_cookie_pool){ - faked_cookie=(byte[])faked_cookie_pool.get(session); + faked_cookie=(byte[])faked_cookie_pool.get(_session); } /* diff -Nru jsch-0.1.37/src/com/jcraft/jsch/IdentityFile.java jsch-0.1.41/src/com/jcraft/jsch/IdentityFile.java --- jsch-0.1.37/src/com/jcraft/jsch/IdentityFile.java 2008-01-21 08:47:55.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/IdentityFile.java 2008-11-18 22:57:47.000000000 +0300 @@ -172,6 +172,20 @@ i+=3; continue; } + if(buf[i]=='A'&& buf[i+1]=='E'&& buf[i+2]=='S'&& buf[i+3]=='-' && + buf[i+4]=='2'&& buf[i+5]=='5'&& buf[i+6]=='6'&& buf[i+7]=='-'){ + i+=8; + if(Session.checkCipher((String)jsch.getConfig("aes256-cbc"))){ + c=Class.forName((String)jsch.getConfig("aes256-cbc")); + cipher=(Cipher)(c.newInstance()); + key=new byte[cipher.getBlockSize()]; + iv=new byte[cipher.getIVSize()]; + } + else{ + throw new JSchException("privatekey: aes256-cbc is not available "+identity); + } + continue; + } if(buf[i]=='C'&& buf[i+1]=='B'&& buf[i+2]=='C'&& buf[i+3]==','){ i+=4; for(int ii=0; ii 8 ? 8: iv.length); tmp=hash.digest(); System.arraycopy(tmp, 0, hn, index, tmp.length); index+=tmp.length; diff -Nru jsch-0.1.37/src/com/jcraft/jsch/IO.java jsch-0.1.41/src/com/jcraft/jsch/IO.java --- jsch-0.1.37/src/com/jcraft/jsch/IO.java 2008-01-21 08:47:46.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/IO.java 2008-03-05 06:05:26.000000000 +0300 @@ -89,17 +89,23 @@ while (length>0); } - public void close(){ + void out_close(){ try{ - if(in!=null && !in_dontclose) in.close(); - in=null; + if(out!=null && !out_dontclose) out.close(); + out=null; } catch(Exception ee){} + } + + public void close(){ try{ - if(out!=null && !out_dontclose) out.close(); - out=null; + if(in!=null && !in_dontclose) in.close(); + in=null; } catch(Exception ee){} + + out_close(); + try{ if(out_ext!=null && !out_ext_dontclose) out_ext.close(); out_ext=null; diff -Nru jsch-0.1.37/src/com/jcraft/jsch/jce/AES128CTR.java jsch-0.1.41/src/com/jcraft/jsch/jce/AES128CTR.java --- jsch-0.1.37/src/com/jcraft/jsch/jce/AES128CTR.java 1970-01-01 03:00:00.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/jce/AES128CTR.java 2008-11-18 00:56:11.000000000 +0300 @@ -0,0 +1,71 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2005-2008 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.spec.*; + +public class AES128CTR implements Cipher{ + private static final int ivsize=16; + private static final int bsize=16; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + + try{ + SecretKeySpec keyspec=new SecretKeySpec(key, "AES"); + cipher=javax.crypto.Cipher.getInstance("AES/CTR/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + keyspec, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } +} diff -Nru jsch-0.1.37/src/com/jcraft/jsch/jce/AES192CTR.java jsch-0.1.41/src/com/jcraft/jsch/jce/AES192CTR.java --- jsch-0.1.37/src/com/jcraft/jsch/jce/AES192CTR.java 1970-01-01 03:00:00.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/jce/AES192CTR.java 2008-11-18 00:56:11.000000000 +0300 @@ -0,0 +1,70 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2005-2008 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.spec.*; + +public class AES192CTR implements Cipher{ + private static final int ivsize=16; + private static final int bsize=24; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + SecretKeySpec keyspec=new SecretKeySpec(key, "AES"); + cipher=javax.crypto.Cipher.getInstance("AES/CTR/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + keyspec, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } +} diff -Nru jsch-0.1.37/src/com/jcraft/jsch/jce/AES256CTR.java jsch-0.1.41/src/com/jcraft/jsch/jce/AES256CTR.java --- jsch-0.1.37/src/com/jcraft/jsch/jce/AES256CTR.java 1970-01-01 03:00:00.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/jce/AES256CTR.java 2008-11-18 00:56:11.000000000 +0300 @@ -0,0 +1,70 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2005-2008 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.spec.*; + +public class AES256CTR implements Cipher{ + private static final int ivsize=16; + private static final int bsize=32; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + SecretKeySpec keyspec=new SecretKeySpec(key, "AES"); + cipher=javax.crypto.Cipher.getInstance("AES/CTR/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + keyspec, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } +} diff -Nru jsch-0.1.37/src/com/jcraft/jsch/jce/ARCFOUR128.java jsch-0.1.41/src/com/jcraft/jsch/jce/ARCFOUR128.java --- jsch-0.1.37/src/com/jcraft/jsch/jce/ARCFOUR128.java 1970-01-01 03:00:00.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/jce/ARCFOUR128.java 2008-12-15 08:30:31.000000000 +0300 @@ -0,0 +1,70 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2008 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class ARCFOUR128 implements Cipher{ + private static final int ivsize=8; + private static final int bsize=16; + private static final int skip=1536; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + byte[] tmp; + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + cipher=javax.crypto.Cipher.getInstance("RC4"); + SecretKeySpec _key = new SecretKeySpec(key, "RC4"); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + _key); + byte[] foo=new byte[1]; + for(int i=0; ibsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + cipher=javax.crypto.Cipher.getInstance("RC4"); + SecretKeySpec _key = new SecretKeySpec(key, "RC4"); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + _key); + byte[] foo=new byte[1]; + for(int i=0; ibsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + + try{ + cipher=javax.crypto.Cipher.getInstance("RC4"); + SecretKeySpec _key = new SecretKeySpec(key, "RC4"); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + _key); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } +} diff -Nru jsch-0.1.37/src/com/jcraft/jsch/jce/TripleDESCTR.java jsch-0.1.41/src/com/jcraft/jsch/jce/TripleDESCTR.java --- jsch-0.1.37/src/com/jcraft/jsch/jce/TripleDESCTR.java 1970-01-01 03:00:00.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/jce/TripleDESCTR.java 2008-11-18 00:56:11.000000000 +0300 @@ -0,0 +1,83 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2008 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class TripleDESCTR implements Cipher{ + private static final int ivsize=8; + private static final int bsize=24; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + //if(padding) pad="PKCS5Padding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + + try{ + cipher=javax.crypto.Cipher.getInstance("DESede/CTR/"+pad); +/* + // The following code does not work on IBM's JDK 1.4.1 + SecretKeySpec skeySpec = new SecretKeySpec(key, "DESede"); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + skeySpec, new IvParameterSpec(iv)); +*/ + DESedeKeySpec keyspec=new DESedeKeySpec(key); + SecretKeyFactory keyfactory=SecretKeyFactory.getInstance("DESede"); + SecretKey _key=keyfactory.generateSecret(keyspec); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + _key, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } +} diff -Nru jsch-0.1.37/src/com/jcraft/jsch/JSch.java jsch-0.1.41/src/com/jcraft/jsch/JSch.java --- jsch-0.1.37/src/com/jcraft/jsch/JSch.java 2008-01-21 08:47:59.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/JSch.java 2008-12-15 08:30:57.000000000 +0300 @@ -41,9 +41,9 @@ // config.put("server_host_key", "ssh-dss,ssh-rsa"); config.put("cipher.s2c", - "aes128-cbc,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc"); + "aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc"); config.put("cipher.c2s", - "aes128-cbc,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc"); + "aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc"); config.put("mac.s2c", "hmac-md5,hmac-sha1,hmac-sha1-96,hmac-md5-96"); config.put("mac.c2s", "hmac-md5,hmac-sha1,hmac-sha1-96,hmac-md5-96"); @@ -82,8 +82,14 @@ config.put("aes128-cbc", "com.jcraft.jsch.jce.AES128CBC"); config.put("aes192-cbc", "com.jcraft.jsch.jce.AES192CBC"); config.put("aes256-cbc", "com.jcraft.jsch.jce.AES256CBC"); -// config.put("cipher.s2c", "aes128-cbc,3des-cbc,blowfish-cbc"); -// config.put("cipher.c2s", "aes128-cbc,3des-cbc,blowfish-cbc"); + + config.put("aes128-ctr", "com.jcraft.jsch.jce.AES128CTR"); + config.put("aes192-ctr", "com.jcraft.jsch.jce.AES192CTR"); + config.put("aes256-ctr", "com.jcraft.jsch.jce.AES256CTR"); + config.put("3des-ctr", "com.jcraft.jsch.jce.TripleDESCTR"); + config.put("arcfour", "com.jcraft.jsch.jce.ARCFOUR"); + config.put("arcfour128", "com.jcraft.jsch.jce.ARCFOUR128"); + config.put("arcfour256", "com.jcraft.jsch.jce.ARCFOUR256"); config.put("userauth.none", "com.jcraft.jsch.UserAuthNone"); config.put("userauth.password", "com.jcraft.jsch.UserAuthPassword"); @@ -100,7 +106,7 @@ //config.put("HashKnownHosts", "yes"); config.put("PreferredAuthentications", "gssapi-with-mic,publickey,keyboard-interactive,password"); - config.put("CheckCiphers", "aes256-cbc,aes192-cbc,aes128-cbc"); + config.put("CheckCiphers", "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256"); } java.util.Vector pool=new java.util.Vector(); java.util.Vector identities=new java.util.Vector(); @@ -263,8 +269,10 @@ } } - String getConfig(String key){ - return (String)(config.get(key)); + public static String getConfig(String key){ + synchronized(config){ + return (String)(config.get(key)); + } } public static void setConfig(java.util.Hashtable newconf){ diff -Nru jsch-0.1.37/src/com/jcraft/jsch/ProxySOCKS4.java jsch-0.1.41/src/com/jcraft/jsch/ProxySOCKS4.java --- jsch-0.1.37/src/com/jcraft/jsch/ProxySOCKS4.java 2008-01-21 08:49:29.000000000 +0300 +++ jsch-0.1.41/src/com/jcraft/jsch/ProxySOCKS4.java 2008-09-26 01:46:57.000000000 +0400 @@ -161,7 +161,7 @@ The remaining fields are ignored. */ - int len=6; + int len=8; int s=0; while(s0 && buf.buffer[i-1]==13){ // 0x0d i--; } } - if(i>4 && (i!=buf.buffer.length) && - (buf.buffer[0]!='S'||buf.buffer[1]!='S'|| - buf.buffer[2]!='H'||buf.buffer[3]!='-')){ + if(i<=3 || + ((i!=buf.buffer.length) && + (buf.buffer[0]!='S'||buf.buffer[1]!='S'|| + buf.buffer[2]!='H'||buf.buffer[3]!='-'))){ + // It must not start with 'SSH-' //System.err.println(new String(buf.buffer, 0, i); continue; } @@ -454,12 +457,21 @@ } isAuthed=true; - connectThread=new Thread(this); - connectThread.setName("Connect thread "+host+" session"); - if(daemon_thread){ - connectThread.setDaemon(daemon_thread); + + synchronized(lock){ + if(isConnected){ + connectThread=new Thread(this); + connectThread.setName("Connect thread "+host+" session"); + if(daemon_thread){ + connectThread.setDaemon(daemon_thread); + } + connectThread.start(); + } + else{ + // The session has been already down and + // we don't have to start new thread. + } } - connectThread.start(); } catch(Exception e) { in_kex=false; @@ -497,7 +509,11 @@ else{ I_S=new byte[j-1-buf.getByte()]; } - System.arraycopy(buf.buffer, buf.s, I_S, 0, I_S.length); + System.arraycopy(buf.buffer, buf.s, I_S, 0, I_S.length); + + if(!in_kex){ // We are in rekeying activated by the remote! + send_kexinit(); + } guess=KeyExchange.guess(I_S, I_C); if(guess==null){ @@ -812,6 +828,22 @@ System.arraycopy(buf.buffer, 0, foo, 0, buf.index); buf.buffer=foo; } + + if((j%s2ccipher_size)!=0){ + String message="Bad packet length "+j; + if(JSch.getLogger().isEnabled(Logger.FATAL)){ + JSch.getLogger().log(Logger.FATAL, message); + } + packet.reset(); + buf.putByte((byte)SSH_MSG_DISCONNECT); + buf.putInt(3); + buf.putString(message.getBytes()); + buf.putString("en".getBytes()); + write(packet); + disconnect(); + throw new JSchException("SSH_MSG_DISCONNECT: "+message); + } + if(j>0){ io.getByte(buf.buffer, buf.index, j); buf.index+=(j); if(s2ccipher!=null){ @@ -855,8 +887,8 @@ int reason_code=buf.getInt(); byte[] description=buf.getString(); byte[] language_tag=buf.getString(); - throw new JSchException("SSH_MSG_DISCONNECT:"+ - " "+reason_code+ + throw new JSchException("SSH_MSG_DISCONNECT: "+ + reason_code+ " "+new String(description)+ " "+new String(language_tag)); //break; @@ -1129,12 +1161,15 @@ } _write(packet); } - private synchronized void _write(Packet packet) throws Exception{ - encode(packet); - if(io!=null){ - io.put(packet); - seqo++; - } + + private void _write(Packet packet) throws Exception{ + synchronized(lock){ + encode(packet); + if(io!=null){ + io.put(packet); + seqo++; + } + } } Runnable thread; @@ -1481,10 +1516,12 @@ PortWatcher.delPort(this); ChannelForwardedTCPIP.delPort(this); - synchronized(connectThread){ - Thread.yield(); - connectThread.interrupt(); - connectThread=null; + synchronized(lock){ + if(connectThread!=null){ + Thread.yield(); + connectThread.interrupt(); + connectThread=null; + } } thread=null; try{ @@ -1554,7 +1591,7 @@ setPortForwardingR(null, rport, host, lport, sf); } public void setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf) throws JSchException{ - ChannelForwardedTCPIP.addPort(this, rport, host, lport, sf); + ChannelForwardedTCPIP.addPort(this, bind_address, rport, host, lport, sf); setPortForwarding(bind_address, rport); } @@ -1565,7 +1602,7 @@ setPortForwardingR(null, rport, daemon, arg); } public void setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg) throws JSchException{ - ChannelForwardedTCPIP.addPort(this, rport, daemon, arg); + ChannelForwardedTCPIP.addPort(this, bind_address, rport, daemon, arg); setPortForwarding(bind_address, rport); } @@ -1586,17 +1623,7 @@ Buffer buf=new Buffer(100); // ?? Packet packet=new Packet(buf); - String address_to_bind="localhost"; - if(bind_address==null){ - //address_to_bind="localhost"; - } - else if(bind_address.length()==0 || - bind_address.equals("*")){ - address_to_bind=""; - } - else{ - address_to_bind=bind_address; - } + String address_to_bind=ChannelForwardedTCPIP.normalize(bind_address); try{ // byte SSH_MSG_GLOBAL_REQUEST 80 @@ -1610,7 +1637,6 @@ // buf.putByte((byte)0); buf.putByte((byte)1); buf.putString(address_to_bind.getBytes()); - //buf.putString("0.0.0.0".getBytes()); buf.putInt(rport); write(packet); } @@ -1682,10 +1708,9 @@ } void addChannel(Channel channel){ - channel.session=this; + channel.setSession(this); } -// public Channel getChannel(){ return channel; } public void setProxy(Proxy proxy){ this.proxy=proxy; } public void setHost(String host){ this.host=host; } public void setPort(int port){ this.port=port; } @@ -1712,20 +1737,24 @@ setConfig((java.util.Hashtable)newconf); } - public synchronized void setConfig(java.util.Hashtable newconf){ - if(config==null) - config=new java.util.Hashtable(); - for(java.util.Enumeration e=newconf.keys() ; e.hasMoreElements() ;) { - String key=(String)(e.nextElement()); - config.put(key, (String)(newconf.get(key))); + public void setConfig(java.util.Hashtable newconf){ + synchronized(lock){ + if(config==null) + config=new java.util.Hashtable(); + for(java.util.Enumeration e=newconf.keys() ; e.hasMoreElements() ;) { + String key=(String)(e.nextElement()); + config.put(key, (String)(newconf.get(key))); + } } } - public synchronized void setConfig(String key, String value){ - if(config==null){ - config=new java.util.Hashtable(); + public void setConfig(String key, String value){ + synchronized(lock){ + if(config==null){ + config=new java.util.Hashtable(); + } + config.put(key, value); } - config.put(key, value); } public String getConfig(String key){ @@ -1802,6 +1831,7 @@ public String getHostKeyAlias(){ return hostKeyAlias; } + public void setServerAliveInterval(int interval) throws JSchException { setTimeout(interval); this.serverAliveInterval=interval; @@ -1809,6 +1839,14 @@ public void setServerAliveCountMax(int count){ this.serverAliveCountMax=count; } + + public int getServerAliveInterval(){ + return this.serverAliveInterval; + } + public int getServerAliveCountMax(){ + return this.serverAliveCountMax; + } + public void setDaemonThread(boolean enable){ this.daemon_thread=enable; } @@ -1825,14 +1863,7 @@ java.util.Vector result=new java.util.Vector(); String[] _ciphers=Util.split(ciphers, ","); for(int i=0; i<_ciphers.length; i++){ - try{ - Class c=Class.forName(getConfig(_ciphers[i])); - Cipher _c=(Cipher)(c.newInstance()); - _c.init(Cipher.ENCRYPT_MODE, - new byte[_c.getBlockSize()], - new byte[_c.getIVSize()]); - } - catch(Exception e){ + if(!checkCipher(getConfig(_ciphers[i]))){ result.addElement(_ciphers[i]); } } @@ -1850,4 +1881,18 @@ return foo; } + + static boolean checkCipher(String cipher){ + try{ + Class c=Class.forName(cipher); + Cipher _c=(Cipher)(c.newInstance()); + _c.init(Cipher.ENCRYPT_MODE, + new byte[_c.getBlockSize()], + new byte[_c.getIVSize()]); + return true; + } + catch(Exception e){ + return false; + } + } }