diff --git a/src/main/java/com/jcraft/jsch/Channel.java b/src/main/java/com/jcraft/jsch/Channel.java index 479bf74a..0e6da7c2 100644 --- a/src/main/java/com/jcraft/jsch/Channel.java +++ b/src/main/java/com/jcraft/jsch/Channel.java @@ -45,38 +45,43 @@ public abstract class Channel implements Runnable{ static int index=0; private static Vector pool=new Vector<>(); - static Channel getChannel(String type){ + static Channel getChannel(String type, Session session){ + Channel ret = null; if(type.equals("session")){ - return new ChannelSession(); + ret = new ChannelSession(); } if(type.equals("shell")){ - return new ChannelShell(); + ret = new ChannelShell(); } if(type.equals("exec")){ - return new ChannelExec(); + ret = new ChannelExec(); } if(type.equals("x11")){ - return new ChannelX11(); + ret = new ChannelX11(); } if(type.equals("auth-agent@openssh.com")){ - return new ChannelAgentForwarding(); + ret = new ChannelAgentForwarding(); } if(type.equals("direct-tcpip")){ - return new ChannelDirectTCPIP(); + ret = new ChannelDirectTCPIP(); } if(type.equals("forwarded-tcpip")){ - return new ChannelForwardedTCPIP(); + ret = new ChannelForwardedTCPIP(); } if(type.equals("sftp")){ - return new ChannelSftp(); + ret = new ChannelSftp(); } if(type.equals("subsystem")){ - return new ChannelSubsystem(); + ret = new ChannelSubsystem(); } if(type.equals("direct-streamlocal@openssh.com")){ - return new ChannelDirectStreamLocal(); + ret = new ChannelDirectStreamLocal(); } - return null; + if (ret == null) { + return null; + } + ret.setSession(session); + return ret; } static Channel getChannel(int id, Session session){ synchronized(pool){ @@ -118,7 +123,7 @@ static void del(Channel c){ volatile int reply=0; volatile int connectTimeout=0; - private Session session; + protected Session session; int notifyme=0; diff --git a/src/main/java/com/jcraft/jsch/ChannelDirectStreamLocal.java b/src/main/java/com/jcraft/jsch/ChannelDirectStreamLocal.java index 351ab7d9..7ace8095 100644 --- a/src/main/java/com/jcraft/jsch/ChannelDirectStreamLocal.java +++ b/src/main/java/com/jcraft/jsch/ChannelDirectStreamLocal.java @@ -27,7 +27,7 @@ public class ChannelDirectStreamLocal extends ChannelDirectTCPIP { protected Packet genChannelOpenPacket() { if (socketPath == null) { - JSch.getLogger().log(Logger.FATAL, "socketPath must be set"); + session.getLogger().log(Logger.FATAL, "socketPath must be set"); throw new RuntimeException("socketPath must be set"); } diff --git a/src/main/java/com/jcraft/jsch/ChannelForwardedTCPIP.java b/src/main/java/com/jcraft/jsch/ChannelForwardedTCPIP.java index 396b0265..0210e059 100644 --- a/src/main/java/com/jcraft/jsch/ChannelForwardedTCPIP.java +++ b/src/main/java/com/jcraft/jsch/ChannelForwardedTCPIP.java @@ -159,8 +159,8 @@ void getData(Buffer buf){ this.config = getPort(_session, null, port); if(this.config == null){ - if(JSch.getLogger().isEnabled(Logger.ERROR)){ - JSch.getLogger().log(Logger.ERROR, + if(_session.getLogger().isEnabled(Logger.ERROR)){ + _session.getLogger().log(Logger.ERROR, "ChannelForwardedTCPIP: "+Util.byte2str(addr)+":"+port+" is not registered."); } } diff --git a/src/main/java/com/jcraft/jsch/Compression.java b/src/main/java/com/jcraft/jsch/Compression.java index 30598e9e..3cefd238 100644 --- a/src/main/java/com/jcraft/jsch/Compression.java +++ b/src/main/java/com/jcraft/jsch/Compression.java @@ -33,6 +33,9 @@ public interface Compression{ static public final int INFLATER=0; static public final int DEFLATER=1; void init(int type, int level) throws Exception; + default void init(int type, int level, Session session) throws Exception { + init(type, level); + } byte[] compress(byte[] buf, int start, int[] len); byte[] uncompress(byte[] buf, int start, int[] len); } diff --git a/src/main/java/com/jcraft/jsch/DHECN.java b/src/main/java/com/jcraft/jsch/DHECN.java index d7aa59d2..4bc00237 100644 --- a/src/main/java/com/jcraft/jsch/DHECN.java +++ b/src/main/java/com/jcraft/jsch/DHECN.java @@ -55,7 +55,6 @@ public abstract class DHECN extends KeyExchange{ @Override public void init(Session session, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{ - this.session=session; this.V_S=V_S; this.V_C=V_C; this.I_S=I_S; @@ -94,10 +93,10 @@ public void init(Session session, session.write(packet); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "SSH_MSG_KEX_ECDH_INIT sent"); - JSch.getLogger().log(Logger.INFO, + session.getLogger().log(Logger.INFO, "expecting SSH_MSG_KEX_ECDH_REPLY"); } diff --git a/src/main/java/com/jcraft/jsch/DHGEX.java b/src/main/java/com/jcraft/jsch/DHGEX.java index 7f6ce943..96b02b18 100644 --- a/src/main/java/com/jcraft/jsch/DHGEX.java +++ b/src/main/java/com/jcraft/jsch/DHGEX.java @@ -61,7 +61,6 @@ public class DHGEX extends KeyExchange{ @Override public void init(Session session, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{ - this.session=session; this.V_S=V_S; this.V_C=V_C; this.I_S=I_S; @@ -101,10 +100,10 @@ public void init(Session session, buf.putInt(max); session.write(packet); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "SSH_MSG_KEX_DH_GEX_REQUEST("+min+"<"+preferred+"<"+max+") sent"); - JSch.getLogger().log(Logger.INFO, + session.getLogger().log(Logger.INFO, "expecting SSH_MSG_KEX_DH_GEX_GROUP"); } @@ -144,10 +143,10 @@ public boolean next(Buffer _buf) throws Exception{ buf.putMPInt(e); session.write(packet); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "SSH_MSG_KEX_DH_GEX_INIT sent"); - JSch.getLogger().log(Logger.INFO, + session.getLogger().log(Logger.INFO, "expecting SSH_MSG_KEX_DH_GEX_REPLY"); } diff --git a/src/main/java/com/jcraft/jsch/DHGN.java b/src/main/java/com/jcraft/jsch/DHGN.java index 4e7e7cc7..8953705d 100644 --- a/src/main/java/com/jcraft/jsch/DHGN.java +++ b/src/main/java/com/jcraft/jsch/DHGN.java @@ -55,7 +55,6 @@ public abstract class DHGN extends KeyExchange{ @Override public void init(Session session, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{ - this.session=session; this.V_S=V_S; this.V_C=V_C; this.I_S=I_S; @@ -101,10 +100,10 @@ public void init(Session session, session.write(packet); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "SSH_MSG_KEXDH_INIT sent"); - JSch.getLogger().log(Logger.INFO, + session.getLogger().log(Logger.INFO, "expecting SSH_MSG_KEXDH_REPLY"); } diff --git a/src/main/java/com/jcraft/jsch/DHXEC.java b/src/main/java/com/jcraft/jsch/DHXEC.java index c64911a1..4f838f49 100644 --- a/src/main/java/com/jcraft/jsch/DHXEC.java +++ b/src/main/java/com/jcraft/jsch/DHXEC.java @@ -60,7 +60,6 @@ public abstract class DHXEC extends KeyExchange{ @Override public void init(Session session, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{ - this.session=session; this.V_S=V_S; this.V_C=V_C; this.I_S=I_S; @@ -99,10 +98,10 @@ public void init(Session session, session.write(packet); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "SSH_MSG_KEX_ECDH_INIT sent"); - JSch.getLogger().log(Logger.INFO, + session.getLogger().log(Logger.INFO, "expecting SSH_MSG_KEX_ECDH_REPLY"); } diff --git a/src/main/java/com/jcraft/jsch/JSch.java b/src/main/java/com/jcraft/jsch/JSch.java index cd619f75..de926479 100644 --- a/src/main/java/com/jcraft/jsch/JSch.java +++ b/src/main/java/com/jcraft/jsch/JSch.java @@ -280,13 +280,14 @@ public void setConfigRepository(ConfigRepository configRepository) { private HostKeyRepository known_hosts=null; - private static final Logger DEVNULL=new Logger(){ + static final Logger DEVNULL=new Logger(){ @Override public boolean isEnabled(int level){return false;} @Override public void log(int level, String message){} }; static Logger logger=DEVNULL; + private Logger instLogger; public JSch(){ } @@ -673,7 +674,8 @@ public static void setConfig(String key, String value){ /** * Sets the logger * - * @param logger logger + * @param logger logger or null if no logging + * should take place * * @see com.jcraft.jsch.Logger */ @@ -681,7 +683,33 @@ public static void setLogger(Logger logger){ if(logger==null) logger=DEVNULL; JSch.logger=logger; } - + + /** + * Returns a logger to be used for this particular instance of JSch + * @return The logger that is used by this instance. If no particular + * logger has been set, the statically set logger is returned. + */ + public Logger getInstanceLogger() { + if (this.instLogger == null) { + return logger; + } + return instLogger; + } + + /** + * Sets a logger to be used for this particular instance of JSch + * @param logger The logger to be used or null if + * the statically set logger should be used + */ + public void setInstanceLogger(Logger logger) { + this.instLogger = logger; + } + + /** + * Returns the statically set logger, i.e. the logger being + * used by all JSch instances without explicitly set logger. + * @return The logger + */ public static Logger getLogger(){ return logger; } diff --git a/src/main/java/com/jcraft/jsch/KeyExchange.java b/src/main/java/com/jcraft/jsch/KeyExchange.java index efc8f2bf..6e1c0eac 100644 --- a/src/main/java/com/jcraft/jsch/KeyExchange.java +++ b/src/main/java/com/jcraft/jsch/KeyExchange.java @@ -69,6 +69,11 @@ public abstract class KeyExchange{ public abstract void init(Session session, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception; + void doInit(Session session, + byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception { + this.session = session; + init(session, V_S, V_C, I_S, I_C); + } public abstract boolean next(Buffer buf) throws Exception; public abstract int getState(); @@ -96,13 +101,13 @@ protected static String[] guess(Session session, byte[]I_S, byte[]I_C) throws Ex Buffer sb=new Buffer(I_S); sb.setOffSet(17); Buffer cb=new Buffer(I_C); cb.setOffSet(17); - if(JSch.getLogger().isEnabled(Logger.INFO)){ + if(session.getLogger().isEnabled(Logger.INFO)){ for(int i=0; iclient"+ " cipher: "+guess[PROPOSAL_ENC_ALGS_STOC]+ " MAC: "+(_s2cAEAD?(""):(guess[PROPOSAL_MAC_ALGS_STOC]))+ " compression: "+guess[PROPOSAL_COMP_ALGS_STOC]); - JSch.getLogger().log(Logger.INFO, + session.getLogger().log(Logger.INFO, "kex: client->server"+ " cipher: "+guess[PROPOSAL_ENC_ALGS_CTOS]+ " MAC: "+(_c2sAEAD?(""):(guess[PROPOSAL_MAC_ALGS_CTOS]))+ @@ -255,8 +260,8 @@ protected boolean verify(String alg, byte[] K_S, int index, sig.update(H); result=sig.verify(sig_of_H); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "ssh_rsa_verify: "+foo+" signature "+result); } } @@ -300,8 +305,8 @@ else if(alg.equals("ssh-dss")){ sig.update(H); result=sig.verify(sig_of_H); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "ssh_dss_verify: signature "+result); } } @@ -345,8 +350,8 @@ else if(alg.equals("ecdsa-sha2-nistp256") || result=sig.verify(sig_of_H); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "ssh_ecdsa_verify: "+alg+" signature "+result); } } @@ -378,8 +383,8 @@ else if(alg.equals("ssh-ed25519") || result=sig.verify(sig_of_H); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "ssh_eddsa_verify: "+alg+" signature "+result); } } diff --git a/src/main/java/com/jcraft/jsch/KeyPairDeferred.java b/src/main/java/com/jcraft/jsch/KeyPairDeferred.java index 2f8c7d1b..0c52be60 100644 --- a/src/main/java/com/jcraft/jsch/KeyPairDeferred.java +++ b/src/main/java/com/jcraft/jsch/KeyPairDeferred.java @@ -28,7 +28,7 @@ public boolean decrypt(byte[] _passphrase) { return true; } if (_passphrase == null) { - JSch.getLogger().log(Logger.ERROR, "no passphrase set."); + jsch.getInstanceLogger().log(Logger.ERROR, "no passphrase set."); return false; } diff --git a/src/main/java/com/jcraft/jsch/KeyPairPKCS8.java b/src/main/java/com/jcraft/jsch/KeyPairPKCS8.java index 9ad72401..4e51a88e 100644 --- a/src/main/java/com/jcraft/jsch/KeyPairPKCS8.java +++ b/src/main/java/com/jcraft/jsch/KeyPairPKCS8.java @@ -370,7 +370,7 @@ else if(Util.array_equals(id, aes256cbc)){ cipher=c.getDeclaredConstructor().newInstance(); } catch(Exception e){ - if(JSch.getLogger().isEnabled(Logger.FATAL)){ + if(jsch.getInstanceLogger().isEnabled(Logger.FATAL)){ String message=""; if(name==null){ message="unknown oid: "+Util.toHex(id); @@ -378,7 +378,7 @@ else if(Util.array_equals(id, aes256cbc)){ else { message="function "+name+" is not supported"; } - JSch.getLogger().log(Logger.FATAL, "PKCS8: "+message); + jsch.getInstanceLogger().log(Logger.FATAL, "PKCS8: "+message); } } return cipher; diff --git a/src/main/java/com/jcraft/jsch/PortWatcher.java b/src/main/java/com/jcraft/jsch/PortWatcher.java index fc244341..81632df6 100644 --- a/src/main/java/com/jcraft/jsch/PortWatcher.java +++ b/src/main/java/com/jcraft/jsch/PortWatcher.java @@ -201,6 +201,7 @@ public void run(){ OutputStream out=socket.getOutputStream(); if(socketPath!=null && socketPath.length()>0){ ChannelDirectStreamLocal channel = new ChannelDirectStreamLocal(); + channel.setSession(session); channel.init(); channel.setInputStream(in); channel.setOutputStream(out); @@ -211,6 +212,7 @@ public void run(){ channel.connect(connectTimeout); } else { ChannelDirectTCPIP channel = new ChannelDirectTCPIP(); + channel.setSession(session); channel.init(); channel.setInputStream(in); channel.setOutputStream(out); diff --git a/src/main/java/com/jcraft/jsch/Session.java b/src/main/java/com/jcraft/jsch/Session.java index 0e295517..3ee69c4d 100644 --- a/src/main/java/com/jcraft/jsch/Session.java +++ b/src/main/java/com/jcraft/jsch/Session.java @@ -34,7 +34,15 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING import java.io.InterruptedIOException; import java.io.OutputStream; import java.net.Socket; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Vector; + import javax.crypto.AEADBadTagException; public class Session implements Runnable{ @@ -73,7 +81,7 @@ public class Session implements Runnable{ private static final int PACKET_MAX_SIZE = 256 * 1024; private byte[] V_S; // server version - private byte[] V_C=Util.str2byte("SSH-2.0-JSCH_"+Version.getVersion()); // client version + private byte[] V_C=Util.str2byte("SSH-2.0-JSCH_"+JSch.VERSION); // client version private byte[] I_C; // the payload of the client's SSH_MSG_KEXINIT private byte[] I_S; // the payload of the server's SSH_MSG_KEXINIT @@ -160,6 +168,7 @@ public class Session implements Runnable{ byte[] password=null; JSch jsch; + Logger logger; Session(JSch jsch, String username, String host, int port) throws JSchException{ super(); @@ -202,8 +211,8 @@ public void connect(int connectTimeout) throws JSchException{ } Packet.setRandom(random); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Connecting to "+host+" port "+port); } @@ -243,8 +252,8 @@ public void connect(int connectTimeout) throws JSchException{ isConnected=true; - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Connection established"); } @@ -302,10 +311,10 @@ public void connect(int connectTimeout) throws JSchException{ String _v_s=Util.byte2str(V_S); sshBugSigType74=_v_s.startsWith("SSH-2.0-OpenSSH_7.4"); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Remote version string: "+_v_s); - JSch.getLogger().log(Logger.INFO, + getLogger().log(Logger.INFO, "Local version string: "+Util.byte2str(V_C)); } @@ -317,8 +326,8 @@ public void connect(int connectTimeout) throws JSchException{ throw new JSchException("invalid protocol: "+buf.getCommand()); } - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "SSH_MSG_KEXINIT received"); } @@ -364,8 +373,8 @@ public void connect(int connectTimeout) throws JSchException{ //System.err.println("read: 21 ? "+buf.getCommand()); if(buf.getCommand()==SSH_MSG_NEWKEYS){ - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "SSH_MSG_NEWKEYS received"); } @@ -441,16 +450,16 @@ public void connect(int connectTimeout) throws JSchException{ //System.err.println(" method: "+method); - if(JSch.getLogger().isEnabled(Logger.INFO)){ + if(getLogger().isEnabled(Logger.INFO)){ String str="Authentications that can continue: "; for(int k=methodi-1; k= max_auth_tries){ - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Login trials exceeds "+max_auth_tries); } } - if(auth_cancel) - throw new JSchException("Auth cancel"); - throw new JSchException("Auth fail"); + throw new JSchException((auth_cancel ? "Auth cancel" + : "Auth fail") + + " for methods '" + smethods + "'"); } if(socket!=null && (connectTimeout>0 || timeout>0)){ @@ -615,7 +624,7 @@ private KeyExchange receive_kexinit(Buffer buf) throws Exception { throw new JSchException(e.toString(), e); } - kex.init(this, V_S, V_C, I_S, I_C); + kex.doInit(this, V_S, V_C, I_S, I_C); return kex; } @@ -636,10 +645,10 @@ private void send_kexinit() throws Exception { String ciphers2c=getConfig("cipher.s2c"); String[] not_available_ciphers=checkCiphers(getConfig("CheckCiphers")); if(not_available_ciphers!=null && not_available_ciphers.length>0){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "cipher.c2s proposal before removing unavailable algos is: " + cipherc2s); - JSch.getLogger().log(Logger.DEBUG, + getLogger().log(Logger.DEBUG, "cipher.s2c proposal before removing unavailable algos is: " + ciphers2c); } @@ -649,10 +658,10 @@ private void send_kexinit() throws Exception { throw new JSchException("There are not any available ciphers."); } - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "cipher.c2s proposal after removing unavailable algos is: " + cipherc2s); - JSch.getLogger().log(Logger.DEBUG, + getLogger().log(Logger.DEBUG, "cipher.s2c proposal after removing unavailable algos is: " + ciphers2c); } } @@ -661,10 +670,10 @@ private void send_kexinit() throws Exception { String macs2c=getConfig("mac.s2c"); String[] not_available_macs=checkMacs(getConfig("CheckMacs")); if(not_available_macs!=null && not_available_macs.length>0){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "mac.c2s proposal before removing unavailable algos is: " + macc2s); - JSch.getLogger().log(Logger.DEBUG, + getLogger().log(Logger.DEBUG, "mac.s2c proposal before removing unavailable algos is: " + macs2c); } @@ -674,10 +683,10 @@ private void send_kexinit() throws Exception { throw new JSchException("There are not any available macs."); } - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "mac.c2s proposal after removing unavailable algos is: " + macc2s); - JSch.getLogger().log(Logger.DEBUG, + getLogger().log(Logger.DEBUG, "mac.s2c proposal after removing unavailable algos is: " + macs2c); } } @@ -685,8 +694,8 @@ private void send_kexinit() throws Exception { String kex=getConfig("kex"); String[] not_available_kexes=checkKexes(getConfig("CheckKexes")); if(not_available_kexes!=null && not_available_kexes.length>0){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "kex proposal before removing unavailable algos is: " + kex); } @@ -695,8 +704,8 @@ private void send_kexinit() throws Exception { throw new JSchException("There are not any available kexes."); } - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "kex proposal after removing unavailable algos is: " + kex); } } @@ -712,8 +721,8 @@ private void send_kexinit() throws Exception { // Cache for UserAuthPublicKey this.not_available_shks = not_available_shks; if(not_available_shks!=null && not_available_shks.length>0){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "server_host_key proposal before removing unavailable algos is: " + server_host_key); } @@ -722,16 +731,16 @@ private void send_kexinit() throws Exception { throw new JSchException("There are not any available sig algorithm."); } - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "server_host_key proposal after removing unavailable algos is: " + server_host_key); } } String prefer_hkr=getConfig("prefer_known_host_key_types"); if(prefer_hkr.equals("yes")){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "server_host_key proposal before known_host reordering is: " + server_host_key); } @@ -770,8 +779,8 @@ private void send_kexinit() throws Exception { } } - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(getLogger().isEnabled(Logger.DEBUG)){ + getLogger().log(Logger.DEBUG, "server_host_key proposal after known_host reordering is: " + server_host_key); } } @@ -817,8 +826,8 @@ private void send_kexinit() throws Exception { write(packet); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "SSH_MSG_KEXINIT sent"); } } @@ -829,8 +838,8 @@ private void send_newkeys() throws Exception { buf.putByte((byte)SSH_MSG_NEWKEYS); write(packet); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "SSH_MSG_NEWKEYS sent"); } } @@ -953,8 +962,8 @@ private void checkHost(String chost, int port, KeyExchange kex) throws JSchExcep "This could mean that a stolen key is being used to "+ "impersonate this host."); } - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Host '"+host+"' has provided revoked key."); } throw new JSchException("revoked HostKey: "+host); @@ -963,14 +972,14 @@ private void checkHost(String chost, int port, KeyExchange kex) throws JSchExcep } if(i==HostKeyRepository.OK && - JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Host '"+host+"' is known and matches the "+key_type+" host key"); } if(insert && - JSch.getLogger().isEnabled(Logger.WARN)){ - JSch.getLogger().log(Logger.WARN, + getLogger().isEnabled(Logger.WARN)){ + getLogger().log(Logger.WARN, "Permanently added '"+host+"' ("+key_type+") to the list of known hosts."); } @@ -988,7 +997,7 @@ public Channel openChannel(String type) throws JSchException{ throw new JSchException("session is down"); } try{ - Channel channel=Channel.getChannel(type); + Channel channel=Channel.getChannel(type, this); addChannel(channel); channel.init(); if(channel instanceof ChannelSession){ @@ -1100,8 +1109,8 @@ public Buffer read(Buffer buf) throws Exception{ if((j%s2ccipher_size)!=0){ String message="Bad packet length "+j; - if(JSch.getLogger().isEnabled(Logger.FATAL)){ - JSch.getLogger().log(Logger.FATAL, message); + if(getLogger().isEnabled(Logger.FATAL)){ + getLogger().log(Logger.FATAL, message); } start_discard(buf, s2ccipher, s2cmac, 0, PACKET_MAX_SIZE-s2ccipher_size); } @@ -1140,8 +1149,8 @@ else if(isAEAD || isEtM){ if((j%s2ccipher_size)!=0){ String message="Bad packet length "+j; - if(JSch.getLogger().isEnabled(Logger.FATAL)){ - JSch.getLogger().log(Logger.FATAL, message); + if(getLogger().isEnabled(Logger.FATAL)){ + getLogger().log(Logger.FATAL, message); } start_discard(buf, s2ccipher, s2cmac, 0, PACKET_MAX_SIZE-s2ccipher_size); } @@ -1197,8 +1206,8 @@ else if(isAEAD || isEtM){ if((need%s2ccipher_size)!=0){ String message="Bad packet length "+need; - if(JSch.getLogger().isEnabled(Logger.FATAL)){ - JSch.getLogger().log(Logger.FATAL, message); + if(getLogger().isEnabled(Logger.FATAL)){ + getLogger().log(Logger.FATAL, message); } start_discard(buf, s2ccipher, s2cmac, 0, PACKET_MAX_SIZE-s2ccipher_size); } @@ -1263,8 +1272,8 @@ else if(type==SSH_MSG_UNIMPLEMENTED){ buf.rewind(); buf.getInt();buf.getShort(); int reason_id=buf.getInt(); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Received SSH_MSG_UNIMPLEMENTED for "+reason_id); } } @@ -1297,25 +1306,25 @@ else if(type==SSH_MSG_EXT_INFO){ String enable_server_sig_algs=getConfig("enable_server_sig_algs"); if(!enable_server_sig_algs.equals("yes")){ ignore=true; - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, "Ignoring SSH_MSG_EXT_INFO while enable_server_sig_algs != yes"); + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Ignoring SSH_MSG_EXT_INFO while enable_server_sig_algs != yes"); } } else if(isAuthed){ ignore=true; - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, "Ignoring SSH_MSG_EXT_INFO received after SSH_MSG_USERAUTH_SUCCESS"); + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Ignoring SSH_MSG_EXT_INFO received after SSH_MSG_USERAUTH_SUCCESS"); } } else if(in_kex){ ignore=true; - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, "Ignoring SSH_MSG_EXT_INFO received before SSH_MSG_NEWKEYS"); + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "Ignoring SSH_MSG_EXT_INFO received before SSH_MSG_NEWKEYS"); } } else{ - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, "SSH_MSG_EXT_INFO received"); + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "SSH_MSG_EXT_INFO received"); } } long num_extensions=buf.getUInt(); @@ -1324,8 +1333,8 @@ else if(in_kex){ byte[] ext_value=buf.getString(); if(!ignore && Util.byte2str(ext_name).equals("server-sig-algs")){ String foo=Util.byte2str(ext_value); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, "server-sig-algs=<" + foo + ">"); + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "server-sig-algs=<" + foo + ">"); } if(sshBugSigType74){ if(!foo.isEmpty()){ @@ -1334,8 +1343,8 @@ else if(in_kex){ else{ foo="rsa-sha2-256,rsa-sha2-512"; } - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, "OpenSSH 7.4 detected: adding rsa-sha2-256 & rsa-sha2-512 to server-sig-algs"); + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "OpenSSH 7.4 detected: adding rsa-sha2-256 & rsa-sha2-512 to server-sig-algs"); } } serverSigAlgs=Util.split(foo, ","); @@ -1386,8 +1395,8 @@ private void start_discard(Buffer buf, Cipher cipher, MAC mac, } catch(IOException e){ ioe = e; - if(JSch.getLogger().isEnabled(Logger.ERROR)){ - JSch.getLogger().log(Logger.ERROR, + if(getLogger().isEnabled(Logger.ERROR)){ + getLogger().log(Logger.ERROR, "start_discard finished early due to " + e.getMessage()); } } @@ -1946,7 +1955,7 @@ else if(in_kex && stimeout c=Class.forName(foo).asSubclass(Compression.class); inflater=c.getDeclaredConstructor().newInstance(); - inflater.init(Compression.INFLATER, 0); + inflater.init(Compression.INFLATER, 0, this); } catch(Exception ee){ throw new JSchException(ee.toString(), ee); @@ -2808,8 +2817,8 @@ private String[] checkCiphers(String ciphers){ if(ciphers==null || ciphers.length()==0) return null; - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "CheckCiphers: "+ciphers); } @@ -2831,9 +2840,9 @@ private String[] checkCiphers(String ciphers){ String[] foo=new String[result.size()]; System.arraycopy(result.toArray(), 0, foo, 0, result.size()); - if(JSch.getLogger().isEnabled(Logger.INFO)){ + if(getLogger().isEnabled(Logger.INFO)){ for(int i=0; i c=Class.forName(kex).asSubclass(KeyExchange.class); KeyExchange _c=c.getDeclaredConstructor().newInstance(); - _c.init(s ,null, null, null, null); + _c.doInit(s ,null, null, null, null); return true; } catch(Exception | NoClassDefFoundError e){ return false; } @@ -2949,8 +2958,8 @@ private String[] checkSignatures(String sigs){ if(sigs==null || sigs.length()==0) return null; - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(getLogger().isEnabled(Logger.INFO)){ + getLogger().log(Logger.INFO, "CheckSignatures: "+sigs); } @@ -2970,9 +2979,9 @@ private String[] checkSignatures(String sigs){ return null; String[] foo=new String[result.size()]; System.arraycopy(result.toArray(), 0, foo, 0, result.size()); - if(JSch.getLogger().isEnabled(Logger.INFO)){ + if(getLogger().isEnabled(Logger.INFO)){ for(int i=0; inull if the instance logger + * of this instance's jsch instance should be used + */ + public void setLogger(Logger logger) { + this.logger = logger; + } } diff --git a/src/main/java/com/jcraft/jsch/UserAuthNone.java b/src/main/java/com/jcraft/jsch/UserAuthNone.java index 1b8b9375..8eef355b 100644 --- a/src/main/java/com/jcraft/jsch/UserAuthNone.java +++ b/src/main/java/com/jcraft/jsch/UserAuthNone.java @@ -46,8 +46,8 @@ public boolean start(Session session) throws Exception{ buf.putString(Util.str2byte("ssh-userauth")); session.write(packet); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "SSH_MSG_SERVICE_REQUEST sent"); } @@ -59,8 +59,8 @@ public boolean start(Session session) throws Exception{ boolean result=(command==SSH_MSG_SERVICE_ACCEPT); - if(JSch.getLogger().isEnabled(Logger.INFO)){ - JSch.getLogger().log(Logger.INFO, + if(session.getLogger().isEnabled(Logger.INFO)){ + session.getLogger().log(Logger.INFO, "SSH_MSG_SERVICE_ACCEPT received"); } if(!result) diff --git a/src/main/java/com/jcraft/jsch/UserAuthPublicKey.java b/src/main/java/com/jcraft/jsch/UserAuthPublicKey.java index 05282730..fb19c478 100644 --- a/src/main/java/com/jcraft/jsch/UserAuthPublicKey.java +++ b/src/main/java/com/jcraft/jsch/UserAuthPublicKey.java @@ -45,8 +45,8 @@ public boolean start(Session session) throws Exception{ } String pkmethodstr=session.getConfig("PubkeyAcceptedAlgorithms"); - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, "PubkeyAcceptedAlgorithms = " + pkmethodstr); } @@ -55,8 +55,8 @@ public boolean start(Session session) throws Exception{ Arrays.asList(not_available_pka) : Collections.emptyList()); if(!not_available_pks.isEmpty()){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, "Signature algorithms unavailable for non-agent identities = " + not_available_pks); } } @@ -88,15 +88,15 @@ public boolean start(Session session) throws Exception{ } if(!_known.isEmpty()){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, "PubkeyAcceptedAlgorithms in server-sig-algs = " + _known); } } if(!_unknown.isEmpty()){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, "PubkeyAcceptedAlgorithms not in server-sig-algs = " + _unknown); } } @@ -111,8 +111,8 @@ public boolean start(Session session) throws Exception{ } } else{ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, "No server-sig-algs found, using PubkeyAcceptedAlgorithms = " + pkmethods); + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, "No server-sig-algs found, using PubkeyAcceptedAlgorithms = " + pkmethods); } } @@ -162,8 +162,8 @@ else if(nonrsamethods.contains(_ipkmethod)){ ipkmethods=Collections.singletonList(_ipkmethod); } if(ipkmethods==null) { - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, _ipkmethod+" cannot be used as public key type for identity "+identity.getName()); } continue; @@ -177,8 +177,8 @@ else if(nonrsamethods.contains(_ipkmethod)){ loop3: for(String ipkmethod : ipkmethods){ if(not_available_pks.contains(ipkmethod) && !(identity instanceof AgentIdentity)){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, ipkmethod+" not available for identity "+identity.getName()); } continue loop3; @@ -208,16 +208,16 @@ else if(nonrsamethods.contains(_ipkmethod)){ command=buf.getCommand()&0xff; if(command==SSH_MSG_USERAUTH_PK_OK){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, ipkmethod + " preauth success"); } pkmethodsuccesses=Collections.singletonList(ipkmethod); break loop3; } else if(command==SSH_MSG_USERAUTH_FAILURE){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, ipkmethod + " preauth failure"); } continue loop3; @@ -235,8 +235,8 @@ else if(command==SSH_MSG_USERAUTH_BANNER){ else{ //System.err.println("USERAUTH fail ("+command+")"); //throw new JSchException("USERAUTH fail ("+command+")"); - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, ipkmethod + " preauth failure command (" + command + ")"); } continue loop3; @@ -262,8 +262,8 @@ else if(command==SSH_MSG_USERAUTH_BANNER){ loop4: for(String pkmethodsuccess : pkmethodsuccesses){ if(not_available_pks.contains(pkmethodsuccess) && !(identity instanceof AgentIdentity)){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, pkmethodsuccess+" not available for identity "+identity.getName()); } continue loop4; @@ -302,8 +302,8 @@ else if(command==SSH_MSG_USERAUTH_BANNER){ System.arraycopy(buf.buffer, 5, tmp, 4+sidlen, buf.index-5); byte[] signature=identity.getSignature(tmp, pkmethodsuccess); if(signature==null){ // for example, too long key length. - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, pkmethodsuccess + " signature failure"); } continue loop4; @@ -317,8 +317,8 @@ else if(command==SSH_MSG_USERAUTH_BANNER){ command=buf.getCommand()&0xff; if(command==SSH_MSG_USERAUTH_SUCCESS){ - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, pkmethodsuccess + " auth success"); } return true; @@ -343,16 +343,16 @@ else if(command==SSH_MSG_USERAUTH_FAILURE){ throw new JSchPartialAuthException(Util.byte2str(foo)); } session.auth_failures++; - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, pkmethodsuccess + " auth failure"); } break loop2; } //System.err.println("USERAUTH fail ("+command+")"); //throw new JSchException("USERAUTH fail ("+command+")"); - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, + if(session.getLogger().isEnabled(Logger.DEBUG)){ + session.getLogger().log(Logger.DEBUG, pkmethodsuccess + " auth failure command (" + command +")"); } break loop2; diff --git a/src/main/java/com/jcraft/jsch/juz/Compression.java b/src/main/java/com/jcraft/jsch/juz/Compression.java index d2d67d35..7ffd6304 100644 --- a/src/main/java/com/jcraft/jsch/juz/Compression.java +++ b/src/main/java/com/jcraft/jsch/juz/Compression.java @@ -2,6 +2,7 @@ package com.jcraft.jsch.juz; import com.jcraft.jsch.*; +import java.util.function.Supplier; import java.util.zip.Deflater; import java.util.zip.Inflater; @@ -29,10 +30,25 @@ public class Compression implements com.jcraft.jsch.Compression { private Inflater inflater; private byte[] tmpbuf=new byte[BUF_SIZE]; private byte[] inflated_buf; + private Session session; public Compression(){ } + private void logMessage(int level, Supplier message) { + Logger logger = session == null ? JSch.getLogger() : session.getLogger(); + if (!logger.isEnabled(level)) { + return; + } + logger.log(level, message.get()); + } + + @Override + public void init(int type, int level, Session session) throws Exception{ + this.session = session; + init(type, level); + } + @Override public void init(int type, int level) throws Exception{ if(type==DEFLATER){ @@ -42,10 +58,7 @@ else if(type==INFLATER){ inflater=new Inflater(); inflated_buf=new byte[BUF_SIZE]; } - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, - "zlib using "+this.getClass().getCanonicalName()); - } + logMessage(Logger.DEBUG, () -> "zlib using "+this.getClass().getCanonicalName()); } @Override @@ -99,10 +112,7 @@ public byte[] uncompress(byte[] buf, int start, int[] len){ while(inflater.getRemaining()>0); } catch(java.util.zip.DataFormatException e){ - if(JSch.getLogger().isEnabled(Logger.WARN)){ - JSch.getLogger().log(Logger.WARN, - "an exception during uncompress\n"+e.toString()); - } + logMessage(Logger.WARN, () -> "an exception during uncompress\n"+e.toString()); } if(buf.length message) { + Logger logger = session == null ? JSch.getLogger() : session.getLogger(); + if (!logger.isEnabled(level)) { + return; + } + logger.log(level, message.get()); + } + @Override - public void init(int type, int level) throws Exception{ + public void init(int type, int level, Session session) throws Exception{ + this.session = session; + init(type, level); + } + + public void init(int type, int level) throws GZIPException { if(type==DEFLATER){ deflater=new Deflater(level); } @@ -50,10 +67,7 @@ else if(type==INFLATER){ inflater=new Inflater(); inflated_buf=new byte[BUF_SIZE]; } - if(JSch.getLogger().isEnabled(Logger.DEBUG)){ - JSch.getLogger().log(Logger.DEBUG, - "zlib using "+this.getClass().getCanonicalName()); - } + logMessage(Logger.DEBUG, () -> "zlib using "+this.getClass().getCanonicalName()); } @Override @@ -61,7 +75,6 @@ public byte[] compress(byte[] buf, int start, int[] len){ deflater.next_in=buf; deflater.next_in_index=start; deflater.avail_in=len[0]-start; - int status; int outputlen=start; byte[] outputbuf=buf; int tmp=0; @@ -70,7 +83,7 @@ public byte[] compress(byte[] buf, int start, int[] len){ deflater.next_out=tmpbuf; deflater.next_out_index=0; deflater.avail_out=BUF_SIZE; - status=deflater.deflate(JZlib.Z_PARTIAL_FLUSH); + int status=deflater.deflate(JZlib.Z_PARTIAL_FLUSH); switch(status){ case JZlib.Z_OK: tmp=BUF_SIZE-deflater.avail_out; @@ -83,11 +96,7 @@ public byte[] compress(byte[] buf, int start, int[] len){ outputlen+=tmp; break; default: - if(JSch.getLogger().isEnabled(Logger.WARN)){ - JSch.getLogger().log(Logger.WARN, - "compress: deflate returnd "+status); - } - + logMessage(Logger.WARN, () -> "compress: deflate returnd "+status); } } while(deflater.avail_out==0); @@ -138,11 +147,8 @@ public byte[] uncompress(byte[] buffer, int start, int[] length){ length[0]=inflated_end; return buffer; default: - if(JSch.getLogger().isEnabled(Logger.WARN)){ - JSch.getLogger().log(Logger.WARN, - "uncompress: inflate returnd "+status); - } - return null; + logMessage(Logger.WARN, () -> "compress: deflate returnd "+status); + return null; } } } diff --git a/src/test/java/com/jcraft/jsch/JSchTest.java b/src/test/java/com/jcraft/jsch/JSchTest.java index 8293b0f7..a2d7ea96 100644 --- a/src/test/java/com/jcraft/jsch/JSchTest.java +++ b/src/test/java/com/jcraft/jsch/JSchTest.java @@ -1,5 +1,6 @@ package com.jcraft.jsch; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.Hashtable; @@ -8,6 +9,11 @@ class JSchTest { + @BeforeEach + void resetJsch() { + JSch.setLogger(null); + } + @Test void getPubkeyAcceptedKeyTypes() throws JSchException { JSch.setConfig("PubkeyAcceptedAlgorithms", "JSchTest111"); @@ -30,4 +36,43 @@ void setPubkeyAcceptedKeyTypesHashtable() throws JSchException { assertEquals("JSchTest333", JSch.getConfig("PubkeyAcceptedKeyTypes")); assertEquals("JSchTest333", JSch.getConfig("PubkeyAcceptedAlgorithms")); } + + @Test + void checkLoggerBehavior() throws Exception { + assertSame(JSch.DEVNULL, JSch.logger, "initial static value of logger should be DEVNULL"); + + JSch jsch = new JSch(); + assertSame(JSch.DEVNULL, jsch.getInstanceLogger(), "instance logger should be DEVNULL"); + + TestLogger staticLogger = new TestLogger(); + TestLogger instanceLogger = new TestLogger(); + + JSch.setLogger(staticLogger); + assertSame(staticLogger, JSch.logger, "mismatch with static logger"); + assertSame(staticLogger, jsch.getInstanceLogger(), "instance should return static logger"); + + jsch.setInstanceLogger(instanceLogger); + assertSame(staticLogger, JSch.logger, "mismatch with static logger"); + assertSame(instanceLogger, jsch.getInstanceLogger(), "instance should return static logger"); + + jsch.setInstanceLogger(null); + assertSame(staticLogger, JSch.logger, "mismatch with static logger"); + assertSame(staticLogger, jsch.getInstanceLogger(), "instance should return static logger"); + + JSch.setLogger(null); + assertSame(JSch.DEVNULL, JSch.logger, "static logger should be DEVNULL"); + assertSame(JSch.DEVNULL, jsch.getInstanceLogger(), "instance logger should be DEVNULL"); + } + + final static class TestLogger implements Logger { + @Override + public boolean isEnabled(int level) { + return true; + } + + @Override + public void log(int level, String message) { + // empty + } + } } diff --git a/src/test/java/com/jcraft/jsch/SessionTest.java b/src/test/java/com/jcraft/jsch/SessionTest.java index 541018e9..cc7b66e8 100644 --- a/src/test/java/com/jcraft/jsch/SessionTest.java +++ b/src/test/java/com/jcraft/jsch/SessionTest.java @@ -5,6 +5,8 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import com.jcraft.jsch.JSchTest.TestLogger; + import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; @@ -54,4 +56,31 @@ void setPubkeyAcceptedKeyTypes() throws JSchException { assertEquals("SessionTest222", session.getConfig("PubkeyAcceptedKeyTypes")); assertEquals("SessionTest222", session.getConfig("PubkeyAcceptedAlgorithms")); } + + @Test + void checkLoggerFunctionality() throws Exception { + Logger orgLogger = JSch.getLogger(); + try { + JSch.setLogger(null); + TestLogger staticLogger = new TestLogger(); + TestLogger jschInstanceLogger = new TestLogger(); + TestLogger sessionLogger = new TestLogger(); + + Session session = new Session(jsch, null, null, 0); + + assertSame(JSch.DEVNULL, session.getLogger(), "DEVNULL logger expected after creation"); + + JSch.setLogger(staticLogger); + assertSame(staticLogger, session.getLogger(), "static logger expected after setting static logger"); + + jsch.setInstanceLogger(jschInstanceLogger); + assertSame(jschInstanceLogger, session.getLogger(), "static logger expected after setting instance logger"); + + session.setLogger(sessionLogger); + assertSame(sessionLogger, session.getLogger(), "static logger expected after setting session logger"); + } + finally { + JSch.setLogger(orgLogger); + } + } }