예제 #1
0
        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);
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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;
            }
        }
예제 #5
0
        //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;
                }
            }
        }
예제 #6
0
 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;
     }
 }
예제 #7
0
        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;
        }
예제 #8
0
        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;
        }