Пример #1
0
 private void ProcessChannelLocalData(ISSHChannelEventReceiver receiver, PacketType pt, SSH2DataReader re) {
     switch(pt) {
         case PacketType.SSH_MSG_CHANNEL_DATA: {
             int len = re.ReadInt32();
             receiver.OnData(re.Image, re.Offset, len);
         }
             break;
         case PacketType.SSH_MSG_CHANNEL_EXTENDED_DATA: {
             int t = re.ReadInt32();
             byte[] data = re.ReadString();
             receiver.OnExtendedData(t, data);
         }
             break;
         case PacketType.SSH_MSG_CHANNEL_REQUEST: {
             string request = Encoding.ASCII.GetString(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
                 SSH2DataWriter wr = new SSH2DataWriter();
                 wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_FAILURE);
                 wr.Write(_remoteID);
                 TransmitPayload(wr.ToByteArray());
             }
         }
             break;
         case PacketType.SSH_MSG_CHANNEL_EOF:
             receiver.OnChannelEOF();
             break;
         case PacketType.SSH_MSG_CHANNEL_CLOSE:
             _connection.ChannelCollection.UnregisterChannelEventReceiver(_localID);
             receiver.OnChannelClosed();
             break;
         case PacketType.SSH_MSG_CHANNEL_FAILURE:
             receiver.OnMiscPacket((byte)pt, re.Image, re.Offset, re.Rest);
             break;
         default:
             receiver.OnMiscPacket((byte)pt, re.Image, re.Offset, re.Rest);
             Debug.WriteLine("Unknown Packet "+pt);
             break;
     }			
 }
Пример #2
0
        private void OpenShellOrSubsystem(ISSHChannelEventReceiver receiver, PacketType pt, SSH2DataReader reader, string scheme) {
            if(_negotiationStatus==NegotiationStatus.WaitingChannelConfirmation) {
                if(pt!=PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
                    if(pt!=PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE)
                        receiver.OnChannelError(new SSHException("opening channel failed; packet type="+pt));
                    else {
                        int errcode = reader.ReadInt32();
                        string msg = Encoding.ASCII.GetString(reader.ReadString());
                        receiver.OnChannelError(new SSHException(msg));
                    }
                    Close();
                }
                else {
                    _remoteID = reader.ReadInt32();
                    _allowedDataSize = reader.ReadInt32();
                    _serverMaxPacketSize = reader.ReadInt32();

                    //open pty
                    SSH2DataWriter wr = new SSH2DataWriter();
                    SSHConnectionParameter param = _connection.Param;
                    wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST);
                    wr.Write(_remoteID);
                    wr.Write("pty-req");
                    wr.Write(true);
                    wr.Write(param.TerminalName);
                    wr.Write(param.TerminalWidth);
                    wr.Write(param.TerminalHeight);
                    wr.Write(param.TerminalPixelWidth);
                    wr.Write(param.TerminalPixelHeight);
                    wr.WriteAsString(new byte[0]);
                    if(_connection.IsEventTracerAvailable)
                        _connection.TraceTransmissionEvent(PacketType.SSH_MSG_CHANNEL_REQUEST, "pty-req", "terminal={0} width={1} height={2}", param.TerminalName, param.TerminalWidth, param.TerminalHeight);
                    TransmitPayload(wr.ToByteArray());

                    _negotiationStatus = NegotiationStatus.WaitingPtyReqConfirmation;
                }
            }
            else if(_negotiationStatus==NegotiationStatus.WaitingPtyReqConfirmation) {
                if(pt!=PacketType.SSH_MSG_CHANNEL_SUCCESS) {
                    receiver.OnChannelError(new SSHException("opening pty failed"));
                    Close();
                }
                else {
                    //agent request (optional)
                    if(_connection.Param.AgentForward!=null) {
                        SSH2DataWriter wr = new SSH2DataWriter();
                        wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST);
                        wr.Write(_remoteID);
                        wr.Write("*****@*****.**");
                        wr.Write(true);
                        _connection.TraceTransmissionEvent(PacketType.SSH_MSG_CHANNEL_REQUEST, "auth-agent-req", "");
                        TransmitPayload(wr.ToByteArray());
                        _negotiationStatus = NegotiationStatus.WaitingAuthAgentReqConfirmation;
                    }
                    else {
                        OpenScheme(scheme);
                        _negotiationStatus = NegotiationStatus.WaitingShellConfirmation;
                    }
                }
            }
            else if(_negotiationStatus==NegotiationStatus.WaitingAuthAgentReqConfirmation) {
                if(pt!=PacketType.SSH_MSG_CHANNEL_SUCCESS && pt!=PacketType.SSH_MSG_CHANNEL_FAILURE) {
                    receiver.OnChannelError(new SSHException("auth-agent-req error"));
                    Close();
                }
                else { //auth-agent-req is optional
                    _connection.SetAgentForwardConfirmed(pt==PacketType.SSH_MSG_CHANNEL_SUCCESS);
                    _connection.TraceReceptionEvent(pt, "auth-agent-req");

                    OpenScheme(scheme);
                    _negotiationStatus = NegotiationStatus.WaitingShellConfirmation;
                }
            }
            else if(_negotiationStatus==NegotiationStatus.WaitingShellConfirmation) {
                if(pt!=PacketType.SSH_MSG_CHANNEL_SUCCESS) {
                    receiver.OnChannelError(new SSHException("Opening shell failed: packet type="+pt.ToString()));
                    Close();
                }
                else {
                    receiver.OnChannelReady();
                    _negotiationStatus = NegotiationStatus.Ready; //goal!
                }
            }
        }
