/// <summary> /// Decode MCS Send Data Indication PDU /// </summary> /// <param name="data">data to be parsed</param> /// <param name="domainPdu">Mcs Domain PDU</param> /// <returns>decoded MCS Send Data Indication PDU</returns> private StackPacket DecodeMcsSendDataIndicationPDU(byte[] data, DomainMCSPDU domainPdu) { // Get Send Data Indication SendDataIndication indication = (SendDataIndication)domainPdu.GetData(); byte[] userData = indication.userData.ByteArrayValue; // Get Security Header Type SecurityHeaderType securityHeaderType = GetSecurityHeaderTypeByContext(); // Peek Security Header bool isLicenseErrorPdu = false; if (clientContext.IsWaitingLicenseErrorPdu) { isLicenseErrorPdu = IsLicenseErrorSecurityHeaderExist(userData); } // Decode PDU if (isLicenseErrorPdu) { // License Error PDU's Basic Security Header content is alway present int tempIndex = 0; TS_SECURITY_HEADER header = ParseTsSecurityHeader(userData, ref tempIndex, SecurityHeaderType.Basic); // Check if PDU is encrypted bool isEncryptedPdu = IsFlagExist((UInt16)header.flags, (UInt16)TS_SECURITY_HEADER_flags_Values.SEC_ENCRYPT); // Correct Server License Error PDU's security header type if needed if (!isEncryptedPdu || EncryptionLevel.ENCRYPTION_LEVEL_NONE == clientContext.RdpEncryptionLevel) { securityHeaderType = SecurityHeaderType.Basic; } // Get decrypted user data byte[] decryptedUserData = DecryptSendDataIndication(userData, securityHeaderType); // Decode Server License Error PDU return DecodeLicenseErrorPDU(data, decryptedUserData, securityHeaderType); } else { // Get decrypted user data byte[] decryptedUserData = DecryptSendDataIndication(userData, securityHeaderType); if (clientContext.MessageChannelId == indication.channelId.Value) { if (IsInitiateMultitransportRequestSecurityHeaderExist(userData)) { return DecodeServerInitiateMultitransportRequest(data, decryptedUserData, securityHeaderType); } else if (IsHeartbeatSecurityHeaderExist(userData)) { return DecodeServerHeartbeatPDU(data, decryptedUserData, securityHeaderType); } else { return DecodeServerAutoDetectRequestPDU(data, decryptedUserData, securityHeaderType); } } // Check channel ID (IO Channel ID/Virual Channel ID) else if (clientContext.IOChannelId != indication.channelId.Value) { // Decode Virtual Channel PDU return DecodeVirtualChannelPDU(data, decryptedUserData, securityHeaderType); } else if (IsStandardRedirectionPdu(userData, securityHeaderType)) { return DecodeServerRedirectionPDU(data, decryptedUserData, securityHeaderType); } else { // Decode other Send Data Indication PDUs return SwitchDecodeMcsSendDataIndicationPDU(data, decryptedUserData, securityHeaderType); } } }
/// <summary> /// Decode MCS Send Data Request PDU /// </summary> /// <param name="serverSessionContext">the server session context</param> /// <param name="data">data to be parsed</param> /// <param name="domainPdu">Mcs Domain PDU</param> /// <returns>decoded MCS Send Data Request PDU</returns> private StackPacket DecodeMcsSendDataRequestPDU(RdpbcgrServerSessionContext serverSessionContext, byte[] data, DomainMCSPDU domainPdu) { SendDataRequest indication = (SendDataRequest)domainPdu.GetData(); byte[] userData = indication.userData.ByteArrayValue; bool isSecurityExchange; bool isClientInfo; bool isAutoDetectResponsePDU; bool isMultitransportErrorPDU; // Get Security Header Type SecurityHeaderType securityHeaderType = GetSecurityHeaderTypeByContext(serverSessionContext); int i = 0; if (userData.Length == ParseUInt16(userData, ref i, false) || (securityHeaderType == SecurityHeaderType.None && serverSessionContext.IOChannelId != indication.channelId.Value && serverSessionContext.McsMsgChannelId != indication.channelId.Value)) { // the packet not transmitted in IO Channel cannot be Security Exchange PDU or Client Info PDU, so set all to false. isSecurityExchange = false; isClientInfo = false; isAutoDetectResponsePDU = false; isMultitransportErrorPDU = false; } else { int tempIndex = 0; TS_SECURITY_HEADER header = ParseTsSecurityHeader(userData, ref tempIndex, SecurityHeaderType.Basic); // Check if PDU is Security Exchange PDU isSecurityExchange = IsFlagExist((UInt16)header.flags, (UInt16)TS_SECURITY_HEADER_flags_Values.SEC_EXCHANGE_PKT); //Check if PDU is Client Info PDU isClientInfo = IsFlagExist((UInt16)header.flags, (UInt16)TS_SECURITY_HEADER_flags_Values.SEC_INFO_PKT); //check if PDU is Auto Detect Response PDU isAutoDetectResponsePDU = IsFlagExist((UInt16)header.flags, (UInt16)TS_SECURITY_HEADER_flags_Values.SEC_AUTODETECT_RSP); //check if PDU is Client Initiate Multitransport Error PDU isMultitransportErrorPDU = IsFlagExist((UInt16)header.flags, (UInt16)TS_SECURITY_HEADER_flags_Values.SEC_TRANSPORT_RSP); } if (isSecurityExchange) { securityHeaderType = SecurityHeaderType.Basic; byte[] decryptedUserData = DecryptSendDataRequest(serverSessionContext, userData, securityHeaderType); return DecodeSecurityExchangePdu(serverSessionContext, data, decryptedUserData, securityHeaderType); } else if (isClientInfo) { if (serverSessionContext.RdpEncryptionLevel == EncryptionLevel.ENCRYPTION_LEVEL_NONE && serverSessionContext.RdpEncryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_NONE) { securityHeaderType = SecurityHeaderType.Basic; } else if (serverSessionContext.RdpEncryptionLevel == EncryptionLevel.ENCRYPTION_LEVEL_FIPS && serverSessionContext.RdpEncryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_FIPS) { securityHeaderType = SecurityHeaderType.Fips; } else { securityHeaderType = SecurityHeaderType.NonFips; } byte[] decryptedUserData = DecryptSendDataRequest(serverSessionContext, userData, securityHeaderType); return DecodeClientInfoPdu(data, decryptedUserData, securityHeaderType); } else if (isAutoDetectResponsePDU) { if (serverSessionContext.RdpEncryptionLevel == EncryptionLevel.ENCRYPTION_LEVEL_NONE && serverSessionContext.RdpEncryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_NONE) { securityHeaderType = SecurityHeaderType.Basic; } else if (serverSessionContext.RdpEncryptionLevel == EncryptionLevel.ENCRYPTION_LEVEL_FIPS && serverSessionContext.RdpEncryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_FIPS) { securityHeaderType = SecurityHeaderType.Fips; } else { securityHeaderType = SecurityHeaderType.NonFips; } byte[] decryptedUserData = DecryptSendDataRequest(serverSessionContext, userData, securityHeaderType); return DecodeClientAutoDetectResponsePDU(data, decryptedUserData, securityHeaderType); } else if (isMultitransportErrorPDU) { if (serverSessionContext.RdpEncryptionLevel == EncryptionLevel.ENCRYPTION_LEVEL_NONE && serverSessionContext.RdpEncryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_NONE) { securityHeaderType = SecurityHeaderType.Basic; } else if (serverSessionContext.RdpEncryptionLevel == EncryptionLevel.ENCRYPTION_LEVEL_FIPS && serverSessionContext.RdpEncryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_FIPS) { securityHeaderType = SecurityHeaderType.Fips; } else { securityHeaderType = SecurityHeaderType.NonFips; } byte[] decryptedUserData = DecryptSendDataRequest(serverSessionContext, userData, securityHeaderType); return DecodeClientInitiateMultitransportResponsePDU(data, decryptedUserData, securityHeaderType); } else { if(!serverSessionContext.IsClientToServerEncrypted) securityHeaderType = SecurityHeaderType.Basic; // Get decrypted user data byte[] decryptedUserData = DecryptSendDataRequest(serverSessionContext, userData, securityHeaderType); // Check channel ID (IO Channel ID/Virual Channel ID) if (serverSessionContext.IOChannelId != indication.channelId.Value) { // Decode Virtual Channel PDU return DecodeVirtualChannelPDU(data, decryptedUserData, securityHeaderType); } else { // Decode other Send Data Indication PDUs return SwitchDecodeMcsSendDataRequestPDU(data, decryptedUserData, securityHeaderType); } } }