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); } }
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; } } }
//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)); }
//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); }
//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); }
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); }
/// <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)); }
/// <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()))); }
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); } }
//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); }
// 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); }
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); }
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; }
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); } } }
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); }
//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); }
/** * 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)); }
//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); }
/// <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); } } }
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(); }
/// <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; } }
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); }
/// <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); }
/// <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); } } }