Пример #3
0
        private void ProcessAgentForwardRequest(ISSHConnectionEventReceiver receiver, SSH2DataReader reader) {
            int remote_channel = reader.ReadInt32();
            int window_size = reader.ReadInt32(); //skip initial window size
            int servermaxpacketsize = reader.ReadInt32();
            TraceReceptionEvent("agent forward request", "");

            SSH2DataWriter wr = new SSH2DataWriter();
            IAgentForward af = _param.AgentForward;
            if(_agentForwardConfirmed && af!=null && af.CanAcceptForwarding()) {
                //send OPEN_CONFIRMATION
                AgentForwardingChannel ch = new AgentForwardingChannel(af);
                SSH2Channel channel = new SSH2Channel(this, ChannelType.AgentForward, this.ChannelCollection.RegisterChannelEventReceiver(null, ch).LocalID, remote_channel, servermaxpacketsize);
                ch.SetChannel(channel);
                wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
                wr.Write(remote_channel);
                wr.Write(channel.LocalChannelID);
                wr.Write(_param.WindowSize); //initial window size
                wr.Write(_param.MaxPacketSize); //max packet size
                TraceTransmissionEvent("granados confirmed agent-forwarding request", "");
            }
            else {
                wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE);
                wr.Write(remote_channel);
                wr.Write(0);
                wr.Write("reject");
                wr.Write(""); //lang tag
                TraceTransmissionEvent("granados rejected agent-forwarding request", "");
            }
            TransmitRawPayload(wr.ToByteArray());
        }
Пример #4
0
        private void AdjustWindowSize(PacketType pt, int data_length) {
            _leftWindowSize -= data_length;
            if(pt==PacketType.SSH_MSG_CHANNEL_EOF || pt==PacketType.SSH_MSG_CHANNEL_CLOSE) return; //window adjust is not necessary if the channel is being closed

            // need not send window size to server when the channel is not opened.
            if (_negotiationStatus!=NegotiationStatus.Ready) return; 

            while(_leftWindowSize <= _windowSize) {
                SSH2DataWriter adj = new SSH2DataWriter();
                adj.WritePacketType(PacketType.SSH_MSG_CHANNEL_WINDOW_ADJUST);
                adj.Write(_remoteID);
                adj.Write(_windowSize);
                TransmitPayload(adj.ToByteArray());
                _leftWindowSize += _windowSize;
                if(_connection.IsEventTracerAvailable)
                    _connection.TraceTransmissionEvent("SSH_MSG_CHANNEL_WINDOW_ADJUST", "adjusted to {0} by increasing {1}", _leftWindowSize, _windowSize);
            }
        }
Пример #5
0
        private string FormatBase64EncodedPublicKeyBody() {
            SSH2DataWriter wr = new SSH2DataWriter();
            wr.WriteString(SSH2Util.PublicKeyAlgorithmName(_keypair.Algorithm));
            _keypair.PublicKey.WriteTo(wr);

            return Encoding.ASCII.GetString(Base64.Encode(wr.ToByteArray()));
        }
