/// <summary> /// Sign and encrypt for Single or Compound packet. /// </summary> public static byte[] SignAndEncrypt(Smb2Packet originalPacket, Dictionary<ulong, Smb2CryptoInfo> cryptoInfoTable, Smb2Role role) { ulong sessionId; bool isCompound = false; if (originalPacket is Smb2SinglePacket) { sessionId = (originalPacket as Smb2SinglePacket).Header.SessionId; } else if (originalPacket is Smb2CompoundPacket) { isCompound = true; // The subsequent request in compound packet should use the SessionId of the first request for encryption sessionId = (originalPacket as Smb2CompoundPacket).Packets[0].Header.SessionId; } else { throw new NotImplementedException(string.Format("Signing and encryption are not implemented for packet: {0}", originalPacket.ToString())); } // Signing and encryption not required if session id is not available yet if (sessionId == 0 || !cryptoInfoTable.ContainsKey(sessionId)) return originalPacket.ToBytes(); Smb2CryptoInfo cryptoInfo = cryptoInfoTable[sessionId]; #region Encrypt // Try to encrypt the message whenever the encryption is supported or not. // If it's not supported, do it for negative test. // For compound packet, the encryption is done for the entire message. byte[] encryptedBinary = Encrypt(sessionId, cryptoInfo, role, originalPacket); if (encryptedBinary != null) return encryptedBinary; #endregion #region Sign if (cryptoInfo.EnableSessionSigning) { if (isCompound) { // Calculate signature for every packet in the chain foreach (Smb2SinglePacket packet in (originalPacket as Smb2CompoundPacket).Packets) { // If the packet is the first one in the chain or the unralated one, use its own SessionId for sign and encrypt // If it's not the first one and it's the related one, use the SessionId of the first request for sign and encrypt if (!packet.Header.Flags.HasFlag(Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS)) { sessionId = packet.Header.SessionId; cryptoInfo = cryptoInfoTable[sessionId]; } packet.Header.Signature = Sign(cryptoInfo, packet.ToBytes()); } } else { (originalPacket as Smb2SinglePacket).Header.Signature = Sign(cryptoInfo, originalPacket.ToBytes()); } } #endregion return originalPacket.ToBytes(); }
/// <summary> /// Sign, compress and encrypt for Single or Compound packet. /// </summary> public static Smb2Packet SignCompressAndEncrypt(Smb2Packet originalPacket, Dictionary <ulong, Smb2CryptoInfo> cryptoInfoTable, Smb2CompressionInfo compressioninfo, Smb2Role role) { ulong sessionId; bool isCompound = false; bool notEncryptNotSign = false; bool notEncrypt = false; var compressedPacket = originalPacket; if (originalPacket is Smb2SinglePacket) { Smb2SinglePacket singlePacket = originalPacket as Smb2SinglePacket; sessionId = singlePacket.Header.SessionId; // [MS-SMB2] Section 3.2.4.1.8, the request being sent is SMB2 NEGOTIATE, // or the request being sent is SMB2 SESSION_SETUP with the SMB2_SESSION_FLAG_BINDING bit set in the Flags field, // the client MUST NOT encrypt the message if (sessionId == 0 || (singlePacket.Header.Command == Smb2Command.NEGOTIATE && (singlePacket is Smb2NegotiateRequestPacket))) { notEncryptNotSign = true; } else if ((singlePacket.Header.Command == Smb2Command.SESSION_SETUP && (singlePacket is Smb2SessionSetupRequestPacket) && (singlePacket as Smb2SessionSetupRequestPacket).PayLoad.Flags == SESSION_SETUP_Request_Flags.SESSION_FLAG_BINDING)) { notEncrypt = true; } } else if (originalPacket is Smb2CompoundPacket) { isCompound = true; // The subsequent request in compound packet should use the SessionId of the first request for encryption sessionId = (originalPacket as Smb2CompoundPacket).Packets[0].Header.SessionId; } else { throw new NotImplementedException(string.Format("Signing and encryption are not implemented for packet: {0}", originalPacket.ToString())); } if (sessionId == 0 || notEncryptNotSign || !cryptoInfoTable.ContainsKey(sessionId)) { if (originalPacket is Smb2CompressiblePacket) { compressedPacket = Smb2Compression.Compress(originalPacket as Smb2CompressiblePacket, compressioninfo, role); } return(compressedPacket); } Smb2CryptoInfo cryptoInfo = cryptoInfoTable[sessionId]; #region Encrypt // Try to encrypt the message whenever the encryption is supported or not except for sesstion setup. // If it's not supported, do it for negative test. // For compound packet, the encryption is done for the entire message. if (!notEncrypt) { if (originalPacket is Smb2CompressiblePacket) { compressedPacket = Smb2Compression.Compress(originalPacket as Smb2CompressiblePacket, compressioninfo, role); } var encryptedPacket = Encrypt(sessionId, cryptoInfo, role, compressedPacket, originalPacket); if (encryptedPacket != null) { return(encryptedPacket); } } #endregion #region Sign if (cryptoInfo.EnableSessionSigning) { if (isCompound) { // Calculate signature for every packet in the chain foreach (Smb2SinglePacket packet in (originalPacket as Smb2CompoundPacket).Packets) { // If the packet is the first one in the chain or the unralated one, use its own SessionId for sign and encrypt // If it's not the first one and it's the related one, use the SessionId of the first request for sign and encrypt if (!packet.Header.Flags.HasFlag(Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS)) { sessionId = packet.Header.SessionId; cryptoInfo = cryptoInfoTable[sessionId]; } packet.Header.Signature = Sign(cryptoInfo, packet.ToBytes()); } } else { (originalPacket as Smb2SinglePacket).Header.Signature = Sign(cryptoInfo, originalPacket.ToBytes()); } } #endregion if (originalPacket is Smb2CompressiblePacket) { compressedPacket = Smb2Compression.Compress(originalPacket as Smb2CompressiblePacket, compressioninfo, role); } return(compressedPacket); }
/// <summary> /// Sign and encrypt for Single or Compound packet. /// </summary> public static byte[] SignAndEncrypt(Smb2Packet originalPacket, Dictionary <ulong, Smb2CryptoInfo> cryptoInfoTable, Smb2Role role) { ulong sessionId; bool isCompound = false; if (originalPacket is Smb2SinglePacket) { sessionId = (originalPacket as Smb2SinglePacket).Header.SessionId; } else if (originalPacket is Smb2CompoundPacket) { isCompound = true; // The subsequent request in compound packet should use the SessionId of the first request for encryption sessionId = (originalPacket as Smb2CompoundPacket).Packets[0].Header.SessionId; } else { throw new NotImplementedException(string.Format("Signing and encryption are not implemented for packet: {0}", originalPacket.ToString())); } // Signing and encryption not required if session id is not available yet if (sessionId == 0 || !cryptoInfoTable.ContainsKey(sessionId)) { return(originalPacket.ToBytes()); } Smb2CryptoInfo cryptoInfo = cryptoInfoTable[sessionId]; #region Encrypt // Try to encrypt the message whenever the encryption is supported or not. // If it's not supported, do it for negative test. // For compound packet, the encryption is done for the entire message. byte[] encryptedBinary = Encrypt(sessionId, cryptoInfo, role, originalPacket); if (encryptedBinary != null) { return(encryptedBinary); } #endregion #region Sign if (cryptoInfo.EnableSessionSigning) { if (isCompound) { // Calculate signature for every packet in the chain foreach (Smb2SinglePacket packet in (originalPacket as Smb2CompoundPacket).Packets) { // If the packet is the first one in the chain or the unralated one, use its own SessionId for sign and encrypt // If it's not the first one and it's the related one, use the SessionId of the first request for sign and encrypt if (!packet.Header.Flags.HasFlag(Packet_Header_Flags_Values.FLAGS_RELATED_OPERATIONS)) { sessionId = packet.Header.SessionId; cryptoInfo = cryptoInfoTable[sessionId]; } packet.Header.Signature = Sign(cryptoInfo, packet.ToBytes()); } } else { (originalPacket as Smb2SinglePacket).Header.Signature = Sign(cryptoInfo, originalPacket.ToBytes()); } } #endregion return(originalPacket.ToBytes()); }