예제 #1
0
        private DataFragment ReceivePacket()
        {
            while (true)
            {
                DataFragment data = _packetReceiver.WaitResponse();

                PacketType pt = (PacketType)data.ByteAt(0); //shortcut
                if (pt == PacketType.SSH_MSG_IGNORE)
                {
                    SSH1DataReader r = new SSH1DataReader(data);
                    r.ReadPacketType();
                    if (_eventReceiver != null)
                    {
                        _eventReceiver.OnIgnoreMessage(r.ReadString());
                    }
                }
                else if (pt == PacketType.SSH_MSG_DEBUG)
                {
                    SSH1DataReader r = new SSH1DataReader(data);
                    r.ReadPacketType();
                    if (_eventReceiver != null)
                    {
                        _eventReceiver.OnDebugMessage(false, r.ReadString());
                    }
                }
                else
                {
                    return(data);
                }
            }
        }
예제 #2
0
        private bool ReceiveAuthenticationResult()
        {
            DataFragment   packet = ReceivePacket();
            SSH1DataReader r      = new SSH1DataReader(packet);
            PacketType     type   = r.ReadPacketType();

            TraceReceptionEvent(type, "user authentication response");
            if (type == PacketType.SSH_MSG_DEBUG)
            {
                //Debug.WriteLine("receivedd debug message:"+Encoding.ASCII.GetString(r.ReadString()));
                return(ReceiveAuthenticationResult());
            }
            else if (type == PacketType.SSH_SMSG_SUCCESS)
            {
                return(true);
            }
            else if (type == PacketType.SSH_SMSG_FAILURE)
            {
                return(false);
            }
            else
            {
                throw new SSHException("unexpected type: " + type);
            }
        }
예제 #3
0
        /// <summary>
        /// constructs from file
        /// </summary>
        /// <param name="path">file name</param>
        /// <param name="passphrase">passphrase or empty string if passphrase is not required</param>
        public SSH1UserAuthKey(string path, string passphrase)
        {
#if PODEROSA_KEYFORMAT
            PrivateKeyLoader loader = new PrivateKeyLoader(path);
            loader.LoadSSH1PrivateKey(
                passphrase,
                out _modulus,
                out _publicExponent,
                out _privateExponent,
                out _primeP,
                out _primeQ,
                out _crtCoefficient,
                out _comment);
#else
            Stream s      = File.Open(path, FileMode.Open);
            byte[] header = new byte[32];
            s.Read(header, 0, header.Length);
            if (Encoding.ASCII.GetString(header) != "SSH PRIVATE KEY FILE FORMAT 1.1\n")
            {
                throw new SSHException(String.Format(Strings.GetString("BrokenKeyFile"), path));
            }

            SSH1DataReader reader = new SSH1DataReader(ReadAll(s));
            s.Close();

            byte[] cipher = reader.Read(2); //first 2 bytes indicates algorithm and next 8 bytes is space
            reader.Read(8);

            _modulus        = reader.ReadMPInt();
            _publicExponent = reader.ReadMPInt();
            _comment        = reader.ReadString();
            byte[] prvt = reader.GetRemainingDataView().GetBytes();
            //必要なら復号
            CipherAlgorithm algo = (CipherAlgorithm)cipher[1];
            if (algo != 0)
            {
                Cipher c   = CipherFactory.CreateCipher(SSHProtocol.SSH1, algo, ConvertToKey(passphrase));
                byte[] buf = new byte[prvt.Length];
                c.Decrypt(prvt, 0, prvt.Length, buf, 0);
                prvt = buf;
            }

            SSH1DataReader prvtreader = new SSH1DataReader(prvt);
            byte[]         mark       = prvtreader.Read(4);
            if (mark[0] != mark[2] || mark[1] != mark[3])
            {
                throw new SSHException(Strings.GetString("WrongPassphrase"));
            }

            _privateExponent = prvtreader.ReadMPInt();
            _crtCoefficient  = prvtreader.ReadMPInt();
            _primeP          = prvtreader.ReadMPInt();
            _primeQ          = prvtreader.ReadMPInt();
#endif
        }
예제 #4
0
        /// <summary>
        /// Read SSH1 private key parameters.
        /// </summary>
        /// <param name="passphrase">passphrase for decrypt the key file</param>
        /// <param name="modulus">private key parameter</param>
        /// <param name="publicExponent">private key parameter</param>
        /// <param name="privateExponent">private key parameter</param>
        /// <param name="primeP">private key parameter</param>
        /// <param name="primeQ">private key parameter</param>
        /// <param name="crtCoefficient">private key parameter</param>
        /// <exception cref="SSHException">failed to parse</exception>
        public void Load(
            string passphrase,
            out BigInteger modulus,
            out BigInteger publicExponent,
            out BigInteger privateExponent,
            out BigInteger primeP,
            out BigInteger primeQ,
            out BigInteger crtCoefficient)
        {
            if (keyFile == null)
            {
                throw new SSHException("A key file is not loaded yet");
            }
            byte[] hdr = Encoding.ASCII.GetBytes(PrivateKeyFileHeader.SSH1_HEADER);
            if (!ByteArrayUtil.ByteArrayStartsWith(keyFile, hdr))
            {
                throw new SSHException(Strings.GetString("NotValidPrivateKeyFile"));
            }

            SSH1DataReader reader = new SSH1DataReader(keyFile);

            reader.Read(hdr.Length);

            byte[] cipher = reader.Read(2); //first 2 bytes indicates algorithm and next 8 bytes is space
            reader.Read(8);

            modulus        = reader.ReadMPInt();
            publicExponent = reader.ReadMPInt();
            byte[] comment = reader.ReadString();
            byte[] prvt    = reader.ReadAll();
            //必要なら復号
            CipherAlgorithm algo = (CipherAlgorithm)cipher[1];

            if (algo != 0)
            {
                Cipher c   = CipherFactory.CreateCipher(SSHProtocol.SSH1, algo, SSH1PassphraseToKey(passphrase));
                byte[] buf = new byte[prvt.Length];
                c.Decrypt(prvt, 0, prvt.Length, buf, 0);
                prvt = buf;
            }

            SSH1DataReader prvtreader = new SSH1DataReader(prvt);

            byte[] mark = prvtreader.Read(4);
            if (mark[0] != mark[2] || mark[1] != mark[3])
            {
                throw new SSHException(Strings.GetString("WrongPassphrase"));
            }

            privateExponent = prvtreader.ReadMPInt();
            crtCoefficient  = prvtreader.ReadMPInt();
            primeP          = prvtreader.ReadMPInt();
            primeQ          = prvtreader.ReadMPInt();
        }
예제 #5
0
        /// <summary>
        /// Process forwarded message.
        /// </summary>
        /// <param name="message">a forwarded message</param>
        private void ProcessMessage(DataFragment message)
        {
            if (_authKeyProvider == null || !_authKeyProvider.IsAuthKeyProviderEnabled)
            {
                SendFailure();
                return;
            }

            SSH1DataReader reader = new SSH1DataReader(message);
            OpenSSHAgentForwardingMessageType messageType = (OpenSSHAgentForwardingMessageType)reader.ReadByte();

            switch (messageType)
            {
            // for SSH1 keys
            case OpenSSHAgentForwardingMessageType.SSH_AGENTC_REQUEST_RSA_IDENTITIES:
                SSH1Identities();
                break;

            case OpenSSHAgentForwardingMessageType.SSH_AGENTC_RSA_CHALLENGE: {
                reader.ReadUInt32();            // ignored
                BigInteger e = reader.ReadMPInt();
                BigInteger n = reader.ReadMPInt();
                BigInteger encryptedChallenge = reader.ReadMPInt();
                byte[]     sessionId          = reader.Read(16);
                uint       responseType       = reader.ReadUInt32();

                SSH1IRSAChallenge(e, n, encryptedChallenge, sessionId, responseType);
            }
            break;

            // for SSH2 keys
            case OpenSSHAgentForwardingMessageType.SSH2_AGENTC_REQUEST_IDENTITIES:
                SSH2Identities();
                break;

            case OpenSSHAgentForwardingMessageType.SSH2_AGENTC_SIGN_REQUEST: {
                byte[] blob  = reader.ReadByteString();
                byte[] data  = reader.ReadByteString();
                uint   flags = reader.ReadUInt32();

                SSH2Sign(blob, data, flags);
            }
            break;

            default:
                SendFailure();
                break;
            }
        }
예제 #6
0
        //RSA authentication
        private void DoRSAChallengeResponse()
        {
            //read key
            SSH1UserAuthKey key = new SSH1UserAuthKey(_param.IdentityFile, _param.Password);
            SSH1DataWriter  w   = new SSH1DataWriter();

            w.WriteBigInteger(key.PublicModulus);
            SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_AUTH_RSA, w.ToByteArray());

            p.WriteTo(_stream, _tCipher);
            TraceTransmissionEvent(PacketType.SSH_CMSG_AUTH_RSA, "RSA challenge-reponse");

            DataFragment   response = ReceivePacket();
            SSH1DataReader reader   = new SSH1DataReader(response);
            PacketType     pt       = reader.ReadPacketType();

            if (pt == PacketType.SSH_SMSG_FAILURE)
            {
                throw new SSHException(Strings.GetString("ServerRefusedRSA"));
            }
            else if (pt != PacketType.SSH_SMSG_AUTH_RSA_CHALLENGE)
            {
                throw new SSHException(String.Format(Strings.GetString("UnexpectedResponse"), pt));
            }
            TraceReceptionEvent(PacketType.SSH_SMSG_AUTH_RSA_CHALLENGE, "received challenge");

            //creating challenge
            BigInteger challenge = key.decryptChallenge(reader.ReadMPInt());

            byte[] rawchallenge = RSAUtil.StripPKCS1Pad(challenge, 2).getBytes();

            //building response
            MemoryStream bos = new MemoryStream();

            bos.Write(rawchallenge, 0, rawchallenge.Length); //!!mindtermでは頭が0かどうかで変なハンドリングがあった
            bos.Write(_sessionID, 0, _sessionID.Length);
            byte[] reply = new MD5CryptoServiceProvider().ComputeHash(bos.ToArray());

            w = new SSH1DataWriter();
            w.Write(reply);
            p = SSH1Packet.FromPlainPayload(PacketType.SSH_CMSG_AUTH_RSA_RESPONSE, w.ToByteArray());
            p.WriteTo(_stream, _tCipher);
            TraceReceptionEvent(PacketType.SSH_CMSG_AUTH_RSA_RESPONSE, "received response");
        }
예제 #7
0
        internal void AsyncReceivePacket(DataFragment data)
        {
            try {
                int            len = 0, channel = 0;
                SSH1DataReader re = new SSH1DataReader(data);
                PacketType     pt = re.ReadPacketType();
                switch (pt)
                {
                case PacketType.SSH_SMSG_STDOUT_DATA:
                    len = re.ReadInt32();
                    _channel_collection.FindChannelEntry(_shellID).Receiver.OnData(re.Image, re.Offset, len);
                    break;

                case PacketType.SSH_SMSG_STDERR_DATA: {
                    _channel_collection.FindChannelEntry(_shellID).Receiver.OnExtendedData((int)PacketType.SSH_SMSG_STDERR_DATA, re.ReadString());
                }
                break;

                case PacketType.SSH_MSG_CHANNEL_DATA:
                    channel = re.ReadInt32();
                    len     = re.ReadInt32();
                    _channel_collection.FindChannelEntry(channel).Receiver.OnData(re.Image, re.Offset, len);
                    break;

                case PacketType.SSH_MSG_PORT_OPEN:
                    ProcessPortforwardingRequest(_eventReceiver, re);
                    break;

                case PacketType.SSH_MSG_CHANNEL_CLOSE: {
                    channel = re.ReadInt32();
                    ISSHChannelEventReceiver r = _channel_collection.FindChannelEntry(channel).Receiver;
                    _channel_collection.UnregisterChannelEventReceiver(channel);
                    r.OnChannelClosed();
                }
                break;

                case PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
                    channel = re.ReadInt32();
                    break;

                case PacketType.SSH_MSG_DISCONNECT:
                    _eventReceiver.OnConnectionClosed();
                    break;

                case PacketType.SSH_SMSG_EXITSTATUS:
                    _channel_collection.FindChannelEntry(_shellID).Receiver.OnChannelClosed();
                    break;

                case PacketType.SSH_MSG_DEBUG:
                    _eventReceiver.OnDebugMessage(false, re.ReadString());
                    break;

                case PacketType.SSH_MSG_IGNORE:
                    _eventReceiver.OnIgnoreMessage(re.ReadString());
                    break;

                case PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: {
                    int local  = re.ReadInt32();
                    int remote = re.ReadInt32();
                    _channel_collection.FindChannelEntry(local).Receiver.OnChannelReady();
                }
                break;

                case PacketType.SSH_SMSG_SUCCESS:
                    if (_executingShell)
                    {
                        ExecShell();
                        _channel_collection.FindChannelEntry(_shellID).Receiver.OnChannelReady();
                        _executingShell = false;
                    }
                    break;

                default:
                    _eventReceiver.OnUnknownMessage((byte)pt, re.ReadAll());
                    break;
                }
            }
            catch (Exception ex) {
                _eventReceiver.OnError(ex);
            }
        }
예제 #8
0
        private void ProcessPortforwardingRequest(ISSHConnectionEventReceiver receiver, SSH1DataReader reader)
        {
            int    server_channel = reader.ReadInt32();
            string host           = Encoding.ASCII.GetString(reader.ReadString());
            int    port           = reader.ReadInt32();

            SSH1DataWriter            writer = new SSH1DataWriter();
            PortForwardingCheckResult result = receiver.CheckPortForwardingRequest(host, port, "", 0);

            if (result.allowed)
            {
                int local_id = _channel_collection.RegisterChannelEventReceiver(null, result.channel).LocalID;
                _eventReceiver.EstablishPortforwarding(result.channel, new SSH1Channel(this, ChannelType.ForwardedRemoteToLocal, local_id, server_channel));

                writer.WriteInt32(server_channel);
                writer.WriteInt32(local_id);
                SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, writer.ToByteArray());
                p.WriteTo(_stream, _tCipher);
            }
            else
            {
                writer.WriteInt32(server_channel);
                SSH1Packet p = SSH1Packet.FromPlainPayload(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE, writer.ToByteArray());
                p.WriteTo(_stream, _tCipher);
            }
        }
예제 #9
0
        private void ReceiveServerKeys()
        {
            DataFragment   packet = ReceivePacket();
            SSH1DataReader reader = new SSH1DataReader(packet);
            PacketType     pt     = reader.ReadPacketType();

            if (pt != PacketType.SSH_SMSG_PUBLIC_KEY)
            {
                throw new SSHException("unexpected SSH SSH1Packet type " + pt, reader.ReadAll());
            }

            _cInfo._serverinfo = new SSHServerInfo(reader);
            _cInfo._hostkey    = new RSAPublicKey(_cInfo._serverinfo.host_key_public_exponent, _cInfo._serverinfo.host_key_public_modulus);

            //read protocol support parameters
            int protocol_flags         = reader.ReadInt32();
            int supported_ciphers_mask = reader.ReadInt32();

            _cInfo.SetSupportedCipherAlgorithms(supported_ciphers_mask);
            int supported_authentications_mask = reader.ReadInt32();

            //Debug.WriteLine(String.Format("ServerOptions {0} {1} {2}", protocol_flags, supported_ciphers_mask, supported_authentications_mask));

            if (reader.Rest > 0)
            {
                throw new SSHException("data length mismatch", reader.ReadAll());
            }

            bool found = false;

            foreach (CipherAlgorithm a in _param.PreferableCipherAlgorithms)
            {
                if (a != CipherAlgorithm.Blowfish && a != CipherAlgorithm.TripleDES)
                {
                    continue;
                }
                else if (a == CipherAlgorithm.Blowfish && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.Blowfish)) == 0)
                {
                    continue;
                }
                else if (a == CipherAlgorithm.TripleDES && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.TripleDES)) == 0)
                {
                    continue;
                }

                _cInfo._algorithmForReception = _cInfo._algorithmForTransmittion = a;
                found = true;
                break;
            }

            if (!found)
            {
                throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedX"), "Blowfish/TripleDES"));
            }

            if (_param.AuthenticationType == AuthenticationType.Password && (supported_authentications_mask & (1 << (int)AuthenticationType.Password)) == 0)
            {
                throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedPassword")), reader.ReadAll());
            }
            if (_param.AuthenticationType == AuthenticationType.PublicKey && (supported_authentications_mask & (1 << (int)AuthenticationType.PublicKey)) == 0)
            {
                throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedRSA")), reader.ReadAll());
            }

            TraceReceptionEvent(pt, "received server key");
        }
예제 #10
0
        /// <summary>
        /// Process packet about this channel.
        /// </summary>
        /// <param name="packetType">a packet type (message number)</param>
        /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
        public override void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment)
        {
            if (_state == State.Closed)
            {
                return; // ignore
            }

            DataFragment dataFragmentArg;

            lock (_stateSync) {
                switch (_state)
                {
                case State.Initial:
                    break;

                case State.WaitStartPTYResponse:
                    if (packetType == SSH1PacketType.SSH_SMSG_SUCCESS)
                    {
                        _state = State.StartPTYSuccess;
                        Monitor.PulseAll(_stateSync);       // notifies state change
                        _receivedPacket.TrySet(packetFragment, PASSING_TIMEOUT);
                    }
                    else if (packetType == SSH1PacketType.SSH_SMSG_FAILURE)
                    {
                        _state = State.StartPTYFailure;
                        Monitor.PulseAll(_stateSync);       // notifies state change
                        _receivedPacket.TrySet(packetFragment, PASSING_TIMEOUT);
                    }
                    break;

                case State.Established:
                    break;

                case State.Ready:
                    switch (packetType)
                    {
                    case SSH1PacketType.SSH_SMSG_STDOUT_DATA: {
                        SSH1DataReader reader = new SSH1DataReader(packetFragment);
                        int            len    = reader.ReadInt32();
                        dataFragmentArg = reader.GetRemainingDataView(len);
                    }
                        goto OnData;            // do it out of the lock block

                    case SSH1PacketType.SSH_SMSG_STDERR_DATA: {
                        SSH1DataReader reader = new SSH1DataReader(packetFragment);
                        int            len    = reader.ReadInt32();
                        dataFragmentArg = reader.GetRemainingDataView(len);
                    }
                        goto OnData;            // do it out of the lock block

                    case SSH1PacketType.SSH_SMSG_EXITSTATUS:
                        Transmit(
                            new SSH1Packet(SSH1PacketType.SSH_CMSG_EXIT_CONFIRMATION)
                            );
                        goto SetStateClosedByServer; // do it out of the lock block
                    }
                    goto OnUnhandledPacket;          // do it out of the lock block
                }
            }

            return;

OnData:
            Handler.OnData(dataFragmentArg);
            return;

SetStateClosedByServer:
            Trace("CH[{0}] closed by server", LocalChannel);
            SetStateClosed(true);
            return;

OnUnhandledPacket:
            Handler.OnUnhandledPacket((byte)packetType, packetFragment);
            return;
        }
예제 #11
0
        /// <summary>
        /// Process packet about this channel.
        /// </summary>
        /// <param name="packetType">a packet type (message number)</param>
        /// <param name="packetFragment">a packet image except message number and recipient channel.</param>
        public override void ProcessPacket(SSH1PacketType packetType, DataFragment packetFragment)
        {
            if (_state == State.Closed)
            {
                return; // ignore
            }

            DataFragment dataFragmentArg;

            lock (_stateSync) {
                switch (_state)
                {
                case State.InitiatedByServer:
                    break;

                case State.InitiatedByClient:
                    if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION)
                    {
                        SSH1DataReader reader = new SSH1DataReader(packetFragment);
                        SetRemoteChannel(reader.ReadUInt32());
                        _state = State.Established;
                        Monitor.PulseAll(_stateSync); // notifies state change
                        dataFragmentArg = new DataFragment(0);
                        goto OnEstablished;           // do it out of the lock block
                    }
                    if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE)
                    {
                        goto RequestFailed;     // do it out of the lock block
                    }
                    break;

                case State.Closing:
                    if (packetType == SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION)
                    {
                        goto SetStateClosedByClient;        // do it out of the lock block
                    }
                    break;

                case State.Established:
                case State.Ready:
                    if (ProcessPacketSub(packetType, packetFragment) == SubPacketProcessResult.Consumed)
                    {
                        return;
                    }
                    switch (packetType)
                    {
                    case SSH1PacketType.SSH_MSG_CHANNEL_DATA: {
                        SSH1DataReader reader = new SSH1DataReader(packetFragment);
                        int            len    = reader.ReadInt32();
                        dataFragmentArg = reader.GetRemainingDataView(len);
                    }
                        goto OnData;            // do it out of the lock block

                    case SSH1PacketType.SSH_MSG_CHANNEL_CLOSE:
                        Transmit(
                            new SSH1Packet(SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION)
                            .WriteUInt32(RemoteChannel)
                            );
                        goto SetStateClosedByServer; // do it out of the lock block
                    }
                    goto OnUnhandledPacket;          // do it out of the lock block
                }
            }

            return;

OnEstablished:
            Trace("CH[{0}] channel opend : remoteChannel={1}", LocalChannel, RemoteChannel);
            Handler.OnEstablished(dataFragmentArg);
            OnChannelEstablished();
            return;

RequestFailed:
            Trace("CH[{0}] request failed", LocalChannel);
            RequestFailed();
            return;

SetStateClosedByClient:
            Trace("CH[{0}] closed by client", LocalChannel);
            SetStateClosed(false);
            return;

SetStateClosedByServer:
            Trace("CH[{0}] closed by server", LocalChannel);
            SetStateClosed(true);
            return;

OnData:
            Handler.OnData(dataFragmentArg);
            return;

OnUnhandledPacket:
            Handler.OnUnhandledPacket((byte)packetType, packetFragment);
            return;
        }