Пример #6
0
 private DataFragment SendKEXDHINIT(Mode mode)
 {
     //Round1 computes and sends [e]
     byte[] sx = new byte[32];
     RngManager.GetSecureRng().GetBytes(sx);
     _x = new BigInteger(sx);
     _e = new BigInteger(2).modPow(_x, GetDiffieHellmanPrime(_cInfo._kexAlgorithm));
     SSH2DataWriter wr = new SSH2DataWriter();
     wr.WritePacketType(PacketType.SSH_MSG_KEXDH_INIT);
     wr.WriteBigInteger(_e);
     _status = Status.WAIT_KEXDH_REPLY;
     TraceTransmissionNegotiation(PacketType.SSH_MSG_KEXDH_INIT, "");
     if (mode == Mode.Synchronized)
         return SynchronizedTransmitRawPayload(wr.ToByteArray());
     else {
         TransmitRawPayload(wr.ToByteArray());
         return null;
     }
 }
Пример #7
0
        private AuthenticationResult UserAuth() {
            const string sn = "ssh-connection";
            if(_param.AuthenticationType==AuthenticationType.KeyboardInteractive) {
                SSH2DataWriter wr = OpenTransmissionPacket();
                wr.WritePacketType(PacketType.SSH_MSG_USERAUTH_REQUEST);
                wr.Write(_param.UserName);
                wr.Write(sn);
                wr.Write("keyboard-interactive");
                wr.Write(""); //lang
                wr.Write(""); //submethod
                TraceTransmissionEvent(PacketType.SSH_MSG_USERAUTH_REQUEST, "starting keyboard-interactive authentication");
                TransmitPacket(wr);
                _authenticationResult = ProcessAuthenticationResponse();
            }
            else {
                SSH2DataWriter wr = OpenTransmissionPacket();
                wr.WritePacketType(PacketType.SSH_MSG_USERAUTH_REQUEST);
                wr.Write(_param.UserName);
                if(_param.AuthenticationType==AuthenticationType.Password) {
                    //Password authentication
                    wr.Write(sn);
                    wr.Write("password");
                    wr.Write(false);
                    wr.Write(_param.Password);
                    TraceTransmissionEvent(PacketType.SSH_MSG_USERAUTH_REQUEST, "starting password authentication");
                }
                else {
                    //public key authentication
                    SSH2UserAuthKey kp = SSH2UserAuthKey.FromSECSHStyleFile(_param.IdentityFile, _param.Password);
                    SSH2DataWriter signsource = new SSH2DataWriter();
                    signsource.WriteAsString(_sessionID);
                    signsource.WritePacketType(PacketType.SSH_MSG_USERAUTH_REQUEST);
                    signsource.Write(_param.UserName);
                    signsource.Write(sn);
                    signsource.Write("publickey");
                    signsource.Write(true);
                    signsource.Write(SSH2Util.PublicKeyAlgorithmName(kp.Algorithm));
                    signsource.WriteAsString(kp.GetPublicKeyBlob());

                    SSH2DataWriter signpack = new SSH2DataWriter();
                    signpack.Write(SSH2Util.PublicKeyAlgorithmName(kp.Algorithm));
                    signpack.WriteAsString(kp.Sign(signsource.ToByteArray()));

                    wr.Write(sn);
                    wr.Write("publickey");
                    wr.Write(true);
                    wr.Write(SSH2Util.PublicKeyAlgorithmName(kp.Algorithm));
                    wr.WriteAsString(kp.GetPublicKeyBlob());
                    wr.WriteAsString(signpack.ToByteArray());
                    TraceTransmissionEvent(PacketType.SSH_MSG_USERAUTH_REQUEST, "starting public key authentication");
                }
                TransmitPacket(wr);

                _authenticationResult = ProcessAuthenticationResponse();
                if(_authenticationResult==AuthenticationResult.Failure)
                    throw new SSHException(Strings.GetString("AuthenticationFailed"));
            }
            return _authenticationResult;
        }
