示例#1
0
        private static SSHConnection ConnectMain(SSHConnectionParameter param, ISSHConnectionEventReceiver receiver, VersionExchangeHandler pnh, AbstractGranadosSocket s)
        {
            DataFragment data = pnh.WaitResponse();
            string       sv   = pnh.ServerVersion;

            SSHConnection con = null;

            if (param.Protocol == SSHProtocol.SSH1)
            {
                throw new SSHException("SSH1 is not supported");
            }
            else
            {
                con = new SSH2Connection(param, s, receiver, sv, SSHUtil.ClientVersionString(param.Protocol));
            }

            con.TraceReceptionEvent("server version-string", sv.Trim());
            pnh.Close();
            s.SetHandler(con.PacketBuilder);
            con.SendMyVersion(param);

            if (con.Connect() != AuthenticationResult.Failure)
            {
                return(con);
            }
            else
            {
                s.Close();
                return(null);
            }
        }
示例#2
0
        public void OnData(byte[] data, int offset, int length)
        {
            _buffer.Write(data, offset, length);
            int expectedLength = SSHUtil.ReadInt32(_buffer.UnderlyingBuffer, 0);

            if (expectedLength + 4 <= _buffer.Length)
            {
                SSH2DataReader        r  = new SSH2DataReader(new DataFragment(_buffer.UnderlyingBuffer, 4, _buffer.Length - 4));
                AgentForwadPacketType pt = (AgentForwadPacketType)r.ReadByte();
                //remaining len-1
                _buffer.SetOffset(0);

                switch (pt)
                {
                case AgentForwadPacketType.SSH2_AGENTC_REQUEST_IDENTITIES:
                    SendKeyList();
                    break;

                case AgentForwadPacketType.SSH2_AGENTC_SIGN_REQUEST:
                    SendSign(r);
                    break;

                default:
                    //Debug.WriteLine("Unknown agent packet " + pt.ToString());
                    TransmitWriter(OpenWriter(AgentForwadPacketType.SSH_AGENT_FAILURE));
                    break;
                }
            }
        }
示例#3
0
        //returns true if a new packet could be obtained
        private DataFragment ConstructPacket()
        {
            if (_writeOffset - _readOffset < 4)
            {
                return(null);
            }
            int packet_length  = SSHUtil.ReadInt32(_buffer, _readOffset);
            int padding_length = 8 - (packet_length % 8); //padding length
            int total          = packet_length + padding_length;

            if (_writeOffset - _readOffset < 4 + total)
            {
                return(null);
            }

            byte[] decrypted = new byte[total];
            if (_cipher != null)
            {
                _cipher.Decrypt(_buffer, _readOffset + 4, total, decrypted, 0);
            }
            else
            {
                Array.Copy(_buffer, _readOffset + 4, decrypted, 0, total);
            }
            _readOffset += 4 + total;

            SSH1Packet p = new SSH1Packet();

            return(ConstructAndCheck(decrypted, packet_length, padding_length, _checkMAC));
        }
示例#4
0
        //no decryption, no mac
        private void ReadPacketFromPlainStream()
        {
            int offset        = _buffer.Offset;
            int packet_length = SSHUtil.ReadInt32(_buffer.Data, offset);

            if (packet_length <= 0 || packet_length >= MAX_PACKET_LENGTH)
            {
                throw new SSHException(String.Format("packet size {0} is invalid", packet_length));
            }
            offset += PACKET_LENGTH_FIELD_LEN;

            byte padding_length = _buffer.Data[offset++];

            if (padding_length < 4)
            {
                throw new SSHException(String.Format("padding length {0} is invalid", padding_length));
            }

            int payload_length = packet_length - 1 - padding_length;

            Array.Copy(_buffer.Data, offset, _packet.Data, 0, payload_length);
            _packet.SetLength(0, payload_length);

            _buffer.Consume(packet_length + PACKET_LENGTH_FIELD_LEN);
        }
示例#5
0
        //constracts and appends mac
        public void CalcHash(MAC mac, int sequence)
        {
            byte[] buf = new byte[4 + 4 + _packetLength];
            SSHUtil.WriteIntToByteArray(buf, 0, sequence);
            WriteTo(buf, 4, false);

            _mac = mac.Calc(buf);
        }
示例#6
0
        private void SendMyVersion(SSHConnectionParameter param)
        {
            string cv  = SSHUtil.ClientVersionString(param.Protocol);
            string cv2 = cv + param.VersionEOL;

            byte[] data = Encoding.ASCII.GetBytes(cv2);
            _stream.Write(data, 0, data.Length);
            TraceTransmissionEvent("client version-string", cv);
        }
