Session.cs :  » Network-Clients » SharpSSH » Tamir » SharpSsh » jsch » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Network Clients » SharpSSH 
SharpSSH » Tamir » SharpSsh » jsch » Session.cs
//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 ExceptionSystem.Exception;
using NullReferenceExceptionSystem.NullReferenceException;
using ThreadInterruptedExceptionSystem.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(i<buf.buffer.Length)
          {
            j=io.getByte();
            if(j<0)break;
            buf.buffer[i]=(byte)j; i++;
            if(j==10)break;
          }
          if(j<0)
          {
            throw new JSchException("connection is closed by foreign host");
          }

          if(buf.buffer[i-1]==10)
          {    // 0x0a
            i--;
            if(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]!='-'))
          {
            //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<channel.lwsize_max/2)
              {
                packet.reset();
                buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
                buf.putInt(channel.getRecipient());
                buf.putInt(channel.lwsize_max-channel.lwsize);
                write(packet);
                channel.setLocalWindowSize(channel.lwsize_max);
              }
              break;

            case SSH_MSG_CHANNEL_EXTENDED_DATA:
              buf.getInt();
              buf.getShort();
              i=buf.getInt();
              channel=Channel.getChannel(i, this);
              buf.getInt();                   // data_type_code == 1
              foo=buf.getString(start, length);
              //System.Console.WriteLine("stderr: "+new String(foo,start[0],length[0]));
              if(channel==null)
              {
                break;
              }
              //channel.write(foo, start[0], length[0]);
              channel.write_ext(foo, start[0], length[0]);

              len=length[0];
              channel.setLocalWindowSize(channel.lwsize-len);
              if(channel.lwsize<channel.lwsize_max/2)
              {
                packet.reset();
                buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);
                buf.putInt(channel.getRecipient());
                buf.putInt(channel.lwsize_max-channel.lwsize);
                write(packet);
                channel.setLocalWindowSize(channel.lwsize_max);
              }
              break;

            case SSH_MSG_CHANNEL_WINDOW_ADJUST:
              buf.getInt();
              buf.getShort();
              i=buf.getInt();
              channel=Channel.getChannel(i, this);
              if(channel==null)
              {
                break;
              }
              channel.addRemoteWindowSize(buf.getInt());
              break;

            case SSH_MSG_CHANNEL_EOF:
              buf.getInt();
              buf.getShort();
              i=buf.getInt();
              channel=Channel.getChannel(i, this);
              if(channel!=null)
              {
                //channel._eof_remote=true;
                //channel.eof();
                channel.eof_remote();
              }
              /*
              packet.reset();
              buf.putByte((byte)SSH_MSG_CHANNEL_EOF);
              buf.putInt(channel.getRecipient());
              write(packet);
              */
              break;
            case SSH_MSG_CHANNEL_CLOSE:
              buf.getInt();
              buf.getShort();
              i=buf.getInt();
              channel=Channel.getChannel(i, this);
              if(channel!=null)
              {
                //        channel.close();
                channel.disconnect();
              }
              /*
                if(Channel.pool.size()==0){
                thread=null;
              }
              */
              break;
            case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
              buf.getInt();
              buf.getShort();
              i=buf.getInt();
              channel=Channel.getChannel(i, this);
              if(channel==null)
              {
                //break;
              }
              channel.setRecipient(buf.getInt());
              channel.setRemoteWindowSize(buf.getInt());
              channel.setRemotePacketSize(buf.getInt());
              break;
            case SSH_MSG_CHANNEL_OPEN_FAILURE:
              buf.getInt();
              buf.getShort();
              i=buf.getInt();
              channel=Channel.getChannel(i, this);
              if(channel==null)
              {
                //break;
              }
              int reason_code=buf.getInt();
              //foo=buf.getString();  // additional textual information
              //foo=buf.getString();  // language tag
              channel.exitstatus=reason_code;
              channel._close=true;
              channel._eof_remote=true;
              channel.setRecipient(0);
              break;
            case SSH_MSG_CHANNEL_REQUEST:
              buf.getInt();
              buf.getShort();
              i=buf.getInt();
              foo=buf.getString();
              bool reply=(buf.getByte()!=0);
              channel=Channel.getChannel(i, this);
              if(channel!=null)
              {
                byte reply_type=(byte)SSH_MSG_CHANNEL_FAILURE;
                if((new String(foo)).equals("exit-status"))
                {
                  i=buf.getInt();             // exit-status
                  channel.setExitStatus(i);
                  //      System.Console.WriteLine("exit-stauts: "+i);
                  //          channel.close();
                  reply_type=(byte)SSH_MSG_CHANNEL_SUCCESS;
                }
                if(reply)
                {
                  packet.reset();
                  buf.putByte(reply_type);
                  buf.putInt(channel.getRecipient());
                  write(packet);
                }
              }
              else
              {
              }
              break;
            case SSH_MSG_CHANNEL_OPEN:
              buf.getInt();
              buf.getShort();
              foo=buf.getString();
              String ctyp=new String(foo);
              //System.Console.WriteLine("type="+ctyp);
              if(!new String("forwarded-tcpip").equals(ctyp) &&
                !(new String("x11").equals(ctyp) && x11_forwarding))
              {
                System.Console.WriteLine("Session.run: CHANNEL OPEN "+ctyp);
                throw new IOException("Session.run: CHANNEL OPEN "+ctyp);
              }
              else
              {
                channel=Channel.getChannel(ctyp);
                addChannel(channel);
                channel.getData(buf);
                channel.init();

                packet.reset();
                buf.putByte((byte)SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
                buf.putInt(channel.getRecipient());
                buf.putInt(channel.id);
                buf.putInt(channel.lwsize);
                buf.putInt(channel.lmpsize);
                write(packet);
                Thread tmp=new Thread(channel);
                tmp.setName("Channel "+ctyp+" "+host);
                tmp.start();
                break;
              }
            case SSH_MSG_CHANNEL_SUCCESS:
              buf.getInt();
              buf.getShort();
              i=buf.getInt();
              channel=Channel.getChannel(i, this);
              if(channel==null)
              {
                break;
              }
              channel.reply=1;
              break;
            case SSH_MSG_CHANNEL_FAILURE:
              buf.getInt();
              buf.getShort();
              i=buf.getInt();
              channel=Channel.getChannel(i, this);
              if(channel==null)
              {
                break;
              }
              channel.reply=0;
              break;
            case SSH_MSG_GLOBAL_REQUEST:
              buf.getInt();
              buf.getShort();
              foo=buf.getString();       // request name
              reply=(buf.getByte()!=0);
              if(reply)
              {
                packet.reset();
                buf.putByte((byte)SSH_MSG_REQUEST_FAILURE);
                write(packet);
              }
              break;
            case SSH_MSG_REQUEST_FAILURE:
            case SSH_MSG_REQUEST_SUCCESS:
              Thread t=grr.getThread();
              if(t!=null)
              {
                grr.setReply(msgType==SSH_MSG_REQUEST_SUCCESS? 1 : 0);
                t.interrupt();
              }
              break;
            default:
              System.Console.WriteLine("Session.run: unsupported type "+msgType);
              throw new IOException("Unknown SSH message type "+msgType);
          }
        }
      }
      catch(Exception e)
      {
        //System.Console.WriteLine("# Session.run");
        //e.printStackTrace();
      }
      try
      {
        disconnect();
      }
      catch(NullReferenceException e)
      {
        //System.Console.WriteLine("@1");
        //e.printStackTrace();
      }
      catch(Exception e)
      {
        //System.Console.WriteLine("@2");
        //e.printStackTrace();
      }
      _isConnected=false;
    }

    /*
    public void finalize() throws Throwable{
      disconnect();
      jsch=null;
    }
    */

    public void disconnect()
    {
      if(!_isConnected) return;

      //System.Console.WriteLine(this+": disconnect");
      //Thread.dumpStack();
      /*
      for(int i=0; i<Channel.pool.size(); i++){
        try{
        Channel c=((Channel)(Channel.pool.elementAt(i)));
      if(c.session==this) c.eof();
        }
        catch(Exception e){
        }
      }
      */

      Channel.disconnect(this);

      _isConnected=false;

      PortWatcher.delPort(this);
      ChannelForwardedTCPIP.delPort(this);

      lock(connectThread)
      {
        connectThread.yield();
        connectThread.interrupt();
        connectThread=null;
      }
      thread=null;
      try
      {
        if(io!=null)
        {
          if(io.ins!=null) io.ins.Close();
          if(io.outs!=null) io.outs.Close();
          if(io.outs_ext!=null) io.outs_ext.Close();
        }
        if(proxy==null)
        {
          if(socket!=null)
            socket.close();
        }
        else
        {
          lock(proxy)
          {
            proxy.close();
          }
          proxy=null;
        }
      }
      catch(Exception e)
      {
        //      e.printStackTrace();
      }
      io=null;
      socket=null;
      //    lock(jsch.pool){
      //      jsch.pool.removeElement(this);
      //    }

      jsch.removeSession(this);

      //System.gc();
    }

    public void setPortForwardingL(int lport, String host, int rport) 
    {
      setPortForwardingL("127.0.0.1", lport, host,rport);
    }
    public void setPortForwardingL(String boundaddress, int lport, String host, int rport) 
    {
      setPortForwardingL(boundaddress, lport, host, rport, null);
    }
    public void setPortForwardingL(String boundaddress, int lport, String host, int rport, ServerSocketFactory ssf) 
    {
      PortWatcher pw=PortWatcher.addPort(this, boundaddress, lport, host, rport, ssf);
      Thread tmp=new Thread(pw);
      tmp.setName("PortWatcher Thread for "+host);
      tmp.start();
    }
    public void delPortForwardingL(int lport) 
    {
      delPortForwardingL("127.0.0.1", lport);
    }
    public void delPortForwardingL(String boundaddress, int lport) 
    {
      PortWatcher.delPort(this, boundaddress, lport);
    }
    public String[] getPortForwardingL() 
    {
      return PortWatcher.getPortForwarding(this);
    }

    public void setPortForwardingR(int rport, String host, int lport) 
    {
      setPortForwardingR(rport, host, lport, (SocketFactory)null);
    }
    public void setPortForwardingR(int rport, String host, int lport, SocketFactory sf) 
    {
      ChannelForwardedTCPIP.addPort(this, rport, host, lport, sf);
      setPortForwarding(rport);
    }

    public void setPortForwardingR(int rport, String daemon) 
    {
      setPortForwardingR(rport, daemon, null);
    }
    public void setPortForwardingR(int rport, String daemon, System.Object[] arg) 
    {
      ChannelForwardedTCPIP.addPort(this, rport, daemon, arg);
      setPortForwarding(rport);
    }

    private class GlobalRequestReply
    {
      private Thread thread=null;
      private int reply=-1;
      internal void setThread(Thread thread)
      {
        this.thread=thread;
        this.reply=-1;
      }
      internal Thread getThread(){ return thread; }
      internal void setReply(int reply){ this.reply=reply; }
      internal int getReply(){ return this.reply; }
    }
    private GlobalRequestReply grr=new GlobalRequestReply();
    private void setPortForwarding(int rport) 
    {
      lock(grr)
      {
        Buffer buf=new Buffer(100); // ??
        Packet packet=new Packet(buf);

        try
        {
          // byte SSH_MSG_GLOBAL_REQUEST 80
          // String "tcpip-forward"
          // bool want_reply
          // String  address_to_bind
          // uint32  port number to bind
          packet.reset();
          buf.putByte((byte) SSH_MSG_GLOBAL_REQUEST);
          buf.putString( new String( "tcpip-forward" ).getBytes());
          //      buf.putByte((byte)0);
          buf.putByte((byte)1);
          buf.putString(new String("0.0.0.0").getBytes());
          buf.putInt(rport);
          write(packet);
        }
        catch(Exception e)
        {
          throw new JSchException(e.ToString());
        }

        grr.setThread(Thread.currentThread());
        try{ Thread.Sleep(10000);}
        catch(Exception e)
        {
        }
        int reply=grr.getReply();
        grr.setThread(null);
        if(reply==0)
        {
          throw new JSchException("remote port forwarding failed for listen port "+rport);
        }
      }
    }
    public void delPortForwardingR(int rport) 
    {
      ChannelForwardedTCPIP.delPort(this, rport);
    }

    internal void addChannel(Channel channel)
    {
      channel.session=this;
    }
    public String getConfig(object name)
    {
      System.Object foo=null;
      if(config!=null)
      {
        foo=config.get(name);
        if(foo is String) return (String)foo;
        if(foo is string) return (string)foo;
      }
      foo=jsch.getConfig(name.ToString());
      if(foo is string) return (string)foo;
      if(foo is String) return (String)foo;
      return null;
    }
    //  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; }
    internal void setUserName(String foo){ this.username=foo; }
    public void setPassword(String foo){ this.password=foo; }
    public void setUserInfo(UserInfo userinfo){ this.userinfo=userinfo; }
    public void setInputStream(Stream In){ this.In=In; }
    public void setOutputStream(Stream Out){ this.Out=Out; }
    public void setX11Host(String host){ ChannelX11.setHost(host); }
    public void setX11Port(int port){ ChannelX11.setPort(port); }
    public void setX11Cookie(String cookie){ ChannelX11.setCookie(cookie); }

    public void setConfig(System.Collections.Hashtable foo)
    {
      setConfig( new Hashtable( foo ) );
    }

    public void setConfig(Hashtable foo)
    {
      if(config==null) config=new Hashtable();
      for(Enumeration e=foo.keys() ; e.hasMoreElements() ;) 
      {
        object key=e.nextElement();
        config.put(key, (foo.get(key)));
      }
    }
    public void setSocketFactory(SocketFactory foo){ socket_factory=foo;}
    public bool isConnected(){ return _isConnected; }
    public int getTimeout(){ return timeout; }
    public void setTimeout(int foo)  
    {
      if(socket==null)
      {
        if(foo<0)
        {
          throw new JSchException("invalid timeout value");
        }
        this.timeout=foo;
        return;
      }
      try
      {
        socket.setSoTimeout(foo);
        timeout=foo;
      }
      catch(Exception e)
      {
        throw new JSchException(e.ToString());
      }
    }
    public String getServerVersion()
    {
      return new String(V_S);
    }
    public String getClientVersion()
    {
      return new String(V_C);
    }
    public void setClientVersion(String cv)
    {
      V_C=cv.getBytes();
    }

    public void sendIgnore() 
    {
      Buffer buf=new Buffer();
      Packet packet=new Packet(buf);
      packet.reset();
      buf.putByte((byte)SSH_MSG_IGNORE);
      write(packet);
    }
    
    private static byte[] keepalivemsg=new String("keepalive@jcraft.com").getBytes();
    public void sendKeepAliveMsg()
    {
      Buffer buf=new Buffer();
      Packet packet=new Packet(buf);
      packet.reset();
      buf.putByte((byte)SSH_MSG_GLOBAL_REQUEST);
      buf.putString(keepalivemsg);
      buf.putByte((byte)1);
      write(packet);
    }

    private HostKey hostkey=null;
    public HostKey getHostKey(){ return hostkey; }
    public String getHost(){return host;}
    public String getUserName(){return username;}
    public int getPort(){return port;}

    public String getMac()
    {
      String mac="";
      if(s2cmac!=null)
        mac = s2cmac.getName();
      return mac;

    }
    public String getCipher()
    {
      String cipher="";
      if(s2ccipher!=null)
        cipher= s2ccipher.ToString();
      return cipher;
    }

    public int BufferLength
    {
      get{return this.buf.buffer.Length;}
    }
  }

}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.