Пример #8
0
        private byte[] WriteToDataWriter() {
            SSH2DataWriter wr = new SSH2DataWriter();
            wr.WriteString(SSH2Util.PublicKeyAlgorithmName(_hostkey.Algorithm));
            if (_hostkey.Algorithm == PublicKeyAlgorithm.RSA) {
                RSAPublicKey rsa = (RSAPublicKey)_hostkey;
                wr.WriteBigInteger(rsa.Exponent);
                wr.WriteBigInteger(rsa.Modulus);
            }
            else if (_hostkey.Algorithm == PublicKeyAlgorithm.DSA) {
                DSAPublicKey dsa = (DSAPublicKey)_hostkey;
                wr.WriteBigInteger(dsa.P);
                wr.WriteBigInteger(dsa.Q);
                wr.WriteBigInteger(dsa.G);
                wr.WriteBigInteger(dsa.Y);
            }
            else
                throw new SSHException("Host key algorithm is unsupported");

            return wr.ToByteArray();
        }
Пример #9
0
        public byte[] ToByteArray(string passphrase)
        {
            //step1 key body
            SSH2DataWriter wr = new SSH2DataWriter();
            wr.Write(0); //this field is filled later
            if (_keypair.Algorithm == PublicKeyAlgorithm.RSA)
            {
                RSAKeyPair rsa = (RSAKeyPair)_keypair;
                RSAPublicKey pub = (RSAPublicKey)_keypair.PublicKey;
                wr.WriteBigIntWithBits(pub.Exponent);
                wr.WriteBigIntWithBits(rsa.D);
                wr.WriteBigIntWithBits(pub.Modulus);
                wr.WriteBigIntWithBits(rsa.U);
                wr.WriteBigIntWithBits(rsa.P);
                wr.WriteBigIntWithBits(rsa.Q);
            }
            else
            {
                DSAKeyPair dsa = (DSAKeyPair)_keypair;
                DSAPublicKey pub = (DSAPublicKey)_keypair.PublicKey;
                wr.Write(0);
                wr.WriteBigIntWithBits(pub.P);
                wr.WriteBigIntWithBits(pub.G);
                wr.WriteBigIntWithBits(pub.Q);
                wr.WriteBigIntWithBits(pub.Y);
                wr.WriteBigIntWithBits(dsa.X);
            }

            int padding_len = 0;
            if (passphrase != null)
            {
                padding_len = 8 - (int)wr.Length % 8;
                wr.Write(new byte[padding_len]);
            }
            byte[] encrypted_body = wr.ToByteArray();
            SSHUtil.WriteIntToByteArray(encrypted_body, 0, encrypted_body.Length - padding_len - 4);

            //encrypt if necessary
            if (passphrase != null)
            {
                Cipher c = CipherFactory.CreateCipher(SSHProtocol.SSH2, CipherAlgorithm.TripleDES, PassphraseToKey(passphrase, 24));
                Debug.Assert(encrypted_body.Length % 8 == 0);
                byte[] tmp = new Byte[encrypted_body.Length];
                c.Encrypt(encrypted_body, 0, encrypted_body.Length, tmp, 0);
                encrypted_body = tmp;
            }

            //step2 make binary key data
            wr = new SSH2DataWriter();
            wr.Write(MAGIC_VAL);
            wr.Write(0); //for total size
            wr.Write(_keypair.Algorithm == PublicKeyAlgorithm.RSA ?
                "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}" :
                "dl-modp{sign{dsa-nist-sha1},dh{plain}}");

            wr.Write(passphrase == null ? "none" : "3des-cbc");
            wr.WriteAsString(encrypted_body);

            byte[] rawdata = wr.ToByteArray();
            SSHUtil.WriteIntToByteArray(rawdata, 4, rawdata.Length); //fix total length

            return rawdata;
        }
