/// <exception cref="System.Exception"></exception> public virtual Buffer Read(Buffer buf) { int j = 0; while (true) { buf.Reset(); io.GetByte(buf.buffer, buf.index, s2ccipher_size); buf.index += s2ccipher_size; if (s2ccipher != null) { s2ccipher.Update(buf.buffer, 0, s2ccipher_size, buf.buffer, 0); } j = ((buf.buffer[0] << 24) & unchecked((int)(0xff000000))) | ((buf.buffer[1] << 16 ) & unchecked((int)(0x00ff0000))) | ((buf.buffer[2] << 8) & unchecked((int)(0x0000ff00 ))) | ((buf.buffer[3]) & unchecked((int)(0x000000ff))); // RFC 4253 6.1. Maximum Packet Length if (j < 5 || j > PACKET_MAX_SIZE) { Start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE); } int need = j + 4 - s2ccipher_size; //if(need<0){ // throw new IOException("invalid data"); //} if ((buf.index + need) > buf.buffer.Length) { byte[] foo = new byte[buf.index + need]; System.Array.Copy(buf.buffer, 0, foo, 0, buf.index); buf.buffer = foo; } if ((need % s2ccipher_size) != 0) { string message = "Bad packet length " + need; if (JSch.GetLogger().IsEnabled(Logger.FATAL)) { JSch.GetLogger().Log(Logger.FATAL, message); } Start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE - s2ccipher_size); } if (need > 0) { io.GetByte(buf.buffer, buf.index, need); buf.index += (need); if (s2ccipher != null) { s2ccipher.Update(buf.buffer, s2ccipher_size, need, buf.buffer, s2ccipher_size); } } if (s2cmac != null) { s2cmac.Update(seqi); s2cmac.Update(buf.buffer, 0, buf.index); s2cmac.DoFinal(s2cmac_result1, 0); io.GetByte(s2cmac_result2, 0, s2cmac_result2.Length); if (!Arrays.Equals(s2cmac_result1, s2cmac_result2)) { if (need > PACKET_MAX_SIZE) { throw new IOException("MAC Error"); } Start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE - need); continue; } } 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.GetCommand() & unchecked((int)(0xff)); //System.err.println("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(); throw new JSchException("SSH_MSG_DISCONNECT: " + reason_code + " " + Util.Byte2str (description) + " " + Util.Byte2str(language_tag)); } else { //break; if (type == SSH_MSG_IGNORE) { } else { if (type == SSH_MSG_UNIMPLEMENTED) { buf.Rewind(); buf.GetInt(); buf.GetShort(); int reason_id = buf.GetInt(); if (JSch.GetLogger().IsEnabled(Logger.INFO)) { JSch.GetLogger().Log(Logger.INFO, "Received SSH_MSG_UNIMPLEMENTED for " + reason_id ); } } else { if (type == SSH_MSG_DEBUG) { buf.Rewind(); buf.GetInt(); buf.GetShort(); } 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 { if (type == UserAuth.SSH_MSG_USERAUTH_SUCCESS) { isAuthed = true; if (inflater == null && deflater == null) { string method; method = guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS]; InitDeflater(method); method = guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC]; InitInflater(method); } break; } else { break; } } } } } } } buf.Rewind(); return buf; }
public virtual 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; int stimeout = 0; try { while (isConnected && thread != null) { try { buf = Read(buf); stimeout = 0; } catch (ThreadInterruptedException ee) { if (!in_kex && stimeout < serverAliveCountMax) { SendKeepAliveMsg(); stimeout++; continue; } throw; } int msgType = buf.GetCommand() & unchecked((int)(0xff)); if (kex != null && kex.GetState() == msgType) { kex_start_time = Runtime.CurrentTimeMillis(); bool result = kex.Next(buf); if (!result) { throw new JSchException("verify: " + result); } continue; } switch (msgType) { case SSH_MSG_KEXINIT: { //System.err.println("KEXINIT"); kex = Receive_kexinit(buf); break; } case SSH_MSG_NEWKEYS: { //System.err.println("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; } if (length[0] == 0) { break; } try { channel.Write(foo, start[0], length[0]); } catch (Exception) { //System.err.println(e); try { channel.Disconnect(); } catch (Exception) { } break; } int len = length[0]; channel.SetLocalWindowSize(channel.lwsize - len); if (channel.lwsize < channel.lwsize_max / 2) { packet.Reset(); buf.PutByte(unchecked((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.err.println("stderr: "+new String(foo,start[0],length[0])); if (channel == null) { break; } if (length[0] == 0) { break; } channel.Write_ext(foo, start[0], length[0]); int len = length[0]; channel.SetLocalWindowSize(channel.lwsize - len); if (channel.lwsize < channel.lwsize_max / 2) { packet.Reset(); buf.PutByte(unchecked((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(); } 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(); } break; } case SSH_MSG_CHANNEL_OPEN_CONFIRMATION: { buf.GetInt(); buf.GetShort(); i = buf.GetInt(); channel = Channel.GetChannel(i, this); if (channel == null) { } //break; int r = buf.GetInt(); long rws = buf.GetUInt(); int rps = buf.GetInt(); channel.SetRemoteWindowSize(rws); channel.SetRemotePacketSize(rps); channel.SetRecipient(r); 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 = unchecked((byte)SSH_MSG_CHANNEL_FAILURE); if ((Util.Byte2str(foo)).Equals("exit-status")) { i = buf.GetInt(); // exit-status channel.SetExitStatus(i); reply_type = unchecked((byte)SSH_MSG_CHANNEL_SUCCESS); } if (reply) { packet.Reset(); buf.PutByte(reply_type); buf.PutInt(channel.GetRecipient()); Write(packet); } } break; } case SSH_MSG_CHANNEL_OPEN: { buf.GetInt(); buf.GetShort(); foo = buf.GetString(); string ctyp = Util.Byte2str(foo); if (!"forwarded-tcpip".Equals(ctyp) && !("x11".Equals(ctyp) && x11_forwarding) && !("*****@*****.**".Equals(ctyp) && agent_forwarding)) { //System.err.println("Session.run: CHANNEL OPEN "+ctyp); //throw new IOException("Session.run: CHANNEL OPEN "+ctyp); packet.Reset(); buf.PutByte(unchecked((byte)SSH_MSG_CHANNEL_OPEN_FAILURE)); buf.PutInt(buf.GetInt()); buf.PutInt(Channel.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED); buf.PutString(Util.empty); buf.PutString(Util.empty); Write(packet); } else { channel = Channel.GetChannel(ctyp); AddChannel(channel); channel.GetData(buf); channel.Init(); Sharpen.Thread tmp = new Sharpen.Thread(channel); tmp.SetName("Channel " + ctyp + " " + host); if (daemon_thread) { tmp.SetDaemon(daemon_thread); } tmp.Start(); break; } goto case SSH_MSG_CHANNEL_SUCCESS; } 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 bool reply = (buf.GetByte() != 0); if (reply) { packet.Reset(); buf.PutByte(unchecked((byte)SSH_MSG_REQUEST_FAILURE)); Write(packet); } break; } case SSH_MSG_REQUEST_FAILURE: case SSH_MSG_REQUEST_SUCCESS: { Sharpen.Thread t = grr.GetThread(); if (t != null) { grr.SetReply(msgType == SSH_MSG_REQUEST_SUCCESS ? 1 : 0); t.Interrupt(); } break; } default: { //System.err.println("Session.run: unsupported type "+msgType); throw new IOException("Unknown SSH message type " + msgType); } } } } catch (Exception e) { in_kex = false; if (JSch.GetLogger().IsEnabled(Logger.INFO)) { JSch.GetLogger().Log(Logger.INFO, "Caught an exception, leaving main loop due to " + e.Message); } } //System.err.println("# Session.run"); //e.printStackTrace(); try { Disconnect(); } catch (ArgumentNullException) { } catch (Exception) { } //System.err.println("@1"); //e.printStackTrace(); //System.err.println("@2"); //e.printStackTrace(); isConnected = false; }