internal static ECDSAPublicKey ReadFrom(SSH2DataReader reader) { string curveName = reader.ReadString(); byte[] q = reader.ReadByteString(); EllipticCurve curve = EllipticCurve.FindByName(curveName); if (curve == null) { throw new SSHException(Strings.GetString("UnsupportedEllipticCurve") + " : " + curveName); } ECPoint p; if (!ECPoint.Parse(q, curve, out p)) { throw new SSHException(Strings.GetString("InvalidECPublicKey")); } return new ECDSAPublicKey(curve, p); }
private void SendSign(SSH2DataReader r) { byte[] blob = r.ReadByteString(); byte[] data = r.ReadByteString(); //Debug.WriteLine(String.Format("SignRequest blobsize={0} datasize={1}", blob.Length, data.Length)); SSH2UserAuthKey[] keys = _client.GetAvailableSSH2UserAuthKeys(); SSH2UserAuthKey key = FindKey(keys, blob); if (key == null) { TransmitWriter(OpenWriter(AgentForwadPacketType.SSH_AGENT_FAILURE)); _client.NotifyPublicKeyDidNotMatch(); } else { SSH2DataWriter signpack = new SSH2DataWriter(); signpack.WriteString(SSH2Util.PublicKeyAlgorithmName(key.Algorithm)); signpack.WriteAsString(key.Sign(data)); SSH2DataWriter wr = OpenWriter(AgentForwadPacketType.SSH2_AGENT_SIGN_RESPONSE); wr.WriteAsString(signpack.ToByteArray()); TransmitWriter(wr); } }
internal static EDDSAPublicKey ReadFrom(PublicKeyAlgorithm algorithm, SSH2DataReader reader) { EdwardsCurve curve = EdwardsCurve.FindByAlgorithm(algorithm); if (curve == null) { throw new SSHException(Strings.GetString("UnsupportedEllipticCurve")); } byte[] q = reader.ReadByteString(); return new EDDSAPublicKey(curve, q); }
private bool ProcessPacket(DataFragment packet) { SSH2DataReader r = new SSH2DataReader(packet); SSH2PacketType pt = (SSH2PacketType) r.ReadByte(); if (pt == SSH2PacketType.SSH_MSG_DISCONNECT) { int errorcode = r.ReadInt32(); _eventReceiver.OnConnectionClosed(); return false; } else if (_waitingForPortForwardingResponse) { if (pt != SSH2PacketType.SSH_MSG_REQUEST_SUCCESS) _eventReceiver.OnUnknownMessage((byte)pt, packet.GetBytes()); _waitingForPortForwardingResponse = false; return true; } else if (pt == SSH2PacketType.SSH_MSG_CHANNEL_OPEN) { string method = r.ReadString(); if (method == "forwarded-tcpip") ProcessPortforwardingRequest(_eventReceiver, r); else if (method.StartsWith("auth-agent")) //in most cases, method is "*****@*****.**" ProcessAgentForwardRequest(_eventReceiver, r); else { SSH2DataWriter wr = new SSH2DataWriter(); wr.WriteByte((byte)SSH2PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE); wr.WriteInt32(r.ReadInt32()); wr.WriteInt32(0); wr.WriteString("unknown method"); wr.WriteString(""); //lang tag TraceReceptionEvent("SSH_MSG_CHANNEL_OPEN rejected", "method={0}", method); } return true; } else if (pt >= SSH2PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION && pt <= SSH2PacketType.SSH_MSG_CHANNEL_FAILURE) { int local_channel = r.ReadInt32(); ChannelCollection.Entry e = this.ChannelCollection.FindChannelEntry(local_channel); if (e != null) ((SSH2Channel)e.Channel).ProcessPacket(e.Receiver, pt, r); else Debug.WriteLine("unexpected channel pt=" + pt + " local_channel=" + local_channel.ToString()); return true; } else if (pt == SSH2PacketType.SSH_MSG_IGNORE) { _eventReceiver.OnIgnoreMessage(r.ReadByteString()); return true; } else if (_asyncKeyExchanger != null) { _asyncKeyExchanger.AsyncProcessPacket(packet); return true; } else if (pt == SSH2PacketType.SSH_MSG_KEXINIT) { //Debug.WriteLine("Host sent KEXINIT"); _asyncKeyExchanger = new KeyExchanger(this, _sessionID); _asyncKeyExchanger.AsyncProcessPacket(packet); return true; } else { _eventReceiver.OnUnknownMessage((byte)pt, packet.GetBytes()); return false; } }
//synchronous reception internal DataFragment ReceivePacket() { while (true) { DataFragment data = _packetReceiver.WaitResponse(); SSH2PacketType pt = (SSH2PacketType)data[0]; //sneak //filter unnecessary packet if (pt == SSH2PacketType.SSH_MSG_IGNORE) { SSH2DataReader r = new SSH2DataReader(data); r.ReadByte(); //skip byte[] msg = r.ReadByteString(); if (_eventReceiver != null) _eventReceiver.OnIgnoreMessage(msg); TraceReceptionEvent(pt, msg); } else if (pt == SSH2PacketType.SSH_MSG_DEBUG) { SSH2DataReader r = new SSH2DataReader(data); r.ReadByte(); //skip bool f = r.ReadBool(); byte[] msg = r.ReadByteString(); if (_eventReceiver != null) _eventReceiver.OnDebugMessage(f, msg); TraceReceptionEvent(pt, msg); } else { return data; } } }
private void ProcessChannelLocalData(ISSHChannelEventReceiver receiver, SSH2PacketType pt, SSH2DataReader re) { switch (pt) { case SSH2PacketType.SSH_MSG_CHANNEL_DATA: { int len = re.ReadInt32(); DataFragment frag = re.GetRemainingDataView(len); receiver.OnData(frag.Data, frag.Offset, frag.Length); } break; case SSH2PacketType.SSH_MSG_CHANNEL_EXTENDED_DATA: { int t = re.ReadInt32(); byte[] data = re.ReadByteString(); receiver.OnExtendedData(t, data); } break; case SSH2PacketType.SSH_MSG_CHANNEL_REQUEST: { string request = re.ReadString(); bool reply = re.ReadBool(); if (request == "exit-status") { int status = re.ReadInt32(); } else if (reply) { //we reject unknown requests including keep-alive check Transmit( 0, new SSH2Packet(SSH2PacketType.SSH_MSG_CHANNEL_FAILURE) .WriteInt32(_remoteID) ); } } break; case SSH2PacketType.SSH_MSG_CHANNEL_EOF: receiver.OnChannelEOF(); break; case SSH2PacketType.SSH_MSG_CHANNEL_CLOSE: _connection.ChannelCollection.UnregisterChannelEventReceiver(_localID); receiver.OnChannelClosed(); break; case SSH2PacketType.SSH_MSG_CHANNEL_FAILURE: { DataFragment frag = re.GetRemainingDataView(); receiver.OnMiscPacket((byte)pt, frag.Data, frag.Offset, frag.Length); } break; default: { DataFragment frag = re.GetRemainingDataView(); receiver.OnMiscPacket((byte)pt, frag.Data, frag.Offset, frag.Length); } Debug.WriteLine("Unknown Packet " + pt); break; } }
private bool VerifyHostKey(byte[] K_S, byte[] signature, byte[] hash) { SSH2DataReader re1 = new SSH2DataReader(K_S); string algorithm = re1.ReadString(); if (algorithm != SSH2Util.PublicKeyAlgorithmName(_cInfo.HostKeyAlgorithm.Value)) throw new SSHException("Protocol Error: Host Key Algorithm Mismatch"); SSH2DataReader re2 = new SSH2DataReader(signature); algorithm = re2.ReadString(); if (algorithm != SSH2Util.PublicKeyAlgorithmName(_cInfo.HostKeyAlgorithm.Value)) throw new SSHException("Protocol Error: Host Key Algorithm Mismatch"); byte[] sigbody = re2.ReadByteString(); Debug.Assert(re2.RemainingDataLength == 0); if (_cInfo.HostKeyAlgorithm == PublicKeyAlgorithm.RSA) { RSAPublicKey pk = ReadRSAPublicKey(re1, sigbody, hash); pk.VerifyWithSHA1(sigbody, new SHA1CryptoServiceProvider().ComputeHash(hash)); _cInfo.HostKey = pk; } else if (_cInfo.HostKeyAlgorithm == PublicKeyAlgorithm.DSA) { DSAPublicKey pk = ReadDSAPublicKey(re1, sigbody, hash); pk.Verify(sigbody, new SHA1CryptoServiceProvider().ComputeHash(hash)); _cInfo.HostKey = pk; } else throw new SSHException("Bad host key algorithm " + _cInfo.HostKeyAlgorithm); //ask the client whether he accepts the host key if (!_startedByHost && _param.VerifySSHHostKey != null) { if (!_param.VerifySSHHostKey(_cInfo.GetSSHHostKeyInformationProvider())) { return false; } } return true; }
private bool ProcessKEXDHREPLY(DataFragment packet) { //Round2 receives response SSH2DataReader re = null; SSH2PacketType h; do { re = new SSH2DataReader(packet); h = (SSH2PacketType) re.ReadByte(); if (h == SSH2PacketType.SSH_MSG_KEXDH_REPLY) break; //successfully exit else if (h == SSH2PacketType.SSH_MSG_IGNORE || h == SSH2PacketType.SSH_MSG_DEBUG) { //continue packet = _connection.ReceivePacket(); } else throw new SSHException(String.Format("KeyExchange response is not KEXDH_REPLY but {0}", h)); } while (true); byte[] key_and_cert = re.ReadByteString(); BigInteger f = re.ReadMPInt(); byte[] signature = re.ReadByteString(); Debug.Assert(re.RemainingDataLength == 0); //Round3 calc hash H SSH2DataWriter wr = new SSH2DataWriter(); _k = f.ModPow(_x, GetDiffieHellmanPrime(_cInfo.KEXAlgorithm.Value)); wr = new SSH2DataWriter(); wr.WriteString(_cInfo.ClientVersionString); wr.WriteString(_cInfo.ServerVersionString); wr.WriteAsString(_clientKEXINITPayload); wr.WriteAsString(_serverKEXINITPayload); wr.WriteAsString(key_and_cert); wr.WriteBigInteger(_e); wr.WriteBigInteger(f); wr.WriteBigInteger(_k); _hash = KexComputeHash(wr.ToByteArray()); _connection.TraceReceptionEvent(h, "verifying host key"); if (!VerifyHostKey(key_and_cert, signature, _hash)) return false; //Debug.WriteLine("hash="+DebugUtil.DumpByteArray(hash)); if (_sessionID == null) _sessionID = _hash; return true; }