Пример #10
0
        private void SendKEXINIT(Mode mode) {
            const string kex_algorithm = "diffie-hellman-group1-sha1";
            const string mac_algorithm = "hmac-sha1";
            SSH2DataWriter wr = new SSH2DataWriter();
            wr.WritePacketType(PacketType.SSH_MSG_KEXINIT);
            byte[] cookie = new byte[16];
            _param.Random.NextBytes(cookie);
            wr.Write(cookie);
            wr.Write(kex_algorithm); //    kex_algorithms
            wr.Write(FormatHostKeyAlgorithmDescription());            //    server_host_key_algorithms
            wr.Write(FormatCipherAlgorithmDescription());      //    encryption_algorithms_client_to_server
            wr.Write(FormatCipherAlgorithmDescription());      //    encryption_algorithms_server_to_client
            wr.Write(mac_algorithm);                  //    mac_algorithms_client_to_server
            wr.Write(mac_algorithm);                  //    mac_algorithms_server_to_client
            wr.Write("none");                       //    compression_algorithms_client_to_server
            wr.Write("none");                       //    compression_algorithms_server_to_client
            wr.Write("");                           //    languages_client_to_server
            wr.Write("");                           //    languages_server_to_client
            wr.Write(false); //Indicates whether a guessed key exchange packet follows
            wr.Write(0);       //reserved for future extension

            _clientKEXINITPayload = wr.ToByteArray();
            _status = Status.WAIT_KEXINIT;
            if(_connection.IsEventTracerAvailable) {
                StringBuilder bld = new StringBuilder();
                bld.Append("kex_algorithm=");                            bld.Append(kex_algorithm);
                bld.Append("; server_host_key_algorithms=");             bld.Append(FormatHostKeyAlgorithmDescription());
                bld.Append("; encryption_algorithms_client_to_server="); bld.Append(FormatCipherAlgorithmDescription());
                bld.Append("; encryption_algorithms_server_to_client="); bld.Append(FormatCipherAlgorithmDescription());
                bld.Append("; mac_algorithms_client_to_server=");        bld.Append(mac_algorithm);
                bld.Append("; mac_algorithms_server_to_client=");        bld.Append(mac_algorithm);
                TraceTransmissionNegotiation(PacketType.SSH_MSG_KEXINIT, bld.ToString());
            }
            TransmitRawPayload(_clientKEXINITPayload);
        }
Пример #11
0
 private DataFragment SendKEXDHINIT(Mode mode) {
     //Round1 computes and sends [e]
     byte[] sx = new byte[16];
     _param.Random.NextBytes(sx);
     _x = new BigInteger(sx);
     _e = new BigInteger(2).modPow(_x, DH_PRIME);
     SSH2DataWriter wr = new SSH2DataWriter();
     wr.WritePacketType(PacketType.SSH_MSG_KEXDH_INIT);
     wr.WriteBigInteger(_e);
     _status = Status.WAIT_KEXDH_REPLY;
     TraceTransmissionNegotiation(PacketType.SSH_MSG_KEXDH_INIT, "");
     if (mode == Mode.Synchronized)
         return SynchronizedTransmitRawPayload(wr.ToByteArray());
     else {
         TransmitRawPayload(wr.ToByteArray());
         return null;
     }
 }
Пример #12
0
        // Tests signature verification using test vectors from NIST CAVP.
        // http://csrc.nist.gov/groups/STM/cavp/digital-signatures.html
        internal static void TestSignatureVerification() {
            using (var reader = new System.IO.StreamReader(@"186-3ecdsatestvectors\SigVer.rsp")) {
                EllipticCurve curve = null;
                byte[] msg = null;
                BigInteger qx = null;
                BigInteger qy = null;
                BigInteger r = null;
                BigInteger s = null;
                string result = null;
                int testCount = 0;

                while (true) {
                    string line = reader.ReadLine();
                    if (line == null) {
                        break;
                    }
                    var match = System.Text.RegularExpressions.Regex.Match(line, @"\[([-\w]+),(SHA-\d+)\]");
                    if (match.Success) {
                        string curveName = "nist" + match.Groups[1].Value.ToLowerInvariant().Replace("-", "");
                        curve = FindByName(curveName);
                        if (curve != null) {
                            using (var hashFunc = ECDSAHashAlgorithmChooser.Choose(curve)) {
                                var hashName = "SHA-" + hashFunc.HashSize.ToString();
                                if (hashName == match.Groups[2].Value) {
                                    Debug.WriteLine("Test " + curve.CurveName);
                                }
                                else {
                                    // hash function doesn't match
                                    curve = null;
                                }
                            }
                        }
                        msg = null;
                        qx = qy = r = s = null;
                        result = null;
                        testCount = 0;
                        continue;
                    }

                    if (line.StartsWith("Msg = ") && curve != null) {
                        msg = BigIntegerConverter.ParseHex(line.Substring(6).Trim());
                        continue;
                    }

                    if (line.StartsWith("Qx = ") && curve != null) {
                        qx = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim()));
                        continue;
                    }

                    if (line.StartsWith("Qy = ") && curve != null) {
                        qy = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim()));
                        continue;
                    }

                    if (line.StartsWith("R = ") && curve != null) {
                        r = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(4).Trim()));
                        continue;
                    }

                    if (line.StartsWith("S = ") && curve != null) {
                        s = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(4).Trim()));
                        continue;
                    }

                    if (line.StartsWith("Result = ") && curve != null) {
                        result = line.Substring(9, 1);

                        if (msg != null && qx != null && qy != null && r != null && s != null) {
                            var pk = new ECDSAPublicKey(curve, new ECPoint(qx, qy));
                            var buf = new SSH2DataWriter();
                            buf.WriteBigInteger(r);
                            buf.WriteBigInteger(s);
                            var sig = buf.ToByteArray();
                            string verRes;
                            try {
                                pk.Verify(sig, msg);
                                verRes = "P";
                            }
                            catch (VerifyException) {
                                verRes = "F";
                            }
                            if (verRes != result) {
                                throw new Exception("verification result doesn't match");
                            }
                            ++testCount;
                            Debug.WriteLine("Pass #{0}", testCount);
                        }

                        msg = null;
                        qx = qy = r = s = null;
                        result = null;
                    }
                }
            }
        }
Пример #13
0
        /// <summary>
        /// Signing
        /// </summary>
        /// <param name="data">data to sign</param>
        /// <returns>signature blob</returns>
        public byte[] Sign(byte[] data) {
            BigInteger order = _curve.Order;

            byte[] hash = _publicKey.HashForSigning(data, _curve);
            BigInteger e = new BigInteger(hash);

            using (var rng = new RNGCryptoServiceProvider()) {

                BigInteger.ModulusRing nring = new BigInteger.ModulusRing(order);

                for (int tries = 0; tries < 10; ++tries) {
                    try {
                        ECDSAKeyPair tempKeyPair = _curve.GenerateKeyPair(rng);

                        BigInteger r = tempKeyPair.PublicKeyPoint.X % order;
                        if (r == 0) {
                            continue;
                        }

                        BigInteger k = tempKeyPair.PrivateKey;
                        BigInteger s = nring.Multiply(k.ModInverse(order), e + nring.Multiply(r, _privateKey));
                        if (s == 0) {
                            continue;
                        }

                        SSH2DataWriter writer = new SSH2DataWriter();
                        writer.WriteBigInteger(r);
                        writer.WriteBigInteger(s);

                        return writer.ToByteArray();
                    }
                    catch (Exception ex) {
                        Debug.WriteLine(ex);
                    }
                }
            }

            throw new SSHException(Strings.GetString("FailedSigning"));
        }
Пример #14
0
 private void OpenScheme(string scheme) {
     //open shell / subsystem
     SSH2DataWriter wr = new SSH2DataWriter();
     wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST);
     wr.Write(_remoteID);
     wr.Write(scheme);
     wr.Write(true);
     if(_command!=null)
         wr.Write(_command);
     TransmitPayload(wr.ToByteArray());
 }
