/// <summary> /// Decode Control PDU /// </summary> /// <param name="data">data to be parsed</param> /// <param name="decryptedUserData">decrypted user data to be parsed</param> /// <param name="type">security header type</param> /// <returns>decoded Control PDU</returns> public StackPacket DecodeControlPDU( byte[] data, byte[] decryptedUserData, SecurityHeaderType type) { // data index int dataIndex = 0; // ControlPDU: commonHeader SlowPathPduCommonHeader commonHeader = ParseMcsCommonHeader(data, ref dataIndex, type); // user data index int userDataIndex = 0; // ControlPDU: controlPduData TS_CONTROL_PDU controlPduData = ParseTsControlPdu(decryptedUserData, ref userDataIndex); // Get pdu by action type StackPacket pdu; if (controlPduData.action == action_Values.CTRLACTION_COOPERATE) { // Control PDU - cooperate Client_Control_Pdu_Cooperate cooperatePdu = new Client_Control_Pdu_Cooperate(); cooperatePdu.commonHeader = commonHeader; cooperatePdu.controlPduData = controlPduData; pdu = cooperatePdu; // ETW Provider Dump Message if (cooperatePdu.commonHeader.securityHeader != null) { // RDP Standard Security string messageName = "RDPBCGR:" + cooperatePdu.GetType().Name; ExtendedLogger.DumpMessage(messageName, RdpbcgrUtility.DumpLevel_Layer3, cooperatePdu.GetType().Name, decryptedUserData); } } else if (controlPduData.action == action_Values.CTRLACTION_REQUEST_CONTROL) { // Control PDU - granted control Client_Control_Pdu_Request_Control requestPdu = new Client_Control_Pdu_Request_Control(); requestPdu.commonHeader = commonHeader; requestPdu.controlPduData = controlPduData; pdu = requestPdu; // ETW Provider Dump Message if (requestPdu.commonHeader.securityHeader != null) { // RDP Standard Security string messageName = "RDPBCGR:" + requestPdu.GetType().Name; ExtendedLogger.DumpMessage(messageName, RdpbcgrUtility.DumpLevel_Layer3, requestPdu.GetType().Name, decryptedUserData); } } else { throw new FormatException(ConstValue.ERROR_MESSAGE_ENUM_UNRECOGNIZED); } // Check if data length exceeded expectation VerifyDataLength(decryptedUserData.Length, userDataIndex, ConstValue.ERROR_MESSAGE_DATA_LENGTH_EXCEEDED); return pdu; }
/// <summary> /// 2.2.1.15 /// </summary> /// <param name="clientCoopPdu"></param> public void VerifyPdu(Client_Control_Pdu_Cooperate clientCoopPdu) { if (serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT || serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT || serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT) { site.CaptureRequirementIfIsInstanceOfType(clientCoopPdu.commonHeader.securityHeader, typeof(TS_SECURITY_HEADER1), 747, @"[In Client Control PDU - Cooperate]securityHeader (variable): The securityHeader in " + @"Server Demand Active PDU is a Non-FIPS Security Header (section 2.2.8.1.1.2.2) if " + @"the Encryption LevelMethod selected by the server (see sections 5.3.2 and 2.2.1.4.3) " + @"is ENCRYPTION_LEVEL_CLIENT_COMPATIBLE (2)METHOD_40BIT (0x00000001), ENCRYPTION_METHOD_56BIT" + @" (0x00000008), or ENCRYPTION_LEVEL_HIGH (3METHOD_128BIT (0x00000002)."); } else if (serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_FIPS) { site.CaptureRequirementIfIsInstanceOfType(clientCoopPdu.commonHeader.securityHeader, typeof(TS_SECURITY_HEADER2), 748, @"[In Client Control PDU - Cooperate]securityHeader (variable):The securityHeader in Server" + @" Demand Active PDU is a FIPS Security Header,if the Encryption LevelMethod selected by " + @"the server is ENCRYPTION_METHOD_FIPS (0x00000010)."); } else if (serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_NONE) { site.CaptureRequirementIfIsNull(clientCoopPdu.commonHeader.securityHeader, 749, @" Client Control PDU - Cooperate ,If Enhanced RDP Security is in effect or the Encryption " + @"Method selected by the server is ENCRYPTION_METHOD_NONE (0), then securityHeader MUST NOT" + @" be included in the Client Control PDU - Cooperate."); } site.CaptureRequirementIfIsTrue(clientCoopPdu.controlPduData.controlId == 0 && clientCoopPdu.controlPduData.grantId == 0, 751, @"In controlPduData of Client Control PDU - Cooperate, The grantId and controlId fields of the " + @"Control PDU Data MUST both be set to zero."); site.CaptureRequirementIfAreEqual<action_Values>(action_Values.CTRLACTION_COOPERATE, clientCoopPdu.controlPduData.action, 752, @"In controlPduData of Client Control PDU - Cooperate, the action field MUST be set to " + @"CTRLACTION_COOPERATE (0x0004)."); site.CaptureRequirementIfAreEqual<int>(7, (clientCoopPdu.controlPduData.shareDataHeader.shareControlHeader.pduType.typeAndVersionLow & 0xf), 755, @"In TS_CONTROL_PDU, the type subfield of the pduType field of the Share Control Header of TS_CONTROL_PDU" + @" structure MUST be set to PDUTYPE_DATAPDU (7). "); site.CaptureRequirementIfAreEqual<pduType2_Values>(pduType2_Values.PDUTYPE2_CONTROL, clientCoopPdu.controlPduData.shareDataHeader.pduType2, 756, @" In TS_CONTROL_PDU, the pduType2 field of the Share Data Header of TS_CONTROL_PDU structure MUST be set" + @" to PDUTYPE2_CONTROL (20)."); bool isR758Satisfied = clientCoopPdu.controlPduData.action == action_Values.CTRLACTION_REQUEST_CONTROL || clientCoopPdu.controlPduData.action == action_Values.CTRLACTION_GRANTED_CONTROL || clientCoopPdu.controlPduData.action == action_Values.CTRLACTION_DETACH || clientCoopPdu.controlPduData.action == action_Values.CTRLACTION_COOPERATE; site.CaptureRequirementIfIsTrue(isR758Satisfied, 758, @"In TS_CONTROL_PDU, the action field must take one of the following values 1.CTRLACTION_REQUEST_CONTROL" + @" 0x0001 - Request control 2.CTRLACTION_GRANTED_CONTROL 0x0002 - Granted control 3.CTRLACTION_DETACH " + @"0x0003 - Detach 4.CTRLACTION_COOPERATE 0x0004 - Cooperate"); }
/// <summary> /// Create an instance of the class that is identical to the current PDU. /// </summary> /// <returns>The new instance.</returns> public override StackPacket Clone() { Client_Control_Pdu_Cooperate cloneControlCoopPdu = new Client_Control_Pdu_Cooperate(context); cloneControlCoopPdu.commonHeader = commonHeader.Clone(); cloneControlCoopPdu.controlPduData = controlPduData; return cloneControlCoopPdu; }