示例#7
0
        /// <summary>
        /// Overrides Close()
        /// </summary>
        /// <param name="cipher"></param>
        /// <param name="mac"></param>
        /// <param name="sequence"></param>
        /// <returns></returns>
        public override DataFragment Close(Cipher cipher, MAC mac, int sequence)
        {
            byte[] buf            = DataWriter.UnderlyingBuffer;
            int    sftpDataLength = DataWriter.Length - OFFSET_SFTP_PACKET_TYPE;

            SSHUtil.WriteIntToByteArray(buf, OFFSET_CHANNEL_DATA_LENGTH, sftpDataLength + 4);
            SSHUtil.WriteIntToByteArray(buf, OFFSET_SFTP_DATA_LENGTH, sftpDataLength);
            return(base.Close(cipher, mac, sequence));
        }
示例#8
0
        /// <summary>
        /// Find a SSH2 key
        /// </summary>
        /// <param name="blob">key blob</param>
        /// <returns>matched key object, or null if not found.</returns>
        private SSH2UserAuthKey SSH2FindKey(byte[] blob)
        {
            var authKeys = _authKeyProvider.GetAvailableSSH2UserAuthKeys();

            if (authKeys == null)
            {
                return(null);
            }
            return(authKeys.FirstOrDefault(key => SSHUtil.ByteArrayEqual(blob, key.GetPublicKeyBlob())));
        }
示例#9
0
 public void WriteTo(byte[] buf, int offset, bool includes_mac)
 {
     SSHUtil.WriteIntToByteArray(buf, offset, _packetLength);
     buf[offset + 4] = (byte)_padding.Length;
     Array.Copy(_payload, 0, buf, offset + 5, _payload.Length);
     Array.Copy(_padding, 0, buf, offset + 5 + _payload.Length, _padding.Length);
     if (includes_mac && _mac != null)
     {
         Array.Copy(_mac, 0, buf, offset + 5 + _payload.Length + _padding.Length, _mac.Length);
     }
 }
示例#10
0
        //returns true if a new packet could be obtained
        private SSH2Packet ConstructPacket()
        {
            SSH2Packet packet = null;

            if (_event != null && !_event.WaitOne(3000, false))
            {
                throw new Exception("waithandle timed out");
            }

            if (_cipher == null)
            {
                if (_writeOffset - _readOffset < 4)
                {
                    return(null);
                }
                int len = SSHUtil.ReadInt32(_buffer, _readOffset);
                if (_writeOffset - _readOffset < 4 + len)
                {
                    return(null);
                }

                packet       = SSH2Packet.FromPlainStream(_buffer, _readOffset);
                _readOffset += 4 + len;
                _sequence++;
            }
            else
            {
                if (_head == null)
                {
                    if (_writeOffset - _readOffset < _cipher.BlockSize)
                    {
                        return(null);
                    }
                    _head = new byte[_cipher.BlockSize];
                    byte[] eh = new byte[_cipher.BlockSize];
                    Array.Copy(_buffer, _readOffset, eh, 0, eh.Length);
                    _readOffset += eh.Length;
                    _cipher.Decrypt(eh, 0, eh.Length, _head, 0);
                }

                int len = SSHUtil.ReadInt32(_head, 0);
                if (_writeOffset - _readOffset < len + 4 - _head.Length + _mac.Size)
                {
                    return(null);
                }

                packet       = SSH2Packet.FromDecryptedHead(_head, _buffer, _readOffset, _cipher, _sequence++, _mac);
                _readOffset += 4 + len - _head.Length + _mac.Size;
                _head        = null;
            }

            return(packet);
        }
