Beispiel #1
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();

        }
Beispiel #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!
                }
            }
        }
Beispiel #3
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;
        }
Beispiel #4
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;
        }
        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;
        }
Beispiel #6
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);
            }
        }