//using System; using System.IO; using System.Runtime.CompilerServices; using Tamir.SharpSsh.java; using Tamir.SharpSsh.java.util; using Tamir.SharpSsh.java.net; using Tamir.SharpSsh.java.lang; using Exception = System.Exception; using NullReferenceException = System.NullReferenceException; using ThreadInterruptedException = System.Threading.ThreadInterruptedException; namespace Tamir.SharpSsh.jsch { public class Session : Runnable { private static String version="SharpSSH-"+Tamir.SharpSsh.SshBase.Version.ToString()+"-JSCH-0.1.28"; // http://ietf.org/internet-drafts/draft-ietf-secsh-assignednumbers-01.txt internal const int SSH_MSG_DISCONNECT= 1; internal const int SSH_MSG_IGNORE= 2; internal const int SSH_MSG_UNIMPLEMENTED= 3; internal const int SSH_MSG_DEBUG= 4; internal const int SSH_MSG_SERVICE_REQUEST= 5; internal const int SSH_MSG_SERVICE_ACCEPT= 6; internal const int SSH_MSG_KEXINIT= 20; internal const int SSH_MSG_NEWKEYS= 21; internal const int SSH_MSG_KEXDH_INIT= 30; internal const int SSH_MSG_KEXDH_REPLY= 31; internal const int SSH_MSG_KEX_DH_GEX_GROUP= 31; internal const int SSH_MSG_KEX_DH_GEX_INIT= 32; internal const int SSH_MSG_KEX_DH_GEX_REPLY= 33; internal const int SSH_MSG_KEX_DH_GEX_REQUEST= 34; internal const int SSH_MSG_USERAUTH_REQUEST= 50; internal const int SSH_MSG_USERAUTH_FAILURE= 51; internal const int SSH_MSG_USERAUTH_SUCCESS= 52; internal const int SSH_MSG_USERAUTH_BANNER= 53; internal const int SSH_MSG_USERAUTH_INFO_REQUEST= 60; internal const int SSH_MSG_USERAUTH_INFO_RESPONSE= 61; internal const int SSH_MSG_USERAUTH_PK_OK= 60; internal const int SSH_MSG_GLOBAL_REQUEST= 80; internal const int SSH_MSG_REQUEST_SUCCESS= 81; internal const int SSH_MSG_REQUEST_FAILURE= 82; internal const int SSH_MSG_CHANNEL_OPEN= 90; internal const int SSH_MSG_CHANNEL_OPEN_CONFIRMATION= 91; internal const int SSH_MSG_CHANNEL_OPEN_FAILURE= 92; internal const int SSH_MSG_CHANNEL_WINDOW_ADJUST= 93; internal const int SSH_MSG_CHANNEL_DATA= 94; internal const int SSH_MSG_CHANNEL_EXTENDED_DATA= 95; internal const int SSH_MSG_CHANNEL_EOF= 96; internal const int SSH_MSG_CHANNEL_CLOSE= 97; internal const int SSH_MSG_CHANNEL_REQUEST= 98; internal const int SSH_MSG_CHANNEL_SUCCESS= 99; internal const int SSH_MSG_CHANNEL_FAILURE= 100; private byte[] V_S; // server version private byte[] V_C=("SSH-2.0-"+version).getBytes(); // 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 private byte[] K_S; // the host key private byte[] session_id; private byte[] IVc2s; private byte[] IVs2c; private byte[] Ec2s; private byte[] Es2c; private byte[] MACc2s; private byte[] MACs2c; private int seqi=0; private int seqo=0; private Cipher s2ccipher; private Cipher c2scipher; private MAC s2cmac; private MAC c2smac; private byte[] mac_buf; private Compression deflater; private Compression inflater; private IO io; private Socket socket; private int timeout=0; private bool _isConnected=false; private bool isAuthed=false; private Thread connectThread=null; internal bool x11_forwarding=false; internal Stream In=null; internal Stream Out=null; internal static Random random; internal Buffer buf; internal Packet packet; internal SocketFactory socket_factory=null; private Hashtable config=null; private Proxy proxy=null; private UserInfo userinfo; internal String host="127.0.0.1"; internal int port=22; internal String username=null; internal String password=null; internal JSch jsch; internal Session(JSch jsch) { ; this.jsch=jsch; buf=new Buffer(); packet=new Packet(buf); } public void connect() { connect(timeout); } public void connect(int connectTimeout) { if(_isConnected) { throw new JSchException("session is already connected"); } io=new IO(); if(random==null) { try { Class c=Class.forName(getConfig("random")); random=(Random)(c.newInstance()); } catch(Exception e) { System.Console.Error.WriteLine("connect: random "+e); } } Packet.setRandom(random); try { int i, j; int pad=0; if(proxy==null) { proxy=jsch.getProxy(host); if(proxy!=null) { lock(proxy) { proxy.close(); } } } if(proxy==null) { Stream In; Stream Out; if(socket_factory==null) { socket=Util.createSocket(host, port, connectTimeout); In=socket.getInputStream(); Out=socket.getOutputStream(); } else { socket=socket_factory.createSocket(host, port); In=socket_factory.getInputStream(socket); Out=socket_factory.getOutputStream(socket); } //if(timeout>0){ socket.setSoTimeout(timeout); } socket.setTcpNoDelay(true); io.setInputStream(In); io.setOutputStream(Out); } else { lock(proxy) { proxy.connect(socket_factory, host, port, connectTimeout); io.setInputStream(proxy.getInputStream()); io.setOutputStream(proxy.getOutputStream()); socket=proxy.getSocket(); } } if(connectTimeout>0 && socket!=null) { socket.setSoTimeout(connectTimeout); } _isConnected=true; while(true) { i=0; j=0; while(i4 && (i!=buf.buffer.Length) && (buf.buffer[0]!='S'||buf.buffer[1]!='S'|| buf.buffer[2]!='H'||buf.buffer[3]!='-')) { //System.err.println(new String(buf.buffer, 0, i); continue; } if(i==buf.buffer.Length || i<7 || // SSH-1.99 or SSH-2.0 (buf.buffer[4]=='1' && buf.buffer[6]!='9') // SSH-1.5 ) { throw new JSchException("invalid server's version String"); } break; } V_S=new byte[i]; Tamir.SharpSsh.java.System.arraycopy(buf.buffer, 0, V_S, 0, i); //System.Console.WriteLine("V_S: ("+i+") ["+new String(V_S)+"]"); //io.put(V_C, 0, V_C.Length); io.put("\n".getBytes(), 0, 1); { // Some Cisco devices will miss to read '\n' if it is sent separately. byte[] foo=new byte[V_C.Length+1]; Tamir.SharpSsh.java.System.arraycopy(V_C, 0, foo, 0, V_C.Length); foo[foo.Length-1]=(byte)'\n'; io.put(foo, 0, foo.Length); } buf=read(buf); //System.Console.WriteLine("read: 20 ? "+buf.buffer[5]); if(buf.buffer[5]!=SSH_MSG_KEXINIT) { throw new JSchException("invalid protocol: "+buf.buffer[5]); } KeyExchange kex=receive_kexinit(buf); while(true) { buf=read(buf); if(kex.getState()==buf.buffer[5]) { bool result=kex.next(buf); if(!result) { //System.Console.WriteLine("verify: "+result); in_kex=false; throw new JSchException("verify: "+result); } } else { in_kex=false; throw new JSchException("invalid protocol(kex): "+buf.buffer[5]); } if(kex.getState()==KeyExchange.STATE_END) { break; } } try{ checkHost(host, kex); } catch(JSchException ee) { in_kex=false; throw ee; } send_newkeys(); // receive SSH_MSG_NEWKEYS(21) buf=read(buf); //System.Console.WriteLine("read: 21 ? "+buf.buffer[5]); if(buf.buffer[5]==SSH_MSG_NEWKEYS) { receive_newkeys(buf, kex); } else { in_kex=false; throw new JSchException("invalid protocol(newkyes): "+buf.buffer[5]); } bool auth=false; bool auth_cancel=false; UserAuthNone usn=new UserAuthNone(userinfo); auth=usn.start(this); String methods=null; if(!auth) { methods=usn.getMethods(); if(methods!=null) { methods=methods.toLowerCase(); } else { // methods: publickey,password,keyboard-interactive methods="publickey,password,keyboard-interactive"; } } loop: while(true) { //System.Console.WriteLine("methods: "+methods); while(!auth && methods!=null && methods.Length()>0) { //System.Console.WriteLine(" methods: "+methods); UserAuth us=null; if(methods.startsWith("publickey")) { //System.Console.WriteLine(" jsch.identities.size()="+jsch.identities.size()); lock(jsch.identities) { if(jsch.identities.size()>0) { us=new UserAuthPublicKey(userinfo); } } } else if(methods.startsWith("keyboard-interactive")) { if(userinfo is UIKeyboardInteractive) { us=new UserAuthKeyboardInteractive(userinfo); } } else if(methods.startsWith("password")) { us=new UserAuthPassword(userinfo); } if(us!=null) { try { auth=us.start(this); auth_cancel=false; } catch(JSchAuthCancelException ee) { //System.Console.WriteLine(ee); auth_cancel=true; } catch(JSchPartialAuthException ee) { methods=ee.getMethods(); //System.Console.WriteLine("PartialAuth: "+methods); auth_cancel=false; continue;//loop; } catch(RuntimeException ee) { throw ee; } catch(Exception ee) { System.Console.WriteLine("ee: "+ee); // SSH_MSG_DISCONNECT: 2 Too many authentication failures } } if(!auth) { int comma=methods.indexOf(","); if(comma==-1) break; methods=methods.subString(comma+1); } } break; } if(connectTimeout>0 || timeout>0) { socket.setSoTimeout(timeout); } if(auth) { isAuthed=true; connectThread=new Thread(this); connectThread.setName("Connect thread "+host+" session"); connectThread.start(); return; } if(auth_cancel) throw new JSchException("Auth cancel"); throw new JSchException("Auth fail"); } catch(Exception e) { in_kex=false; if(_isConnected) { try { packet.reset(); buf.putByte((byte)SSH_MSG_DISCONNECT); buf.putInt(3); buf.putString(new String(e.ToString()).getBytes()); buf.putString(new String("en").getBytes()); write(packet); disconnect(); } catch(Exception ee) { } } _isConnected=false; //e.printStackTrace(); if(e is RuntimeException) throw (RuntimeException)e; if(e is JSchException) throw (JSchException)e; throw new JSchException("Session.connect: "+e); } } private KeyExchange receive_kexinit(Buffer buf) { int j=buf.getInt(); if(j!=buf.getLength()) { // packet was compressed and buf.getByte(); // j is the size of deflated packet. I_S=new byte[buf.index-5]; } else { I_S=new byte[j-1-buf.getByte()]; } Tamir.SharpSsh.java.System.arraycopy(buf.buffer, buf.s, I_S, 0, I_S.Length); /* try{ byte[] tmp=new byte[I_S.Length]; Tamir.SharpSsh.java.System.arraycopy(I_S, 0, tmp, 0, I_S.Length); Buffer tmpb=new Buffer(tmp); System.Console.WriteLine("I_S: len="+I_S.Length); tmpb.setOffSet(17); System.Console.WriteLine("kex: "+new String(tmpb.getString())); System.Console.WriteLine("server_host_key: "+new String(tmpb.getString())); System.Console.WriteLine("cipher.c2s: "+new String(tmpb.getString())); System.Console.WriteLine("cipher.s2c: "+new String(tmpb.getString())); System.Console.WriteLine("mac.c2s: "+new String(tmpb.getString())); System.Console.WriteLine("mac.s2c: "+new String(tmpb.getString())); System.Console.WriteLine("compression.c2s: "+new String(tmpb.getString())); System.Console.WriteLine("compression.s2c: "+new String(tmpb.getString())); System.Console.WriteLine("lang.c2s: "+new String(tmpb.getString())); System.Console.WriteLine("lang.s2c: "+new String(tmpb.getString())); System.Console.WriteLine("?: "+(tmpb.getByte()&0xff)); System.Console.WriteLine("??: "+tmpb.getInt()); } catch(Exception e){ System.Console.WriteLine(e); } */ send_kexinit(); String[] guess=KeyExchange.guess(I_S, I_C); if(guess==null) { throw new JSchException("Algorithm negotiation fail"); } if(!isAuthed && (guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS].equals("none") || (guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC].equals("none")))) { throw new JSchException("NONE Cipher should not be chosen before authentification is successed."); } KeyExchange kex=null; try { Class c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_KEX_ALGS])); kex=(KeyExchange)(c.newInstance()); } catch(Exception e){ System.Console.Error.WriteLine("kex: "+e); } kex._guess=guess; kex.init(this, V_S, V_C, I_S, I_C); return kex; } private bool in_kex=false; public void rekey() { send_kexinit(); } private void send_kexinit() { if(in_kex) return; in_kex=true; // byte SSH_MSG_KEXINIT(20) // byte[16] cookie (random bytes) // String kex_algorithms // String server_host_key_algorithms // String encryption_algorithms_client_to_server // String encryption_algorithms_server_to_client // String mac_algorithms_client_to_server // String mac_algorithms_server_to_client // String compression_algorithms_client_to_server // String compression_algorithms_server_to_client // String languages_client_to_server // String languages_server_to_client packet.reset(); buf.putByte((byte) SSH_MSG_KEXINIT); lock(random) { random.fill(buf.buffer, buf.index, 16); buf.skip(16); } buf.putString(getConfig("kex").getBytes()); buf.putString(getConfig("server_host_key").getBytes()); buf.putString(getConfig("cipher.c2s").getBytes()); buf.putString(getConfig("cipher.s2c").getBytes()); buf.putString(getConfig("mac.c2s").getBytes()); buf.putString(getConfig("mac.s2c").getBytes()); buf.putString(getConfig("compression.c2s").getBytes()); buf.putString(getConfig("compression.s2c").getBytes()); buf.putString(getConfig("lang.c2s").getBytes()); buf.putString(getConfig("lang.s2c").getBytes()); buf.putByte((byte)0); buf.putInt(0); buf.setOffSet(5); I_C=new byte[buf.getLength()]; buf.getByte(I_C); write(packet); } private void send_newkeys() { // send SSH_MSG_NEWKEYS(21) packet.reset(); buf.putByte((byte)SSH_MSG_NEWKEYS); write(packet); } private void checkHost(String host, KeyExchange kex) { String shkc=getConfig("StrictHostKeyChecking"); //System.Console.WriteLine("shkc: "+shkc); byte[] K_S=kex.getHostKey(); String key_type=kex.getKeyType(); String key_fprint=kex.getFingerPrint(); hostkey=new HostKey(host, K_S); HostKeyRepository hkr=jsch.getHostKeyRepository(); int i=0; lock(hkr) { i=hkr.check(host, K_S); } bool insert=false; if((shkc.equals("ask") || shkc.equals("yes")) && i==HostKeyRepository.CHANGED) { String file=null; lock(hkr) { file=hkr.getKnownHostsRepositoryID(); } if(file==null){file="known_hosts";} String message= "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n"+ "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n"+ "Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n"+ "It is also possible that the "+key_type+" host key has just been changed.\n"+ "The fingerprint for the "+key_type+" key sent by the remote host is\n"+ key_fprint+".\n"+ "Please contact your system administrator.\n"+ "Add correct host key in "+file+" to get rid of this message."; bool b=false; if(userinfo!=null) { //userinfo.showMessage(message); b=userinfo.promptYesNo(message+ "\nDo you want to delete the old key and insert the new key?"); } //throw new JSchException("HostKey has been changed: "+host); if(!b) { throw new JSchException("HostKey has been changed: "+host); } else { lock(hkr) { hkr.remove(host, (key_type.equals("DSA") ? "ssh-dss" : "ssh-rsa"), null); insert=true; } } } // bool insert=false; if((shkc.equals("ask") || shkc.equals("yes")) && (i!=HostKeyRepository.OK) && !insert) { if(shkc.equals("yes")) { throw new JSchException("reject HostKey: "+host); } //System.Console.WriteLine("finger-print: "+key_fprint); if(userinfo!=null) { bool foo=userinfo.promptYesNo( "The authenticity of host '"+host+"' can't be established.\n"+ key_type+" key fingerprint is "+key_fprint+".\n"+ "Are you sure you want to continue connecting?" ); if(!foo) { throw new JSchException("reject HostKey: "+host); } insert=true; } else { if(i==HostKeyRepository.NOT_INCLUDED) throw new JSchException("UnknownHostKey: "+host+". "+key_type+" key fingerprint is "+key_fprint); else throw new JSchException("HostKey has been changed: "+host); } } if(shkc.equals("no") && HostKeyRepository.NOT_INCLUDED==i) { insert=true; } if(insert) { lock(hkr) { hkr.add(host, K_S, userinfo); } } } //public void start(){ (new Thread(this)).start(); } public Channel openChannel(String type) { if(!_isConnected) { throw new JSchException("session is down"); } try { Channel channel=Channel.getChannel(type); addChannel(channel); channel.init(); return channel; } catch(Exception e) { System.Console.WriteLine(e); } return null; } // encode will bin invoked in write with synchronization. public void encode(Packet packet) { //System.Console.WriteLine("encode: "+packet.buffer.buffer[5]); //System.Console.WriteLine(" "+packet.buffer.index); //if(packet.buffer.buffer[5]==96){ //Thread.dumpStack(); //} if(deflater!=null) { packet.buffer.index=deflater.compress(packet.buffer.buffer, 5, packet.buffer.index); } if(c2scipher!=null) { packet.padding(c2scipher.getIVSize()); int pad=packet.buffer.buffer[4]; lock(random) { random.fill(packet.buffer.buffer, packet.buffer.index-pad, pad); } } else { packet.padding(8); } byte[] mac=null; if(c2smac!=null) { c2smac.update(seqo); c2smac.update(packet.buffer.buffer, 0, packet.buffer.index); mac=c2smac.doFinal(); } if(c2scipher!=null) { byte[] buf=packet.buffer.buffer; c2scipher.update(buf, 0, packet.buffer.index, buf, 0); } if(mac!=null) { packet.buffer.putByte(mac); } } int[] uncompress_len=new int[1]; private int cipher_size=8; public Buffer read(Buffer buf) { int j=0; while(true) { buf.reset(); io.getByte(buf.buffer, buf.index, cipher_size); buf.index+=cipher_size; if(s2ccipher!=null) { s2ccipher.update(buf.buffer, 0, cipher_size, buf.buffer, 0); } // j=((buf.buffer[0]<<24)&0xff000000)| // ((buf.buffer[1]<<16)&0x00ff0000)| // ((buf.buffer[2]<< 8)&0x0000ff00)| // ((buf.buffer[3] )&0x000000ff); j=Util.ToInt32( buf.buffer, 0 ); j=j-4-cipher_size+8; if(j<0 || (buf.index+j)>buf.buffer.Length) { throw new IOException("invalid data"); } if(j>0) { io.getByte(buf.buffer, buf.index, j); buf.index+=(j); if(s2ccipher!=null) { s2ccipher.update(buf.buffer, cipher_size, j, buf.buffer, cipher_size); } } if(s2cmac!=null) { s2cmac.update(seqi); s2cmac.update(buf.buffer, 0, buf.index); byte[] result=s2cmac.doFinal(); io.getByte(mac_buf, 0, mac_buf.Length); if(!Arrays.equals(result, mac_buf)) { throw new IOException("MAC Error"); } } seqi++; if(inflater!=null) { //inflater.uncompress(buf); int pad=buf.buffer[4]; uncompress_len[0]=buf.index-5-pad; byte[] foo=inflater.uncompress(buf.buffer, 5, uncompress_len); if(foo!=null) { buf.buffer=foo; buf.index=5+uncompress_len[0]; } else { System.Console.Error.WriteLine("fail in inflater"); break; } } int type=buf.buffer[5]&0xff; //System.Console.WriteLine("read: "+type); if(type==SSH_MSG_DISCONNECT) { buf.rewind(); buf.getInt();buf.getShort(); int reason_code=buf.getInt(); byte[] description=buf.getString(); byte[] language_tag=buf.getString(); /* System.Console.Error.WriteLine("SSH_MSG_DISCONNECT:"+ " "+reason_code+ " "+new String(description)+ " "+new String(language_tag)); */ throw new JSchException("SSH_MSG_DISCONNECT:"+ " "+reason_code+ " "+new String(description)+ " "+new String(language_tag)); //break; } else if(type==SSH_MSG_IGNORE) { } else if(type==SSH_MSG_DEBUG) { buf.rewind(); buf.getInt();buf.getShort(); /* byte always_display=(byte)buf.getByte(); byte[] message=buf.getString(); byte[] language_tag=buf.getString(); System.Console.Error.WriteLine("SSH_MSG_DEBUG:"+ " "+new String(message)+ " "+new String(language_tag)); */ } else if(type==SSH_MSG_CHANNEL_WINDOW_ADJUST) { buf.rewind(); buf.getInt();buf.getShort(); Channel c=Channel.getChannel(buf.getInt(), this); if(c==null) { } else { c.addRemoteWindowSize(buf.getInt()); } } else { break; } } buf.rewind(); return buf; } internal byte[] getSessionId() { return session_id; } private void receive_newkeys(Buffer buf, KeyExchange kex) { // send_newkeys(); updateKeys(kex); in_kex=false; } private void updateKeys(KeyExchange kex) { byte[] K=kex.getK(); byte[] H=kex.getH(); HASH hash=kex.getHash(); String[] guess=kex._guess; if(session_id==null) { session_id=new byte[H.Length]; Tamir.SharpSsh.java.System.arraycopy(H, 0, session_id, 0, H.Length); } /* Initial IV client to server: HASH (K || H || "A" || session_id) Initial IV server to client: HASH (K || H || "B" || session_id) Encryption key client to server: HASH (K || H || "C" || session_id) Encryption key server to client: HASH (K || H || "D" || session_id) Integrity key client to server: HASH (K || H || "E" || session_id) Integrity key server to client: HASH (K || H || "F" || session_id) */ buf.reset(); buf.putMPInt(K); buf.putByte(H); buf.putByte((byte)0x41); buf.putByte(session_id); hash.update(buf.buffer, 0, buf.index); IVc2s=hash.digest(); int j=buf.index-session_id.Length-1; buf.buffer[j]++; hash.update(buf.buffer, 0, buf.index); IVs2c=hash.digest(); buf.buffer[j]++; hash.update(buf.buffer, 0, buf.index); Ec2s=hash.digest(); buf.buffer[j]++; hash.update(buf.buffer, 0, buf.index); Es2c=hash.digest(); buf.buffer[j]++; hash.update(buf.buffer, 0, buf.index); MACc2s=hash.digest(); buf.buffer[j]++; hash.update(buf.buffer, 0, buf.index); MACs2c=hash.digest(); try { Class c; c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC])); s2ccipher=(Cipher)(c.newInstance()); while(s2ccipher.getBlockSize()>Es2c.Length) { buf.reset(); buf.putMPInt(K); buf.putByte(H); buf.putByte(Es2c); hash.update(buf.buffer, 0, buf.index); byte[] foo=hash.digest(); byte[] bar=new byte[Es2c.Length+foo.Length]; Tamir.SharpSsh.java.System.arraycopy(Es2c, 0, bar, 0, Es2c.Length); Tamir.SharpSsh.java.System.arraycopy(foo, 0, bar, Es2c.Length, foo.Length); Es2c=bar; } s2ccipher.init(Cipher.DECRYPT_MODE, Es2c, IVs2c); cipher_size=s2ccipher.getIVSize(); c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_MAC_ALGS_STOC])); s2cmac=(MAC)(c.newInstance()); s2cmac.init(MACs2c); mac_buf=new byte[s2cmac.getBlockSize()]; c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS])); c2scipher=(Cipher)(c.newInstance()); while(c2scipher.getBlockSize()>Ec2s.Length) { buf.reset(); buf.putMPInt(K); buf.putByte(H); buf.putByte(Ec2s); hash.update(buf.buffer, 0, buf.index); byte[] foo=hash.digest(); byte[] bar=new byte[Ec2s.Length+foo.Length]; Tamir.SharpSsh.java.System.arraycopy(Ec2s, 0, bar, 0, Ec2s.Length); Tamir.SharpSsh.java.System.arraycopy(foo, 0, bar, Ec2s.Length, foo.Length); Ec2s=bar; } c2scipher.init(Cipher.ENCRYPT_MODE, Ec2s, IVc2s); c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_MAC_ALGS_CTOS])); c2smac=(MAC)(c.newInstance()); c2smac.init(MACc2s); if(!guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS].equals("none")) { String foo=getConfig(guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS]); if(foo!=null) { try { c=Class.forName(foo); deflater=(Compression)(c.newInstance()); int level=6; try{ level=Integer.parseInt(getConfig("compression_level"));} catch(Exception ee){ } deflater.init(Compression.DEFLATER, level); } catch(Exception ee) { System.Console.Error.WriteLine(foo+" isn't accessible."); } } } else { if(deflater!=null) { deflater=null; } } if(!guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC].equals("none")) { String foo=getConfig(guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC]); if(foo!=null) { try { c=Class.forName(foo); inflater=(Compression)(c.newInstance()); inflater.init(Compression.INFLATER, 0); } catch(Exception ee) { System.Console.Error.WriteLine(foo+" isn't accessible."); } } } else { if(inflater!=null) { inflater=null; } } } catch(Exception e){ System.Console.Error.WriteLine("updatekeys: "+e); } } public void write(Packet packet, Channel c, int length) { while(true) { if(in_kex) { try{Thread.Sleep(10);} catch(ThreadInterruptedException e){}; continue; } lock(c) { if(c.rwsize>=length) { c.rwsize-=length; break; } } if(c._close || !c.isConnected()) { throw new IOException("channel is broken"); } bool sendit=false; int s=0; byte command=0; int recipient=-1; lock(c) { if(c.rwsize>0) { int len=c.rwsize; if(len>length) { len=length; } if(len!=length) { s=packet.shift(len, (c2smac!=null ? c2smac.getBlockSize() : 0)); } command=packet.buffer.buffer[5]; recipient=c.getRecipient(); length-=len; c.rwsize-=len; sendit=true; } } if(sendit) { _write(packet); if(length==0) { return; } packet.unshift(command, recipient, s, length); lock(c) { if(c.rwsize>=length) { c.rwsize-=length; break; } } } try{Thread.Sleep(100);} catch(ThreadInterruptedException e){}; } _write(packet); } /* public lockpublic void write(Packet packet) { encode(packet); if(io!=null){ io.put(packet); seqo++; } } */ public void write(Packet packet) { // System.Console.WriteLine("in_kex="+in_kex+" "+(packet.buffer.buffer[5])); while(in_kex) { byte command=packet.buffer.buffer[5]; //System.Console.WriteLine("command: "+command); if(command==SSH_MSG_KEXINIT || command==SSH_MSG_NEWKEYS || command==SSH_MSG_KEXDH_INIT || command==SSH_MSG_KEXDH_REPLY || command==SSH_MSG_DISCONNECT || command==SSH_MSG_KEX_DH_GEX_GROUP || command==SSH_MSG_KEX_DH_GEX_INIT || command==SSH_MSG_KEX_DH_GEX_REPLY || command==SSH_MSG_KEX_DH_GEX_REQUEST) { break; } try{Thread.Sleep(10);} catch(ThreadInterruptedException e){}; } _write(packet); } [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.Synchronized)] private void _write(Packet packet) { encode(packet); if(io!=null) { io.put(packet); seqo++; } } Runnable thread; public void run() { thread=this; byte[] foo; Buffer buf=new Buffer(); Packet packet=new Packet(buf); int i=0; Channel channel; int[] start=new int[1]; int[] length=new int[1]; KeyExchange kex=null; try { while(_isConnected && thread!=null) { buf=read(buf); int msgType=buf.buffer[5]&0xff; // if(msgType!=94) //System.Console.WriteLine("read: 94 ? "+msgType); if(kex!=null && kex.getState()==msgType) { bool result=kex.next(buf); if(!result) { throw new JSchException("verify: "+result); } continue; } switch(msgType) { case SSH_MSG_KEXINIT: //System.Console.WriteLine("KEXINIT"); kex=receive_kexinit(buf); break; case SSH_MSG_NEWKEYS: //System.Console.WriteLine("NEWKEYS"); send_newkeys(); receive_newkeys(buf, kex); kex=null; break; case SSH_MSG_CHANNEL_DATA: buf.getInt(); buf.getByte(); buf.getByte(); i=buf.getInt(); channel=Channel.getChannel(i, this); foo=buf.getString(start, length); if(channel==null) { break; } try { channel.write(foo, start[0], length[0]); } catch(Exception e) { //System.Console.WriteLine(e); try{channel.disconnect();} catch(Exception ee){} break; } int len=length[0]; channel.setLocalWindowSize(channel.lwsize-len); if(channel.lwsize