示例#11
0
        // Derived class can override this method to modify the buffer.
        public virtual DataFragment Close(Cipher cipher, MAC mac, int sequence)
        {
            if (!_isOpen)
            {
                throw new SSHException("internal state error");
            }

            int blocksize     = cipher == null ? 8 : cipher.BlockSize;
            int payloadLength = _writer.Length - (SEQUENCE_MARGIN + LENGTH_MARGIN + PADDING_MARGIN);
            int paddingLength = 11 - payloadLength % blocksize;

            while (paddingLength < 4)
            {
                paddingLength += blocksize;
            }
            int packetLength = PADDING_MARGIN + payloadLength + paddingLength;
            int imageLength  = packetLength + LENGTH_MARGIN;

            //fill padding
            byte[] tmp = new byte[4];
            Rng    rng = RngManager.GetSecureRng();

            for (int i = 0; i < paddingLength; i += 4)
            {
                rng.GetBytes(tmp);
                _writer.Write(tmp);
            }

            //manipulate stream
            byte[] rawbuf = _writer.UnderlyingBuffer;
            SSHUtil.WriteIntToByteArray(rawbuf, 0, sequence);
            SSHUtil.WriteIntToByteArray(rawbuf, SEQUENCE_MARGIN, packetLength);
            rawbuf[SEQUENCE_MARGIN + LENGTH_MARGIN] = (byte)paddingLength;

            //mac
            if (mac != null)
            {
                byte[] macCode = mac.ComputeHash(rawbuf, 0, packetLength + LENGTH_MARGIN + SEQUENCE_MARGIN);
                Array.Copy(macCode, 0, rawbuf, packetLength + LENGTH_MARGIN + SEQUENCE_MARGIN, macCode.Length);
                imageLength += macCode.Length;
            }

            //encrypt
            if (cipher != null)
            {
                cipher.Encrypt(rawbuf, SEQUENCE_MARGIN, packetLength + LENGTH_MARGIN, rawbuf, SEQUENCE_MARGIN);
            }

            _dataFragment.Init(rawbuf, SEQUENCE_MARGIN, imageLength);
            _isOpen = false;
            return(_dataFragment);
        }
示例#12
0
        private static void SendMyVersion(AbstractSocket stream, SSHConnectionParameter param)
        {
            string cv = SSHUtil.ClientVersionString(param.Protocol);

            if (param.Protocol == SSHProtocol.SSH1)
            {
                cv += param.SSH1VersionEOL;
            }
            else
            {
                cv += "\r\n";
            }
            byte[] data = Encoding.UTF8.GetBytes(cv);
            stream.Write(data, 0, data.Length);
        }
示例#13
0
        public void Close(Cipher cipher, Random rnd, MAC mac, int sequence, DataFragment result)
        {
            if (!_is_open)
            {
                throw new SSHException("internal state error");
            }

            int blocksize      = cipher == null? 8 : cipher.BlockSize;
            int payload_length = _writer.Length - (SEQUENCE_MARGIN + LENGTH_MARGIN + PADDING_MARGIN);
            int r = 11 - payload_length % blocksize;

            while (r < 4)
            {
                r += blocksize;
            }
            _paddingLength = r;
            _packetLength  = PADDING_MARGIN + payload_length + _paddingLength;
            int image_length = _packetLength + LENGTH_MARGIN;

            //fill padding
            for (int i = 0; i < _paddingLength; i += 4)
            {
                _writer.Write(rnd.Next());
            }

            //manipulate stream
            byte[] rawbuf = _writer.UnderlyingBuffer;
            SSHUtil.WriteIntToByteArray(rawbuf, 0, sequence);
            SSHUtil.WriteIntToByteArray(rawbuf, SEQUENCE_MARGIN, _packetLength);
            rawbuf[SEQUENCE_MARGIN + LENGTH_MARGIN] = (byte)_paddingLength;

            //mac
            if (mac != null)
            {
                _mac = mac.ComputeHash(rawbuf, 0, _packetLength + LENGTH_MARGIN + SEQUENCE_MARGIN);
                Array.Copy(_mac, 0, rawbuf, _packetLength + LENGTH_MARGIN + SEQUENCE_MARGIN, _mac.Length);
                image_length += _mac.Length;
            }

            //encrypt
            if (cipher != null)
            {
                cipher.Encrypt(rawbuf, SEQUENCE_MARGIN, _packetLength + LENGTH_MARGIN, rawbuf, SEQUENCE_MARGIN);
            }

            result.Init(rawbuf, SEQUENCE_MARGIN, image_length);
            _is_open = false;
        }
