📄 session.cs
字号:
#region Licences
// Copyright (C) 2005 Sebastian Faltoni <sebastian@dotnetfireball.net>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#endregion Licences
//using System;
using System.IO;
using System.Runtime.CompilerServices;
using Fireball.Ssh.java;
using Fireball.Ssh.java.util;
using Fireball.Ssh.java.net;
using Fireball.Ssh.java.lang;
using Exception = System.Exception;
using NullReferenceException = System.NullReferenceException;
using ThreadInterruptedException = System.Threading.ThreadInterruptedException;
namespace Fireball.Ssh.jsch
{
public class Session : Runnable
{
private static String version="SharpSSH-"+Fireball.Ssh.SshBase.Version.ToString();
// 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=("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(this, host, port, connectTimeout);
io.setInputStream(proxy.getInputStream());
io.setOutputStream(proxy.getOutputStream());
socket=proxy.getSocket();
}
}
if(connectTimeout>0 && socket!=null)
{
socket.setSoTimeout(connectTimeout);
}
_isConnected=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==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]; Fireball.Ssh.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];
Fireball.Ssh.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
{
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().toLowerCase();
// methods: publickey,password,keyboard-interactive
if(methods==null)
{
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)
{
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)
{
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -