//using System;
//using System.Net;
//using System.Net.Sockets;
//using System.IO;
//using System.Threading;
//
//namespace Tamir.SharpSsh.jsch
//{
// /// <summary>
// /// Summary description for Session.
// /// </summary>
// public class Session
// {
// private const String version="sharpSsh-0.1.24-experimental";
//
// // 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_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=Util.getBytes("SSH-2.0-"+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
// 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;
//
// bool x11_forwarding=false;
//
// private System.Threading.Thread connectThread=null;
//
// internal Stream ins=null;
// internal Stream outs=null;
//
// internal static Random random;
//
// internal Buffer buf;
// internal Packet packet;
//
// internal SocketFactory socket_factory=null;
//
// private System.Collections.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
// {
// Type t=Type.GetType(getConfig("random"));
// random=(Random)(Activator.CreateInstance(t));
// }
// catch{}
// }
// Packet.setRandom(random);
//
// try
// {
// int i, j;
// //int pad=0;
//
// if(proxy==null)
// {
// proxy=jsch.getProxy(host);
// if(proxy!=null)
// {
// lock(proxy)
// {
// proxy.close();
// }
// }
// }
// IPEndPoint ipe=null;
// if(proxy==null)
// {
// Stream ins;
// Stream outs;
// if(socket_factory==null)
// {
// if(connectTimeout==0)
// {
// ipe = new IPEndPoint(Dns.GetHostByName(host).AddressList[0], port);
// socket=new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// }
// // String message="";
// // Thread tmp=new Thread(new Runnable(){
// // public void run(){
// // try{
// // sockp[0]=new Socket(host, port);
// // if(done[0]){
// // if(sockp[0]!=null){
// // sockp[0].close();
// // sockp[0]=null;
// // }
// // }
// // else thread.interrupt();
// // }
// // catch(Exception e){
// // ee[0]=e;
// // thread.interrupt();
// // if(sockp[0]!=null){
// // try{
// // sockp[0].close();
// // sockp[0]=null;
// // }catch(Exception eee){}
// // }
// // }
// // }
// // });
// // tmp.start();
// // try{
// // Thread.sleep(connectTimeout);
// // message="timeout: ";
// // }
// // catch(java.lang.InterruptedException eee){
// // tmp.interrupt();
// // tmp=null;
// // System.gc();
// // }
// // done[0]=true;
// // if(sockp[0]!=null){
// // socket=sockp[0];
// // }
// // else{
// // message+="socket is not established";
// // if(ee[0]!=null){
// // message=ee[0].toString();
// // }
// // throw new JSchException(message);
// // }
// // }
// socket.Connect(ipe);
// NetworkStream ns = new NetworkStream( socket );
// ins=ns;
// outs=ns;
// }
// else
// {
// socket=socket_factory.createSocket(host, port);
// ins=socket_factory.getInputStream(socket);
// outs=socket_factory.getOutputStream(socket);
// }
// if(timeout>0)
// {
// socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, timeout);
// }
// socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);
// io.setInputStream(ins);
// io.setOutputStream(outs);
// }
// else
// {
// lock(proxy)
// {
// proxy.connect(this, host, port);
// io.setInputStream(proxy.getInputStream());
// io.setOutputStream(proxy.getOutputStream());
// }
// }
//
// isConnected=true;
//
// i=0;
// while(i<buf.buffer.Length)
// {
// j=io.getByte();
// buf.buffer[i]=(byte)j; i++;
// if(j==10)break;
// }
//
// if(buf.buffer[i-1]==10)
// { // 0x0a
// i--;
// if(buf.buffer[i-1]==13)
// { // 0x0d
// i--;
// }
// }
//
// 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");
// }
//
// V_S=new byte[i]; Array.Copy(buf.buffer, 0, V_S, 0, i);
// //Console.WritLine("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];
// Array.Copy(V_C, 0, foo, 0, V_C.Length);
// foo[foo.Length-1]=(byte)'\n';
// io.put(foo, 0, foo.Length);
// }
//
// buf=read(buf);
// //Console.WritLine("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);
//
// bool result;
// while(true)
// {
// buf=read(buf);
// if(kex.getState()==buf.buffer[5])
// {
// result=kex.next(buf);
// if(!result)
// {
// //Console.WritLine("verify: "+result);
// throw new JSchException("verify: "+result);
// }
// }
// else
// {
// throw new JSchException("invalid protocol(kex): "+buf.buffer[5]);
// }
// if(kex.getState()==KeyExchange.STATE_END)
// {
// break;
// }
// }
//
// checkHost(host, kex);
//
// send_newkeys();
//
// // receive SSH_MSG_NEWKEYS(21)
// buf=read(buf);
// //Console.WritLine("read: 21 ? "+buf.buffer[5]);
// if(buf.buffer[5]==SSH_MSG_NEWKEYS)
// {
// receive_newkeys(buf, kex);
// }
// else
// {
// 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=usn.getMethods();
// // methods: publickey,password,keyboard-interactive
// if(methods==null)
// {
// methods="publickey,password,keyboard-interactive";
// }
//
// //loop:
// while(true)
// {
//
// //Console.WritLine("methods: "+methods);
//
// while(!auth &&
// methods!=null && methods.Length>0)
// {
//
// //Console.WritLine(" methods: "+methods);
//
// UserAuth us=null;
// if(methods.StartsWith("publickey"))
// {
// //Console.WritLine(" jsch.identities.size()="+jsch.identities.size());
// lock(jsch.identities)
// {
// if(jsch.identities.Count>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)
// {
// Console.WriteLine(ee);
// auth_cancel=true;
// }
// catch(JSchPartialAuthException ee)
// {
// methods=ee.getMethods();
// //Console.WritLine("PartialAuth: "+methods);
// auth_cancel=false;
// continue /*loop*/;
// }
// catch(Exception ee)
// {
// throw ee;
// }
// }
// if(!auth)
// {
// int comma=methods.IndexOf(",");
// if(comma==-1) break;
// methods=methods.Substring(comma+1);
// }
// }
// break;
// }
//
// if(auth)
// {
// connectThread=new System.Threading.Thread(new System.Threading.ThreadStart(run));
// connectThread.Start();
// return;
// }
// if(auth_cancel)
// throw new JSchException("Auth cancel");
// throw new JSchException("Auth fail");
// }
// catch(Exception e)
// {
// if(isConnected)
// {
// try
// {
// packet.reset();
// buf.putByte((byte)SSH_MSG_DISCONNECT);
// buf.putInt(3);
// buf.putString(Util.getBytes(e.ToString()));
// buf.putString(Util.getBytes( "en" ));
// write(packet);
// disconnect();
// }
// catch
// {
// }
// }
// isConnected=false;
// //e.printStackTrace();
// //if(e is JSchException) throw (JSchException)e;
// //throw new JSchException("Session.connect: "+e);
// throw 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()];
// }
// Array.Copy(buf.buffer, buf.s, I_S, 0, I_S.Length);
// /*
// try{
// byte[] tmp=new byte[I_S.length];
// System.arraycopy(I_S, 0, tmp, 0, I_S.length);
// Buffer tmpb=new Buffer(tmp);
// Console.WritLine("I_S: len="+I_S.length);
// tmpb.setOffSet(17);
// Console.WritLine("kex: "+new String(tmpb.getString()));
// Console.WritLine("server_host_key: "+new String(tmpb.getString()));
// Console.WritLine("cipher.c2s: "+new String(tmpb.getString()));
// Console.WritLine("cipher.s2c: "+new String(tmpb.getString()));
// Console.WritLine("mac.c2s: "+new String(tmpb.getString()));
// Console.WritLine("mac.s2c: "+new String(tmpb.getString()));
// Console.WritLine("compression.c2s: "+new String(tmpb.getString()));
// Console.WritLine("compression.s2c: "+new String(tmpb.getString()));
// Console.WritLine("lang.c2s: "+new String(tmpb.getString()));
// Console.WritLine("lang.s2c: "+new String(tmpb.getString()));
// Console.WritLine("?: "+(tmpb.getByte()&0xff));
// Console.WritLine("??: "+tmpb.getInt());
// }
// catch(Exception e){
// Console.WritLine(e);
// }
// */
//
// send_kexinit();
// String[] guess=KeyExchange.Guess(I_S, I_C);
// if(guess==null)
// {
// throw new JSchException("Algorithm negotiation fail");
// }
//
// KeyExchange kex=null;
// try
// {
// Type t=Type.GetType(getConfig(guess[KeyExchange.PROPOSAL_KEX_ALGS]));
// kex=(KeyExchange)(Activator.CreateInstance(t));
// kex.guess=guess;
// kex.init(this, V_S, V_C, I_S, I_C);
// }
// catch(Exception e){Console.WriteLine("kex: "+e); }
//
// 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(Util.getBytes( getConfig("kex")));
// buf.putString(Util.getBytes(getConfig("server_host_key")));
// buf.putString(Util.getBytes(getConfig("cipher.c2s")));
// buf.putString(Util.getBytes(getConfig("cipher.s2c")));
// buf.putString(Util.getBytes(getConfig("mac.c2s")));
// buf.putString(Util.getBytes(getConfig("mac.s2c")));
// buf.putString(Util.getBytes(getConfig("compression.c2s")));
// buf.putString(Util.getBytes(getConfig("compression.s2c")));
// buf.putString(Util.getBytes(getConfig("lang.c2s")));
// buf.putString(Util.getBytes(getConfig("lang.s2c")));
// 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");
//
// //Console.WritLine("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);
// }
// 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=
// "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"+
// "@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @\n"+
// "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\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.";
// if(userinfo!=null)
// {
// userinfo.showMessage(message);
// }
// throw new JSchException("HostKey has been changed");
// }
//
// bool insert=false;
//
// if((shkc.Equals("ask") || shkc.Equals("yes")) &&
// i!=HostKeyRepository.OK)
// {
// if(shkc.Equals("yes"))
// {
// throw new JSchException("reject HostKey");
// }
// //Console.WritLine("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");
// }
// insert=true;
// }
// else
// {
// if(i==HostKeyRepository.NOT_INCLUDED)
// throw new JSchException("UnknownHostKey");
// else throw new JSchException("HostKey has been changed.");
// }
// }
//
// 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
// {
// //e.printStackTrace();
// }
// return null;
// }
//
// // encode will bin invoked in write with synchronization.
// public void encode(Packet packet)
// {
// //Console.WritLine("encode: "+packet.buffer.buffer[5]);
// //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();
// }