示例#14
0
        private void ReadPacketWithDecryptedHead()
        {
            /* SOURCE      : _head(packet_size, padding_length) + _buffer(payload + mac)
             * DESTINATION : _packet(payload)
             */

            int offset        = _buffer.Offset;
            int packet_length = SSHUtil.ReadInt32(_head, 0);

            if (packet_length <= 0 || packet_length >= MAX_PACKET_LENGTH)
            {
                throw new SSHException(String.Format("packet size {0} is invalid", packet_length));
            }

            _packet.AssureCapacity(packet_length + PACKET_LENGTH_FIELD_LEN + SEQUENCE_FIELD_LEN);
            int padding_length = (int)_head[PACKET_LENGTH_FIELD_LEN];

            if (padding_length < 4)
            {
                throw new SSHException("padding length is invalid");
            }

            //to compute hash, we write _sequence at the top of _packet.Data
            SSHUtil.WriteIntToByteArray(_packet.Data, 0, _sequence);
            Array.Copy(_head, 0, _packet.Data, SEQUENCE_FIELD_LEN, _head.Length);

            if (packet_length > (_cipher.BlockSize - PACKET_LENGTH_FIELD_LEN))   //in case of _head is NOT the entire of the packet
            {
                int decrypting_size = packet_length - (_cipher.BlockSize - PACKET_LENGTH_FIELD_LEN);
                _cipher.Decrypt(_buffer.Data, _buffer.Offset, decrypting_size, _packet.Data, SEQUENCE_FIELD_LEN + _head.Length);
            }

            _packet.SetLength(SEQUENCE_FIELD_LEN + PACKET_LENGTH_FIELD_LEN + PADDING_LENGTH_FIELD_LEN, packet_length - 1 - padding_length);
            _buffer.Consume(packet_length + PACKET_LENGTH_FIELD_LEN - _head.Length + _mac.Size);

            if (_macEnabled)
            {
                byte[] result = _mac.ComputeHash(_packet.Data, 0, 4 + PACKET_LENGTH_FIELD_LEN + packet_length);

                if (SSHUtil.memcmp(result, 0, _buffer.Data, _buffer.Offset - _mac.Size, _mac.Size) != 0)
                {
                    throw new SSHException("MAC mismatch");
                }
            }
        }
 /**
  * reads type, data, and crc from byte array.
  * an exception is thrown if crc check fails.
  */
 internal void ConstructAndCheck(byte[] buf, int packet_length, int padding_length, bool check_crc)
 {
     _type = buf[padding_length];
     //System.out.println("Type: " + _type);
     if (packet_length > 5)                   //the body is not empty
     {
         _data = new byte[packet_length - 5]; //5 is the length of [type] and [crc]
         Array.Copy(buf, padding_length + 1, _data, 0, packet_length - 5);
     }
     _CRC = (uint)SSHUtil.ReadInt32(buf, buf.Length - 4);
     if (check_crc)
     {
         uint c = CRC.Calc(buf, 0, buf.Length - 4);
         if (_CRC != c)
         {
             throw new SSHException("CRC Error", buf);
         }
     }
 }
示例#16
0
        public static SSH2Packet FromDecryptedHead(byte[] head, byte[] buffer, int offset, Cipher cipher, int sequence, MAC mac)
        {
            SSH2Packet p = new SSH2Packet();

            p._packetLength = SSHUtil.ReadInt32(head, 0);
            if (p._packetLength <= 0 || p._packetLength >= MAX_PACKET_LENGTH)
            {
                throw new SSHException(String.Format("packet size {0} is invalid", p._packetLength));
            }
            SSH2DataWriter buf = new SSH2DataWriter();

            buf.Write(sequence);
            buf.Write(head);
            if (p._packetLength > (cipher.BlockSize - 4))
            {
                byte[] tmp = new byte[p._packetLength - (cipher.BlockSize - 4)];
                cipher.Decrypt(buffer, offset, tmp.Length, tmp, 0);
                offset += tmp.Length;
                buf.Write(tmp);
            }
            byte[] result      = buf.ToByteArray();
            int    padding_len = (int)result[8];

            if (padding_len < 4)
            {
                throw new SSHException("padding length is invalid");
            }

            byte[] payload = new byte[result.Length - 9 - padding_len];
            Array.Copy(result, 9, payload, 0, payload.Length);
            p._payload = payload;

            if (mac != null)
            {
                p._mac = mac.Calc(result);
                if (SSHUtil.memcmp(p._mac, 0, buffer, offset, mac.Size) != 0)
                {
                    throw new SSHException("MAC Error");
                }
            }
            return(p);
        }
示例#17
0
        //returns true if a new packet is obtained to _packet
        private bool ConstructPacket()
        {
            if (_cipher == null)   //暗号が確立する前
            {
                if (_buffer.Length < PACKET_LENGTH_FIELD_LEN)
                {
                    return(false);
                }
                int len = SSHUtil.ReadInt32(_buffer.Data, _buffer.Offset);
                if (_buffer.Length < PACKET_LENGTH_FIELD_LEN + len)
                {
                    return(false);
                }

                ReadPacketFromPlainStream();
            }
            else
            {
                if (!_head_is_available)
                {
                    if (_buffer.Length < _cipher.BlockSize)
                    {
                        return(false);
                    }
                    _cipher.Decrypt(_buffer.Data, _buffer.Offset, _head.Length, _head, 0);
                    _buffer.Consume(_head.Length);
                    _head_is_available = true;
                }

                int len = SSHUtil.ReadInt32(_head, 0);
                if (_buffer.Length < len + PACKET_LENGTH_FIELD_LEN - _head.Length + _mac.Size)
                {
                    return(false);
                }

                ReadPacketWithDecryptedHead();
                _head_is_available = false;
            }

            _sequence++;
            return(true);
        }
示例#18
0
        /**
         * reads type, data, and crc from byte array.
         * an exception is thrown if crc check fails.
         */
        private DataFragment ConstructAndCheck(byte[] buf, int packet_length, int padding_length, bool check_crc)
        {
            int body_len = packet_length - 4;

            byte[] body = new byte[body_len];
            Array.Copy(buf, padding_length, body, 0, body_len);

            uint received_crc = (uint)SSHUtil.ReadInt32(buf, buf.Length - 4);

            if (check_crc)
            {
                uint crc = CRC.Calc(buf, 0, buf.Length - 4);
                if (received_crc != crc)
                {
                    throw new SSHException("CRC Error", buf);
                }
            }

            return(new DataFragment(body, 0, body_len));
        }
示例#19
0
        //no decryption, no mac
        public static SSH2Packet FromPlainStream(byte[] buffer, int offset)
        {
            SSH2Packet p = new SSH2Packet();

            p._packetLength = SSHUtil.ReadInt32(buffer, offset);
            if (p._packetLength <= 0 || p._packetLength >= MAX_PACKET_LENGTH)
            {
                throw new SSHException(String.Format("packet size {0} is invalid", p._packetLength));
            }
            offset += 4;

            byte pl = buffer[offset++];

            if (pl < 4)
            {
                throw new SSHException(String.Format("padding length {0} is invalid", pl));
            }
            p._payload = new byte[p._packetLength - 1 - pl];
            Array.Copy(buffer, offset, p._payload, 0, p._payload.Length);
            return(p);
        }
示例#20
0
        /// <summary>
        /// Handles channel data
        /// </summary>
        /// <param name="data">channel data</param>
        public override void OnData(DataFragment data)
        {
            _buffer.Append(data);

            if (_buffer.Length >= 4)
            {
                uint messageLength = SSHUtil.ReadUInt32(_buffer.RawBuffer, _buffer.RawBufferOffset);
                if (_buffer.Length >= 4 + messageLength)
                {
                    DataFragment message = new DataFragment(_buffer.RawBuffer, _buffer.RawBufferOffset + 4, (int)messageLength);
                    try {
                        ProcessMessage(message);
                    }
                    catch (Exception e) {
                        Debug.WriteLine(e.Message);
                        Debug.WriteLine(e.StackTrace);
                    }
                    _buffer.RemoveHead(4 + (int)messageLength);
                }
            }
        }
示例#21
0
        public void VerifyWithSHA1(byte[] data, byte[] expected)
        {
            BigInteger result = VerifyBI(data);

            byte[] finaldata = RSAUtil.StripPKCS1Pad(result, 1).GetBytes();

            if (finaldata.Length != PKIUtil.SHA1_ASN_ID.Length + expected.Length)
            {
                throw new VerifyException("result is too short");
            }
            else
            {
                byte[] r = new byte[finaldata.Length];
                Array.Copy(PKIUtil.SHA1_ASN_ID, 0, r, 0, PKIUtil.SHA1_ASN_ID.Length);
                Array.Copy(expected, 0, r, PKIUtil.SHA1_ASN_ID.Length, expected.Length);
                if (!SSHUtil.ByteArrayEqual(r, finaldata))
                {
                    throw new VerifyException("failed to verify");
                }
            }
        }
        private byte[] BuildImage()
        {
            int packet_length  = (_data == null? 0 : _data.Length) + 5;          //type and CRC
            int padding_length = 8 - (packet_length % 8);

            byte[] image = new byte[packet_length + padding_length + 4];
            SSHUtil.WriteIntToByteArray(image, 0, packet_length);

            for (int i = 0; i < padding_length; i++)
            {
                image[4 + i] = 0;                                         //padding: filling by random values is better
            }
            image[4 + padding_length] = _type;
            if (_data != null)
            {
                Array.Copy(_data, 0, image, 4 + padding_length + 1, _data.Length);
            }

            _CRC = CRC.Calc(image, 4, image.Length - 8);
            SSHUtil.WriteIntToByteArray(image, image.Length - 4, (int)_CRC);

            return(image);
        }
        //returns true if a new packet could be obtained
        private SSH1Packet ConstructPacket()
        {
            if (_event != null && !_event.WaitOne(3000, false))
            {
                throw new Exception("waithandle timed out");
            }

            if (_writeOffset - _readOffset < 4)
            {
                return(null);
            }
            int packet_length  = SSHUtil.ReadInt32(_buffer, _readOffset);
            int padding_length = 8 - (packet_length % 8);             //padding length
            int total          = packet_length + padding_length;

            if (_writeOffset - _readOffset < 4 + total)
            {
                return(null);
            }

            byte[] decrypted = new byte[total];
            if (_cipher != null)
            {
                _cipher.Decrypt(_buffer, _readOffset + 4, total, decrypted, 0);
            }
            else
            {
                Array.Copy(_buffer, _readOffset + 4, decrypted, 0, total);
            }
            _readOffset += 4 + total;

            SSH1Packet p = new SSH1Packet();

            p.ConstructAndCheck(decrypted, packet_length, padding_length, _checkMAC);
            return(p);
        }
 public void WriteInt(int value)
 {
     SSHUtil.WriteIntToByteArray(_buffer, _offset, value);
     _offset += 4;
 }
        public void WritePrivatePartInSECSHStyleFile(Stream dest, string comment, 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

            //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();
        }
示例#26
0
        /// <summary>
        /// Establish a SSH connection
        /// </summary>
        /// <param name="socket">TCP socket which is already connected to the server.</param>
        /// <param name="param">SSH connection parameter</param>
        /// <param name="connectionEventHandlerCreator">a factory function to create a connection event handler (can be null)</param>
        /// <param name="protocolEventLoggerCreator">a factory function to create a protocol log event handler (can be null)</param>
        /// <returns>new connection object</returns>
        public static ISSHConnection Connect(
            Socket socket,
            SSHConnectionParameter param,
            Func <ISSHConnection, ISSHConnectionEventHandler> connectionEventHandlerCreator = null,
            Func <ISSHConnection, ISSHProtocolEventLogger> protocolEventLoggerCreator       = null)
        {
            if (socket == null)
            {
                throw new ArgumentNullException("socket");
            }
            if (param == null)
            {
                throw new ArgumentNullException("param");
            }
            if (!socket.Connected)
            {
                throw new ArgumentException("socket is not connected to the remote host", "socket");
            }
            if (param.UserName == null)
            {
                throw new ArgumentException("UserName property is not set", "param");
            }
            if (param.AuthenticationType != AuthenticationType.KeyboardInteractive && param.Password == null)
            {
                throw new ArgumentException("Password property is not set", "param");
            }

            string clientVersion = SSHUtil.ClientVersionString(param.Protocol);

            PlainSocket psocket = new PlainSocket(socket, null);

            try {
                // receive protocol version string
                SSHProtocolVersionReceiver protoVerReceiver = new SSHProtocolVersionReceiver();
                protoVerReceiver.Receive(psocket, 5000);
                // verify the version string
                protoVerReceiver.Verify(param.Protocol);

                ISSHConnection sshConnection;

                if (param.Protocol == SSHProtocol.SSH1)
                {
                    // create a connection object
                    var con = new SSH1Connection(
                        psocket,
                        param,
                        protoVerReceiver.ServerVersion,
                        clientVersion,
                        connectionEventHandlerCreator,
                        protocolEventLoggerCreator);
                    // start receiving loop
                    psocket.RepeatAsyncRead();
                    // send client version
                    con.SendMyVersion();
                    // establish a SSH connection
                    con.Connect();
                    sshConnection = con;
                }
                else
                {
                    // create a connection object
                    var con = new SSH2Connection(
                        psocket,
                        param,
                        protoVerReceiver.ServerVersion,
                        clientVersion,
                        connectionEventHandlerCreator,
                        protocolEventLoggerCreator);
                    // start receiving loop
                    psocket.RepeatAsyncRead();
                    // send client version
                    con.SendMyVersion();
                    // establish a SSH connection
                    con.Connect();
                    sshConnection = con;
                }

                return(sshConnection);
            }
            catch (Exception) {
                psocket.Close();
                throw;
            }
        }
示例#27
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);
        }
示例#28
0
        /// <summary>
        /// Extracts SSH packet from the internal buffer.
        /// </summary>
        /// <returns>
        /// true if one SSH packet has been extracted.
        /// in this case, _packetImage contains Packet Type field and Data field of the SSH packet.
        /// </returns>
        private bool ConstructPacket()
        {
            const int PACKET_LENGTH_FIELD_LEN = 4;
            const int CHECK_BYTES_FIELD_LEN   = 4;

            if (_packetLength < 0)
            {
                if (_inputBuffer.Length < PACKET_LENGTH_FIELD_LEN)
                {
                    return(false);
                }

                uint packetLength = SSHUtil.ReadUInt32(_inputBuffer.RawBuffer, _inputBuffer.RawBufferOffset);
                _inputBuffer.RemoveHead(PACKET_LENGTH_FIELD_LEN);

                if (packetLength < MIN_PACKET_LENGTH || packetLength > MAX_PACKET_LENGTH)
                {
                    throw new SSHException(String.Format("invalid packet length : {0}", packetLength));
                }

                _packetLength = (int)packetLength;
            }

            int paddingLength  = 8 - (_packetLength % 8);
            int requiredLength = paddingLength + _packetLength;

            if (_inputBuffer.Length < requiredLength)
            {
                return(false);
            }

            _packetImage.Clear();
            _packetImage.Append(_inputBuffer, 0, requiredLength);   // Padding, Packet Type, Data, and Check fields
            _inputBuffer.RemoveHead(requiredLength);

            if (_cipher != null)
            {
                _cipher.Decrypt(
                    _packetImage.RawBuffer, _packetImage.RawBufferOffset, requiredLength,
                    _packetImage.RawBuffer, _packetImage.RawBufferOffset);
            }

            if (_checkMAC)
            {
                uint crc = CRC.Calc(
                    _packetImage.RawBuffer,
                    _packetImage.RawBufferOffset,
                    requiredLength - CHECK_BYTES_FIELD_LEN);
                uint expected = SSHUtil.ReadUInt32(
                    _packetImage.RawBuffer,
                    _packetImage.RawBufferOffset + requiredLength - CHECK_BYTES_FIELD_LEN);
                if (crc != expected)
                {
                    throw new SSHException("CRC Error");
                }
            }

            // retain only Packet Type and Data fields
            _packetImage.RemoveHead(paddingLength);
            _packetImage.RemoveTail(CHECK_BYTES_FIELD_LEN);

            // sanity check
            if (_packetImage.Length != _packetLength - CHECK_BYTES_FIELD_LEN)
            {
                throw new InvalidOperationException();
            }

            // prepare for the next packet
            _packetLength = -1;

            return(true);
        }
示例#29
0
        /// <summary>
        /// Extracts SSH packet from the internal buffer.
        /// </summary>
        /// <returns>
        /// true if one SSH packet has been extracted.
        /// in this case, _packetImage contains payload part of the SSH packet.
        /// </returns>
        private bool ConstructPacket()
        {
            const int SEQUENCE_NUMBER_FIELD_LEN = 4;
            const int PACKET_LENGTH_FIELD_LEN   = 4;
            const int PADDING_LENGTH_FIELD_LEN  = 1;

            lock (_cipherSync) {
                if (_packetLength < 0)
                {
                    int headLen = (_cipher != null) ? _cipher.BlockSize : 4;

                    if (_inputBuffer.Length < headLen)
                    {
                        return(false);
                    }

                    _packetImage.Clear();
                    _packetImage.WriteUInt32(_sequence);
                    _packetImage.Append(_inputBuffer, 0, headLen);
                    _inputBuffer.RemoveHead(headLen);

                    int headOffset = _packetImage.RawBufferOffset + SEQUENCE_NUMBER_FIELD_LEN;

                    if (_cipher != null)
                    {
                        // decrypt first block
                        _cipher.Decrypt(
                            _packetImage.RawBuffer, headOffset, headLen,
                            _packetImage.RawBuffer, headOffset);
                    }

                    uint packetLength = SSHUtil.ReadUInt32(_packetImage.RawBuffer, headOffset);

                    if (packetLength < MIN_PACKET_LENGTH || packetLength >= MAX_PACKET_LENGTH)
                    {
                        throw new SSHException(String.Format("invalid packet length : {0}", packetLength));
                    }

                    _packetLength = (int)packetLength;
                }

                int packetHeadLen  = _packetImage.Length;   // size already read in
                int requiredLength = SEQUENCE_NUMBER_FIELD_LEN + PACKET_LENGTH_FIELD_LEN + _packetLength + _macLength - packetHeadLen;

                if (_inputBuffer.Length < requiredLength)
                {
                    return(false);
                }

                _packetImage.Append(_inputBuffer, 0, requiredLength);
                _inputBuffer.RemoveHead(requiredLength);

                if (_cipher != null)
                {
                    // decrypt excluding MAC
                    int headOffset = _packetImage.RawBufferOffset + packetHeadLen;
                    _cipher.Decrypt(
                        _packetImage.RawBuffer, headOffset, requiredLength - _macLength,
                        _packetImage.RawBuffer, headOffset);
                }

                int paddingLength = _packetImage[SEQUENCE_NUMBER_FIELD_LEN + PACKET_LENGTH_FIELD_LEN];
                if (paddingLength < 4)
                {
                    throw new SSHException(String.Format("invalid padding length : {0}", paddingLength));
                }

                int payloadLength = _packetLength - PADDING_LENGTH_FIELD_LEN - paddingLength;

                if (_checkMAC && _mac != null)
                {
                    int    contentLen = SEQUENCE_NUMBER_FIELD_LEN + PACKET_LENGTH_FIELD_LEN + _packetLength;
                    byte[] result     = _mac.ComputeHash(_packetImage.RawBuffer, _packetImage.RawBufferOffset, contentLen);

                    if (result.Length != _macLength ||
                        !SSHUtil.ByteArrayEqual(result, 0, _packetImage.RawBuffer, _packetImage.RawBufferOffset + contentLen, _macLength))
                    {
                        throw new SSHException("MAC mismatch");
                    }
                }

                // retain only payload
                _packetImage.RemoveHead(SEQUENCE_NUMBER_FIELD_LEN + PACKET_LENGTH_FIELD_LEN + PADDING_LENGTH_FIELD_LEN);
                _packetImage.RemoveTail(_macLength + paddingLength);

                // sanity check
                if (_packetImage.Length != payloadLength)
                {
                    throw new InvalidOperationException();
                }

                // prepare for the next packet
                ++_sequence;
                _packetLength = -1;

                return(true);
            }
        }
        internal void AsyncReceivePacket(SSH1Packet p)
        {
            try {
                int len = 0, channel = 0;
                switch (p.Type)
                {
                case PacketType.SSH_SMSG_STDOUT_DATA:
                    len = SSHUtil.ReadInt32(p.Data, 0);
                    FindChannelEntry(_shellID)._receiver.OnData(p.Data, 4, len);
                    break;

                case PacketType.SSH_SMSG_STDERR_DATA: {
                    SSH1DataReader re = new SSH1DataReader(p.Data);
                    FindChannelEntry(_shellID)._receiver.OnExtendedData((int)PacketType.SSH_SMSG_STDERR_DATA, re.ReadString());
                }
                break;

                case PacketType.SSH_MSG_CHANNEL_DATA:
                    channel = SSHUtil.ReadInt32(p.Data, 0);
                    len     = SSHUtil.ReadInt32(p.Data, 4);
                    FindChannelEntry(channel)._receiver.OnData(p.Data, 8, len);
                    break;

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

                case PacketType.SSH_MSG_CHANNEL_CLOSE: {
                    channel = SSHUtil.ReadInt32(p.Data, 0);
                    ISSHChannelEventReceiver r = FindChannelEntry(channel)._receiver;
                    UnregisterChannelEventReceiver(channel);
                    r.OnChannelClosed();
                }
                break;

                case PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
                    channel = SSHUtil.ReadInt32(p.Data, 0);
                    break;

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

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

                case PacketType.SSH_MSG_DEBUG: {
                    SSH1DataReader re = new SSH1DataReader(p.Data);
                    _eventReceiver.OnDebugMessage(false, re.ReadString());
                }
                break;

                case PacketType.SSH_MSG_IGNORE: {
                    SSH1DataReader re = new SSH1DataReader(p.Data);
                    _eventReceiver.OnIgnoreMessage(re.ReadString());
                }
                break;

                case PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: {
                    int local  = SSHUtil.ReadInt32(p.Data, 0);
                    int remote = SSHUtil.ReadInt32(p.Data, 4);
                    FindChannelEntry(local)._receiver.OnChannelReady();
                }
                break;

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

                default:
                    _eventReceiver.OnUnknownMessage((byte)p.Type, p.Data);
                    break;
                }
            }
            catch (Exception ex) {
                if (!_closed)
                {
                    _eventReceiver.OnError(ex, ex.Message);
                }
            }
        }