public ChannelAgentForwarding() : base() { SetLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX); SetLocalWindowSize(LOCAL_WINDOW_SIZE_MAX); SetLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE); type = Util.Str2byte("*****@*****.**"); rbuf = new Buffer(); rbuf.Reset(); //wbuf=new Buffer(rmpsize); //packet=new Packet(wbuf); mbuf = new Buffer(); connected = true; }
/// <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; }
/// <exception cref="NSch.JSchException"></exception> /// <exception cref="System.IO.IOException"></exception> private void Start_discard(Buffer buf, NSch.Cipher cipher, MAC mac, int packet_length , int discard) { MAC discard_mac = null; if (!cipher.IsCBC()) { throw new JSchException("Packet corrupt"); } if (packet_length != PACKET_MAX_SIZE && mac != null) { discard_mac = mac; } discard -= buf.index; while (discard > 0) { buf.Reset(); int len = discard > buf.buffer.Length ? buf.buffer.Length : discard; io.GetByte(buf.buffer, 0, len); if (discard_mac != null) { discard_mac.Update(buf.buffer, 0, len); } discard -= len; } if (discard_mac != null) { discard_mac.DoFinal(buf.buffer, 0); } throw new JSchException("Packet corrupt"); }
/// <exception cref="System.IO.IOException"></exception> internal override void Write(byte[] foo, int s, int l) { if (packet == null) { wbuf = new Buffer(rmpsize); packet = new Packet(wbuf); } rbuf.Shift(); if (rbuf.buffer.Length < rbuf.index + l) { byte[] newbuf = new byte[rbuf.s + l]; System.Array.Copy(rbuf.buffer, 0, newbuf, 0, rbuf.buffer.Length); rbuf.buffer = newbuf; } rbuf.PutByte(foo, s, l); int mlen = rbuf.GetInt(); if (mlen > rbuf.GetLength()) { rbuf.s -= 4; return; } int typ = rbuf.GetByte(); Session _session = null; try { _session = GetSession(); } catch (JSchException e) { throw new IOException(e.ToString()); } IdentityRepository irepo = _session.jsch.GetIdentityRepository(); UserInfo userinfo = _session.GetUserInfo(); mbuf.Reset(); if (typ == SSH2_AGENTC_REQUEST_IDENTITIES) { mbuf.PutByte(SSH2_AGENT_IDENTITIES_ANSWER); ArrayList identities = irepo.GetIdentities(); lock (identities) { int count = 0; for (int i = 0; i < identities.Count; i++) { Identity identity = (Identity)(identities[i]); if (identity.GetPublicKeyBlob() != null) { count++; } } mbuf.PutInt(count); for (int i_1 = 0; i_1 < identities.Count; i_1++) { Identity identity = (Identity)(identities[i_1]); byte[] pubkeyblob = identity.GetPublicKeyBlob(); if (pubkeyblob == null) { continue; } mbuf.PutString(pubkeyblob); mbuf.PutString(Util.empty); } } } else { if (typ == SSH_AGENTC_REQUEST_RSA_IDENTITIES) { mbuf.PutByte(SSH_AGENT_RSA_IDENTITIES_ANSWER); mbuf.PutInt(0); } else { if (typ == SSH2_AGENTC_SIGN_REQUEST) { byte[] blob = rbuf.GetString(); byte[] data = rbuf.GetString(); int flags = rbuf.GetInt(); // if((flags & 1)!=0){ //SSH_AGENT_OLD_SIGNATURE // old OpenSSH 2.0, 2.1 // datafellows = SSH_BUG_SIGBLOB; // } ArrayList identities = irepo.GetIdentities(); Identity identity = null; lock (identities) { for (int i = 0; i < identities.Count; i++) { Identity _identity = (Identity)(identities[i]); if (_identity.GetPublicKeyBlob() == null) { continue; } if (!Util.Array_equals(blob, _identity.GetPublicKeyBlob())) { continue; } if (_identity.IsEncrypted()) { if (userinfo == null) { continue; } while (_identity.IsEncrypted()) { if (!userinfo.PromptPassphrase("Passphrase for " + _identity.GetName())) { break; } string _passphrase = userinfo.GetPassphrase(); if (_passphrase == null) { break; } byte[] passphrase = Util.Str2byte(_passphrase); try { if (_identity.SetPassphrase(passphrase)) { break; } } catch (JSchException) { break; } } } if (!_identity.IsEncrypted()) { identity = _identity; break; } } } byte[] signature = null; if (identity != null) { signature = identity.GetSignature(data); } if (signature == null) { mbuf.PutByte(SSH2_AGENT_FAILURE); } else { mbuf.PutByte(SSH2_AGENT_SIGN_RESPONSE); mbuf.PutString(signature); } } else { if (typ == SSH2_AGENTC_REMOVE_IDENTITY) { byte[] blob = rbuf.GetString(); irepo.Remove(blob); mbuf.PutByte(SSH_AGENT_SUCCESS); } else { if (typ == SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES) { mbuf.PutByte(SSH_AGENT_SUCCESS); } else { if (typ == SSH2_AGENTC_REMOVE_ALL_IDENTITIES) { irepo.RemoveAll(); mbuf.PutByte(SSH_AGENT_SUCCESS); } else { if (typ == SSH2_AGENTC_ADD_IDENTITY) { int fooo = rbuf.GetLength(); byte[] tmp = new byte[fooo]; rbuf.GetByte(tmp); bool result = irepo.Add(tmp); mbuf.PutByte(result ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); } else { rbuf.Skip(rbuf.GetLength() - 1); mbuf.PutByte(SSH_AGENT_FAILURE); } } } } } } } byte[] response = new byte[mbuf.GetLength()]; mbuf.GetByte(response); Send(response); }
/// <exception cref="System.IO.IOException"></exception> private void Fill(Buffer buf, int len) { buf.Reset(); Fill(buf.buffer, 0, len); buf.Skip(len); }
/// <exception cref="System.Exception"></exception> public override bool Next(Buffer _buf) { int i; int j; switch (state) { case SSH_MSG_KEX_DH_GEX_GROUP: { // byte SSH_MSG_KEX_DH_GEX_GROUP(31) // mpint p, safe prime // mpint g, generator for subgroup in GF (p) _buf.GetInt(); _buf.GetByte(); j = _buf.GetByte(); if (j != SSH_MSG_KEX_DH_GEX_GROUP) { System.Console.Error.WriteLine("type: must be SSH_MSG_KEX_DH_GEX_GROUP " + j); return(false); } p = _buf.GetMPInt(); g = _buf.GetMPInt(); dh.SetP(p); dh.SetG(g); // The client responds with: // byte SSH_MSG_KEX_DH_GEX_INIT(32) // mpint e <- g^x mod p // x is a random number (1 < x < (p-1)/2) e = dh.GetE(); packet.Reset(); buf.PutByte(unchecked ((byte)SSH_MSG_KEX_DH_GEX_INIT)); buf.PutMPInt(e); session.Write(packet); if (JSch.GetLogger().IsEnabled(Logger.INFO)) { JSch.GetLogger().Log(Logger.INFO, "SSH_MSG_KEX_DH_GEX_INIT sent"); JSch.GetLogger().Log(Logger.INFO, "expecting SSH_MSG_KEX_DH_GEX_REPLY"); } state = SSH_MSG_KEX_DH_GEX_REPLY; return(true); } case SSH_MSG_KEX_DH_GEX_REPLY: { //break; // The server responds with: // byte SSH_MSG_KEX_DH_GEX_REPLY(33) // string server public host key and certificates (K_S) // mpint f // string signature of H j = _buf.GetInt(); j = _buf.GetByte(); j = _buf.GetByte(); if (j != SSH_MSG_KEX_DH_GEX_REPLY) { System.Console.Error.WriteLine("type: must be SSH_MSG_KEX_DH_GEX_REPLY " + j); return(false); } K_S = _buf.GetString(); // K_S is server_key_blob, which includes .... // string ssh-dss // impint p of dsa // impint q of dsa // impint g of dsa // impint pub_key of dsa //System.err.print("K_S: "); dump(K_S, 0, K_S.length); byte[] f = _buf.GetMPInt(); byte[] sig_of_H = _buf.GetString(); dh.SetF(f); K = dh.GetK(); //The hash H is computed as the HASH hash of the concatenation of the //following: // string V_C, the client's version string (CR and NL excluded) // string V_S, the server's version string (CR and NL excluded) // string I_C, the payload of the client's SSH_MSG_KEXINIT // string I_S, the payload of the server's SSH_MSG_KEXINIT // string K_S, the host key // uint32 min, minimal size in bits of an acceptable group // uint32 n, preferred size in bits of the group the server should send // uint32 max, maximal size in bits of an acceptable group // mpint p, safe prime // mpint g, generator for subgroup // mpint e, exchange value sent by the client // mpint f, exchange value sent by the server // mpint K, the shared secret // This value is called the exchange hash, and it is used to authenti- // cate the key exchange. buf.Reset(); buf.PutString(V_C); buf.PutString(V_S); buf.PutString(I_C); buf.PutString(I_S); buf.PutString(K_S); buf.PutInt(min); buf.PutInt(preferred); buf.PutInt(max); buf.PutMPInt(p); buf.PutMPInt(g); buf.PutMPInt(e); buf.PutMPInt(f); buf.PutMPInt(K); byte[] foo = new byte[buf.GetLength()]; buf.GetByte(foo); sha.Update(foo, 0, foo.Length); H = sha.Digest(); // System.err.print("H -> "); dump(H, 0, H.length); i = 0; j = 0; j = ((K_S[i++] << 24) & unchecked ((int)(0xff000000))) | ((K_S[i++] << 16) & unchecked ( (int)(0x00ff0000))) | ((K_S[i++] << 8) & unchecked ((int)(0x0000ff00))) | ((K_S[i ++]) & unchecked ((int)(0x000000ff))); string alg = Util.Byte2str(K_S, i, j); i += j; bool result = false; if (alg.Equals("ssh-rsa")) { byte[] tmp; byte[] ee; byte[] n; type = RSA; j = ((K_S[i++] << 24) & unchecked ((int)(0xff000000))) | ((K_S[i++] << 16) & unchecked ( (int)(0x00ff0000))) | ((K_S[i++] << 8) & unchecked ((int)(0x0000ff00))) | ((K_S[i ++]) & unchecked ((int)(0x000000ff))); tmp = new byte[j]; System.Array.Copy(K_S, i, tmp, 0, j); i += j; ee = tmp; j = ((K_S[i++] << 24) & unchecked ((int)(0xff000000))) | ((K_S[i++] << 16) & unchecked ( (int)(0x00ff0000))) | ((K_S[i++] << 8) & unchecked ((int)(0x0000ff00))) | ((K_S[i ++]) & unchecked ((int)(0x000000ff))); tmp = new byte[j]; System.Array.Copy(K_S, i, tmp, 0, j); i += j; n = tmp; // SignatureRSA sig=new SignatureRSA(); // sig.init(); NSch.SignatureRSA sig = null; try { Type c = Sharpen.Runtime.GetType(session.GetConfig("signature.rsa")); sig = (NSch.SignatureRSA)(System.Activator.CreateInstance(c)); sig.Init(); } catch (Exception ex) { System.Console.Error.WriteLine(ex); } sig.SetPubKey(ee, n); sig.Update(H); result = sig.Verify(sig_of_H); if (JSch.GetLogger().IsEnabled(Logger.INFO)) { JSch.GetLogger().Log(Logger.INFO, "ssh_rsa_verify: signature " + result); } } else { if (alg.Equals("ssh-dss")) { byte[] q = null; byte[] tmp; type = DSS; j = ((K_S[i++] << 24) & unchecked ((int)(0xff000000))) | ((K_S[i++] << 16) & unchecked ( (int)(0x00ff0000))) | ((K_S[i++] << 8) & unchecked ((int)(0x0000ff00))) | ((K_S[i ++]) & unchecked ((int)(0x000000ff))); tmp = new byte[j]; System.Array.Copy(K_S, i, tmp, 0, j); i += j; p = tmp; j = ((K_S[i++] << 24) & unchecked ((int)(0xff000000))) | ((K_S[i++] << 16) & unchecked ( (int)(0x00ff0000))) | ((K_S[i++] << 8) & unchecked ((int)(0x0000ff00))) | ((K_S[i ++]) & unchecked ((int)(0x000000ff))); tmp = new byte[j]; System.Array.Copy(K_S, i, tmp, 0, j); i += j; q = tmp; j = ((K_S[i++] << 24) & unchecked ((int)(0xff000000))) | ((K_S[i++] << 16) & unchecked ( (int)(0x00ff0000))) | ((K_S[i++] << 8) & unchecked ((int)(0x0000ff00))) | ((K_S[i ++]) & unchecked ((int)(0x000000ff))); tmp = new byte[j]; System.Array.Copy(K_S, i, tmp, 0, j); i += j; g = tmp; j = ((K_S[i++] << 24) & unchecked ((int)(0xff000000))) | ((K_S[i++] << 16) & unchecked ( (int)(0x00ff0000))) | ((K_S[i++] << 8) & unchecked ((int)(0x0000ff00))) | ((K_S[i ++]) & unchecked ((int)(0x000000ff))); tmp = new byte[j]; System.Array.Copy(K_S, i, tmp, 0, j); i += j; f = tmp; // SignatureDSA sig=new SignatureDSA(); // sig.init(); NSch.SignatureDSA sig = null; try { Type c = Sharpen.Runtime.GetType(session.GetConfig("signature.dss")); sig = (NSch.SignatureDSA)(System.Activator.CreateInstance(c)); sig.Init(); } catch (Exception ex) { System.Console.Error.WriteLine(ex); } sig.SetPubKey(f, p, q, g); sig.Update(H); result = sig.Verify(sig_of_H); if (JSch.GetLogger().IsEnabled(Logger.INFO)) { JSch.GetLogger().Log(Logger.INFO, "ssh_dss_verify: signature " + result); } } else { System.Console.Error.WriteLine("unknown alg"); } } state = STATE_END; return(result); } } return(false); }