Пример #15
0
        private bool ProcessKEXDHREPLY(DataFragment packet) {
            //Round2 receives response
            SSH2DataReader re = null;
            PacketType h;
            do {
                re = new SSH2DataReader(packet);
                h = re.ReadPacketType();
                if(h==PacketType.SSH_MSG_KEXDH_REPLY)
                    break; //successfully exit
                else if(h==PacketType.SSH_MSG_IGNORE || h==PacketType.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.ReadString();
            BigInteger f = re.ReadMPInt();
            byte[] signature = re.ReadString();
            Debug.Assert(re.Rest==0);

            //Round3 calc hash H
            SSH2DataWriter wr = new SSH2DataWriter();
            _k = f.modPow(_x, DH_PRIME);
            wr = new SSH2DataWriter();
            wr.Write(_cInfo._clientVersionString);
            wr.Write(_cInfo._serverVersionString);
            wr.WriteAsString(_clientKEXINITPayload);
            wr.WriteAsString(_serverKEXINITPayload);
            wr.WriteAsString(key_and_cert);
            wr.Write(_e);
            wr.Write(f);
            wr.Write(_k);
            _hash = new SHA1CryptoServiceProvider().ComputeHash(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;
        }
Пример #16
0
        // sending "exec" service for SCP protocol.
        private void ExecCommand(ISSHChannelEventReceiver receiver, PacketType pt, SSH2DataReader reader) {
            if(_negotiationStatus==NegotiationStatus.WaitingChannelConfirmation) {
                if(pt!=PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
                    if(pt!=PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE)
                        receiver.OnChannelError(new SSHException("opening channel failed; packet type="+pt));
                    else {
                        int errcode = reader.ReadInt32();
                        string msg = Encoding.ASCII.GetString(reader.ReadString());
                        receiver.OnChannelError(new SSHException(msg));
                    }
                    Close();
                }
                else {
                    _remoteID = reader.ReadInt32();
                    _allowedDataSize = reader.ReadInt32();
                    _serverMaxPacketSize = reader.ReadInt32();

                    // exec command
                    SSH2DataWriter wr = new SSH2DataWriter();
                    SSHConnectionParameter param = _connection.Param;
                    wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST);
                    wr.Write(_remoteID);
                    wr.Write("exec");  // "exec"
                    wr.Write(false);   // want confirm is disabled. (*)
                    wr.Write(_command);

                    if (_connection.IsEventTracerAvailable)
                        _connection.TraceTransmissionEvent("exec command","cmd={0}", _command);
                    TransmitPayload(wr.ToByteArray());

                    //confirmation is omitted
                    receiver.OnChannelReady();
                    _negotiationStatus = NegotiationStatus.Ready; //goal!
                }
            }
            else if(_negotiationStatus==NegotiationStatus.WaitingExecCmdConfirmation) {
                if(pt!=PacketType.SSH_MSG_CHANNEL_DATA) {
                    receiver.OnChannelError(new SSHException("exec command failed"));
                    Close();
                }
                else {
                    receiver.OnChannelReady();
                    _negotiationStatus = NegotiationStatus.Ready; //goal!
                }
            }
            else
                throw new SSHException("internal state error");
        }
Пример #17
0
        private byte[] DeriveKey(BigInteger key, byte[] hash, char ch, int length) {
            byte[] result = new byte[length];

            SSH2DataWriter wr = new SSH2DataWriter();
            wr.Write(key);
            wr.Write(hash);
            wr.Write((byte)ch);
            wr.Write(_sessionID);
            byte[] h1 = new SHA1CryptoServiceProvider().ComputeHash(wr.ToByteArray());
            if(h1.Length >= length) {
                Array.Copy(h1, 0, result, 0, length);
                return result;
            }
            else {
                wr = new SSH2DataWriter();
                wr.Write(key);
                wr.Write(_sessionID);
                wr.Write(h1);
                byte[] h2 = new SHA1CryptoServiceProvider().ComputeHash(wr.ToByteArray());
                if(h1.Length+h2.Length >= length) {
                    Array.Copy(h1, 0, result, 0, h1.Length);
                    Array.Copy(h2, 0, result, h1.Length, length-h1.Length);
                    return result;
                }
                else
                    throw new SSHException("necessary key length is too big"); //long key is not supported
            }
        }
Пример #18
0
        public void WritePrivatePartInSECSHStyleFile(Stream dest, string comment, string passphrase) {

            //step1 key body
            SSH2DataWriter wr = new SSH2DataWriter();
            wr.WriteInt32(0); //this field is filled later
            if (_keypair.Algorithm == PublicKeyAlgorithm.RSA) {
                RSAKeyPair rsa = (RSAKeyPair)_keypair;
                RSAPublicKey pub = (RSAPublicKey)_keypair.PublicKey;
                wr.WriteBigIntWithBits(pub.Exponent);
                wr.WriteBigIntWithBits(rsa.D);
                wr.WriteBigIntWithBits(pub.Modulus);
                wr.WriteBigIntWithBits(rsa.U);
                wr.WriteBigIntWithBits(rsa.P);
                wr.WriteBigIntWithBits(rsa.Q);
            }
            else {
                DSAKeyPair dsa = (DSAKeyPair)_keypair;
                DSAPublicKey pub = (DSAPublicKey)_keypair.PublicKey;
                wr.WriteInt32(0);
                wr.WriteBigIntWithBits(pub.P);
                wr.WriteBigIntWithBits(pub.G);
                wr.WriteBigIntWithBits(pub.Q);
                wr.WriteBigIntWithBits(pub.Y);
                wr.WriteBigIntWithBits(dsa.X);
            }

            int padding_len = 0;
            if (passphrase != null) {
                padding_len = 8 - (int)wr.Length % 8;
                wr.Write(new byte[padding_len]);
            }
            byte[] encrypted_body = wr.ToByteArray();
            SSHUtil.WriteIntToByteArray(encrypted_body, 0, encrypted_body.Length - padding_len - 4);

            //encrypt if necessary
            if (passphrase != null) {
                Cipher c = CipherFactory.CreateCipher(SSHProtocol.SSH2, CipherAlgorithm.TripleDES, PassphraseToKey(passphrase, 24));
                Debug.Assert(encrypted_body.Length % 8 == 0);
                byte[] tmp = new Byte[encrypted_body.Length];
                c.Encrypt(encrypted_body, 0, encrypted_body.Length, tmp, 0);
                encrypted_body = tmp;
            }

            //step2 make binary key data
            wr = new SSH2DataWriter();
            wr.WriteInt32(MAGIC_VAL);
            wr.WriteInt32(0); //for total size
            wr.WriteString(_keypair.Algorithm == PublicKeyAlgorithm.RSA ?
                "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}" :
                "dl-modp{sign{dsa-nist-sha1},dh{plain}}");

            wr.WriteString(passphrase == null ? "none" : "3des-cbc");
            wr.WriteAsString(encrypted_body);

            byte[] rawdata = wr.ToByteArray();
            SSHUtil.WriteIntToByteArray(rawdata, 4, rawdata.Length); //fix total length

            //step3 write final data
            StreamWriter sw = new StreamWriter(dest, Encoding.ASCII);
            sw.WriteLine("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----");
            if (comment != null)
                WriteKeyFileBlock(sw, "Comment: " + comment, true);
            WriteKeyFileBlock(sw, Encoding.ASCII.GetString(Base64.Encode(rawdata)), false);
            sw.WriteLine("---- END SSH2 ENCRYPTED PRIVATE KEY ----");
            sw.Close();

        }
Пример #19
0
        private void ProcessPortforwardingRequest(ISSHConnectionEventReceiver receiver, SSH2DataReader reader) {

            int remote_channel = reader.ReadInt32();
            int window_size = reader.ReadInt32(); //skip initial window size
            int servermaxpacketsize = reader.ReadInt32();
            string host = Encoding.ASCII.GetString(reader.ReadString());
            int port = reader.ReadInt32();
            string originator_ip = Encoding.ASCII.GetString(reader.ReadString());
            int originator_port = reader.ReadInt32();
            
            TraceReceptionEvent("port forwarding request", String.Format("host={0} port={1} originator-ip={2} originator-port={3}", host, port, originator_ip, originator_port));
            PortForwardingCheckResult r = receiver.CheckPortForwardingRequest(host,port,originator_ip,originator_port);
            SSH2DataWriter wr = new SSH2DataWriter();
            if(r.allowed) {
                //send OPEN_CONFIRMATION
                SSH2Channel channel = new SSH2Channel(this, ChannelType.ForwardedRemoteToLocal, this.ChannelCollection.RegisterChannelEventReceiver(null, r.channel).LocalID, remote_channel, servermaxpacketsize);
                wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
                wr.Write(remote_channel);
                wr.Write(channel.LocalChannelID);
                wr.Write(_param.WindowSize); //initial window size
                wr.Write(_param.MaxPacketSize); //max packet size
                receiver.EstablishPortforwarding(r.channel, channel);
                TraceTransmissionEvent("port-forwarding request is confirmed", "host={0} port={1} originator-ip={2} originator-port={3}", host, port, originator_ip, originator_port);
            }
            else {
                wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE);
                wr.Write(remote_channel);
                wr.Write(r.reason_code);
                wr.Write(r.reason_message);
                wr.Write(""); //lang tag
                TraceTransmissionEvent("port-forwarding request is rejected", "host={0} port={1} originator-ip={2} originator-port={3}", host, port, originator_ip, originator_port);
            }
            TransmitRawPayload(wr.ToByteArray());
        }
Пример #20
0
 public byte[] GetPublicKeyBlob() {
     SSH2DataWriter w = new SSH2DataWriter();
     w.WriteString(SSH2Util.PublicKeyAlgorithmName(_keypair.Algorithm));
     _keypair.PublicKey.WriteTo(w);
     return w.ToByteArray();
 }
Пример #21
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);
            }
        }