/// <summary> /// This ROP logs on to a private mailbox or public folder. /// </summary> /// <param name="logonType">This type specifies ongoing action on the private mailbox or public folder.</param> /// <param name="logonResponse">The response of this ROP.</param> /// <param name="userDN">This string specifies which mailbox to log on to.</param> /// <param name="needVerify">Whether need to verify the response.</param> /// <returns>The handle of logon object.</returns> private uint RopLogon(LogonType logonType, out RopLogonResponse logonResponse, string userDN, bool needVerify) { this.rawDataValue = null; this.responseValue = null; this.responseSOHsValue = null; userDN += "\0"; uint insideObjHandle = 0; RopLogonRequest logonRequest = new RopLogonRequest() { RopId = (byte)RopId.RopLogon, LogonId = LogonId, OutputHandleIndex = (byte)HandleIndex.FirstIndex, StoreState = (uint)StoreState.None, // Set parameters for public folder logon type. LogonFlags = logonType == LogonType.PublicFolder ? (byte)LogonFlags.PublicFolder : (byte)LogonFlags.Private, OpenFlags = logonType == LogonType.PublicFolder ? (uint)(OpenFlags.UsePerMDBReplipMapping | OpenFlags.Public) : (uint)OpenFlags.UsePerMDBReplipMapping, // Set EssdnSize to 0, which specifies the size of the ESSDN field. EssdnSize = logonType == LogonType.PublicFolder ? (ushort)0 : (ushort)Encoding.ASCII.GetByteCount(userDN), Essdn = logonType == LogonType.PublicFolder ? null : Encoding.ASCII.GetBytes(userDN), }; this.responseSOHsValue = this.ProcessSingleRop(logonRequest, insideObjHandle, ref this.responseValue, ref this.rawDataValue, RopResponseType.SuccessResponse); logonResponse = (RopLogonResponse)this.responseValue; if (needVerify) { this.Site.Assert.AreEqual((uint)RopResponseType.SuccessResponse, logonResponse.ReturnValue, string.Format("Logon Failed! Error: 0x{0:X8}", logonResponse.ReturnValue)); } return this.responseSOHsValue[0][logonResponse.OutputHandleIndex]; }
/// <summary> /// Logon Mail server. /// </summary> /// <param name="logonType">Logon Type.</param> /// <param name="objHandle">Server response handle.</param> /// <param name="openFlags">The possible values are specified in [MS-OXCSTOR]. This structure contains more flags that control the behavior of the logon.</param> /// <returns>Logon Response.</returns> protected RopLogonResponse Logon(LogonFlags logonType, out uint objHandle, uint openFlags) { RopLogonRequest logonRequest = new RopLogonRequest(); object ropResponse = null; string userDN = Common.GetConfigurationPropertyValue("AdminUserEssdn", this.Site) + Constants.StringNullTerminated; logonRequest.RopId = (byte)RopId.RopLogon; logonRequest.LogonId = Constants.CommonLogonId; logonRequest.OutputHandleIndex = 0x0; logonRequest.StoreState = 0; logonRequest.LogonFlags = (byte)logonType; logonRequest.OpenFlags = openFlags; if (LogonFlags.PublicFolder == logonType) { logonRequest.EssdnSize = 0; logonRequest.Essdn = null; } else if (LogonFlags.Private == logonType) { logonRequest.EssdnSize = (ushort)Encoding.ASCII.GetByteCount(userDN); logonRequest.Essdn = Encoding.ASCII.GetBytes(userDN); } this.Adapter.DoRopCall(logonRequest, this.LogonHandle, ref ropResponse, ref this.responseHandles); RopLogonResponse logonResponse = (RopLogonResponse)ropResponse; objHandle = this.responseHandles[0][logonResponse.OutputHandleIndex]; this.defaultFolderIds = logonResponse.FolderIds; return logonResponse; }
/// <summary> /// Compose a Logon ROP request. /// </summary> /// <returns>Return a Logon ROP request.</returns> private RopLogonRequest GetRopLogonRequest() { RopLogonRequest logonRop = new RopLogonRequest(); logonRop.RopId = (byte)RopId.RopLogon; // RopId 0XFE indicates RopLogon. logonRop.LogonId = ConstValues.LogonId; // The logonId 0x00 is associated with this operation. logonRop.OutputHandleIndex = 0x00; // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the output Server Object is stored. string userDN = this.AdminUserDN + "\0"; // A null-terminated string that specifies the DN of the AdminUser who is requesting the connection. logonRop.StoreState = 0; // A flags structure. This field MUST be set to 0x00000000. logonRop.LogonFlags = 0x01; // Logon to a private mailbox. logonRop.OpenFlags = 0x01000000; // For a private-mailbox logon, the USE_PER_MDB_REPLID_MAPPING flag should be set. logonRop.EssdnSize = (ushort)System.Text.Encoding.ASCII.GetByteCount(userDN); logonRop.Essdn = System.Text.Encoding.ASCII.GetBytes(userDN); return logonRop; }
/// <summary> /// Verify the response by sending the ROP RopLogon for the private mailbox. /// </summary> /// <param name="request">The structure of ROP RopLogon request.</param> /// <param name="response">The structure of ROP RopLogon response.</param> private void VerifyRopLogonForPrivateMailbox(RopLogonRequest request, RopLogonResponse response) { if (response.ReturnValue == 0) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R13"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R13 // If calling RopLogon ROP successfully, indicates the logon session is established. this.Site.CaptureRequirement( 13, @"[In RopLogon ROP] The RopLogon ROP ([MS-OXCROPS] section 2.2.3.1) establishes a logon session between the client and the server."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R106"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R106 // If calling RopLogon ROP successfully, indicates the Essdn is right identifier to log on to mailbox. this.Site.CaptureRequirement( 106, @"[In RopLogon ROP Request Buffer] Essdn: In the case of a private mailbox logon, this field contains an ASCII string that uniquely identifies a mailbox to log on to."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R123"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R123 this.Site.CaptureRequirementIfAreEqual<byte>( 0x01, (byte)(response.ResponseFlags & (byte)0x01), 123, @"[In RopLogon ROP Success Response Buffer for Private Mailbox] [Response Flags] The description of flag Reserved: This bit [Reserved] MUST be set."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R122"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R122 // Check if the flag Reserved is 0x01. Site.CaptureRequirementIfAreEqual<byte>( 0x01, (byte)(response.ResponseFlags & (byte)0x01), 122, @"[In RopLogon ROP Success Response Buffer for Private Mailbox] [Response Flags] The value of flag Reserved: 0x01."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R1062"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1062 this.Site.CaptureRequirementIfAreEqual<byte>( request.LogonFlags, response.LogonFlags, 1062, @"[In RopLogon ROP Success Response Buffer for Private Mailbox] LogonFlags: The server returns these flags [Private, Undercover, and Ghostedflags] unchanged from the LogonFlags field of the RopLogon request (section 2.2.1.1.1)."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R118"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R118 this.Site.CaptureRequirementIfAreEqual<byte>( request.LogonFlags, response.LogonFlags, 118, @"[In RopLogon ROP Success Response Buffer for Private Mailbox] LogonFlags: This field is composed of the Private, Undercover, and Ghosted flags."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R117"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R117 // The RopLogon ROP response structure for public folders is designated Site.CaptureRequirement( 117, @"[In RopLogon ROP Success Response Buffer for Private Mailbox] The following field values [LogonFlags, FolderIds, Response Flags, ReplId, ReplGuid, Logon Time, GwartTime, StoreState] are included in the RopLogon response only when the Private bit is set in the LogonFlags field of the RopLogon request (section 2.2.1.1.1)."); } }
/// <summary> /// Verify the response by sending the ROP RopLogon for the public folders. /// </summary> /// <param name="request">The structure of ROP RopLogon request.</param> /// <param name="response">The structure of ROP ROPLogonForPublicFolder response.</param> private void VerifyRopLogonForPublicFolder(RopLogonRequest request, RopLogonResponse response) { // The returnValue is 0 to indicate that the response is successful. if (response.ReturnValue == 0) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R13"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R13 this.Site.CaptureRequirementIfAreEqual<uint>( 0, response.ReturnValue, 13, @"[In RopLogon ROP] The RopLogon ROP ([MS-OXCROPS] section 2.2.3.1) establishes a logon session between the client and the server."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R146, LogonFlags:{0}", response.LogonFlags); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R146 bool isVerifyR146 = ((LogonFlags)response.LogonFlags & ~(LogonFlags.Private | LogonFlags.PublicFolder | LogonFlags.Ghosted | LogonFlags.Undercover)) == 0; Site.CaptureRequirementIfIsTrue( isVerifyR146, 146, @"[In RopLogon ROP Success Response Buffer for Public Folders] LogonFlags: This field [LogonFlags] is composed of the Private, Undercover, and Ghosted flags."); #region Capture 1071 // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R1071"); // In the step2 logon a Public Folders. // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1071 Site.CaptureRequirementIfAreEqual<byte>( request.LogonFlags, response.LogonFlags, 1071, @"[In RopLogon ROP Success Response Buffer for Public Folders] LogonFlags: The server returns these flags [Private, Undercover, and Ghosted] unchanged from the LogonFlags field of the RopLogon request (section 2.2.1.1.1)."); #endregion Guid perUserGuid = new Guid(response.PerUserGuid); if (Common.IsRequirementEnabled(1332, this.Site)) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R1332"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1332 this.Site.CaptureRequirementIfAreNotEqual<Guid>( Guid.Empty, perUserGuid, 1332, @"[In Appendix A: Product Behavior] The implementation does not set the PerUserGuid field to an empty GUID. (<9> Section 2.2.1.1.4: Exchange 2007 does not set the PerUserGuid field to an empty GUID.)"); } if (Common.IsRequirementEnabled(163, this.Site)) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R163"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R163 this.Site.CaptureRequirementIfAreEqual<Guid>( Guid.Empty, perUserGuid, 163, @"Implementation does set this field [PerUserGuid in RopLogon ROP Success Response Buffer for Public Folders] to an empty GUID (all zeroes). (Exchange 2003, Exchange 2010 and above follow this behavior.)"); } // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R3012"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R3012 // Check if the LogonFlag is set. bool isVerifyR3012 = (response.LogonFlags & (byte)LogonFlags.Private) == (byte)LogonFlags.Private; // The server returns the LogonFlags unchanged from the LogonFlag filed of the RopLogon request , So // if the response LgonFlag don't contain Private flag, it is not set in the request, then this requirement // will be verified. Site.CaptureRequirementIfIsFalse( isVerifyR3012, 3012, @"[In RopLogon ROP Success Response Buffer for Public Folders] The success response buffer for public folders is sent only when the Private bit is not set in the LogonFlags field of the RopLogon request (section 2.2.1.1.1)."); } else if (response.ReturnValue == 0x00000478) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R112"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R112 bool isVerifyR112 = ((LogonFlags)response.LogonFlags & ~(LogonFlags.Private | LogonFlags.PublicFolder | LogonFlags.Ghosted | LogonFlags.Undercover)) == 0; Site.CaptureRequirementIfIsTrue( isVerifyR112, 112, @"[In RopLogon ROP Redirect Response Buffer] LogonFlags: This field contains the Private, Undercover, and Ghosted flags."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R115"); // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R115 bool isVerifyR115 = Common.IsNullTerminatedASCIIStr(response.ServerName); Site.CaptureRequirementIfIsTrue( isVerifyR115, 115, @"[In RopLogon ROP Redirect Response Buffer] ServerName: The string includes the terminating NULL character."); } }
public void MSOXCMSG_S03_TC02_RopSetReadFlagsAsyncEnable() { this.CheckMapiHttpIsSupported(); this.ConnectToServer(ConnectionType.PrivateMailboxServer); #region Call RopLogon to logon specific private mailbox and SUPPORT_PROGRESS flag is set in the OpenFlags field. string userDN = Common.GetConfigurationPropertyValue("AdminUserEssdn", this.Site) + "\0"; RopLogonRequest logonRequest = new RopLogonRequest() { RopId = (byte)RopId.RopLogon, LogonId = CommonLogonId, OutputHandleIndex = 0x00, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the output Server Object is stored. StoreState = 0, LogonFlags = (byte)LogonFlags.Private, OpenFlags = (uint)OpenFlags.UsePerMDBReplipMapping | 0x20000000, EssdnSize = (ushort)Encoding.ASCII.GetByteCount(userDN), Essdn = Encoding.ASCII.GetBytes(userDN) }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(logonRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); RopLogonResponse logonResponse = (RopLogonResponse)this.response; uint objHandle = this.ResponseSOHs[0][logonResponse.OutputHandleIndex]; #endregion #region Call RopCreateMessage to create a new Message object. uint targetMessageHandle = this.CreatedMessage(logonResponse.FolderIds[4], objHandle); #endregion #region Call RopSaveChangesMessage to save the message created by step 2. RopSaveChangesMessageResponse saveChangesMessageResponse = this.SaveMessage(targetMessageHandle, (byte)SaveFlags.ForceSave); Site.Assert.AreEqual<uint>(TestSuiteBase.Success, saveChangesMessageResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg); ulong[] messageIds = new ulong[1]; messageIds[0] = saveChangesMessageResponse.MessageId; #endregion #region Call RopOpenFolder to open Inbox folder. uint folderHandle = this.OpenSpecificFolder(logonResponse.FolderIds[4], objHandle); #endregion #region Call RopSetReadFlags to change the state of the PidTagMessageFlags property and the WantAsynchronous flag is set in RopSetReadFlags. RopSetReadFlagsRequest setReadFlagsRequet = new RopSetReadFlagsRequest { RopId = (byte)RopId.RopSetReadFlags, LogonId = CommonLogonId, InputHandleIndex = CommonInputHandleIndex, WantAsynchronous = 0x01, ReadFlags = (byte)ReadFlags.ClearReadFlag, MessageIds = messageIds, MessageIdCount = Convert.ToUInt16(messageIds.Length) }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(setReadFlagsRequet, folderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); #region Verify MS-OXCMSG_R1705, MS-OXCMSG_R1706 if (Common.IsRequirementEnabled(1705, this.Site)) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R1705, server returns response type is {0}.", this.response.GetType()); // Verify MS-OXCMSG requirement: MS-OXCMSG_R1705 bool isVerifiedR1705 = this.response is RopSetReadFlagsResponse; this.Site.CaptureRequirementIfIsTrue( isVerifiedR1705, 1705, @"[In Appendix A: Product Behavior] Implementation does return a RopSetReadFlags ROP response if the WantAsynchronous flag is nonzero. (Exchange 2007 and above follow this behavior.)"); } if (Common.IsRequirementEnabled(1706, this.Site)) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R1706,server returns response type is {0}.", this.response.GetType()); this.Site.CaptureRequirementIfIsNotInstanceOfType( this.response, typeof(RopProgressResponse), 1706, @"[In Appendix A: Product Behavior] Implementation doesn't return a RopProgress ROP response instead if the WantAsynchronous flag is nonzero. (Exchange 2007 and above follow this behavior.)"); } #endregion #endregion #region Call RopRelease to release all resources. this.ReleaseRop(targetMessageHandle); this.ReleaseRop(folderHandle); #endregion }
public void MSOXCMSG_S01_TC11_CreateMessageWithoutPermissions() { this.CheckMapiHttpIsSupported(); this.ConnectToServer(ConnectionType.PrivateMailboxServer); string commonUser = Common.GetConfigurationPropertyValue("CommonUser", Site); string commonUserPassword = Common.GetConfigurationPropertyValue("CommonUserPassword", Site); string commonUserEssdn = Common.GetConfigurationPropertyValue("CommonUserEssdn", Site); #region Call RopLogon to log on a private mailbox. RopLogonResponse logonResponse = this.Logon(LogonType.Mailbox, out this.insideObjHandle); #endregion #region Call RopOpenFolder to open inbox folder uint openedFolderHandle = this.OpenSpecificFolder(logonResponse.FolderIds[4], this.insideObjHandle); #endregion #region Add Read permission to "CommonUser" on inbox folder. // Add folder visible permission for the inbox. uint pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible | (uint)PidTagMemberRights.ReadAny; this.AddPermission(commonUserEssdn, pidTagMemberRights, openedFolderHandle); #endregion #region Call RopLogon to logon the private mailbox with "CommonUser" this.rawData = null; this.insideObjHandle = 0; this.response = null; this.ResponseSOHs = null; this.MSOXCMSGAdapter.RpcDisconnect(); this.MSOXCMSGAdapter.Reset(); this.MSOXCMSGAdapter.RpcConnect(ConnectionType.PrivateMailboxServer, commonUser, commonUserPassword, commonUserEssdn); string userDN = Common.GetConfigurationPropertyValue("AdminUserEssdn", this.Site) + "\0"; RopLogonRequest logonRequest = new RopLogonRequest() { RopId = (byte)RopId.RopLogon, LogonId = CommonLogonId, OutputHandleIndex = 0x00, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the output Server Object is stored. StoreState = 0, LogonFlags = 0x01, // Logon to a private mailbox OpenFlags = (uint)OpenFlags.UsePerMDBReplipMapping, // Requesting admin access to the mail box EssdnSize = (ushort)Encoding.ASCII.GetByteCount(userDN), Essdn = Encoding.ASCII.GetBytes(userDN) }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(logonRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); logonResponse = (RopLogonResponse)this.response; Site.Assert.AreEqual<uint>(TestSuiteBase.Success, logonResponse.ReturnValue, "Call RopLogon should success."); uint objHandle = this.ResponseSOHs[0][logonResponse.OutputHandleIndex]; #endregion #region Call RopCreateMessage to create new Message object in folder without permission. RopCreateMessageRequest createMessageRequest = new RopCreateMessageRequest() { RopId = (byte)RopId.RopCreateMessage, LogonId = CommonLogonId, InputHandleIndex = CommonInputHandleIndex, OutputHandleIndex = CommonOutputHandleIndex, CodePageId = 0x0FFF, // Code page of Logon object is used FolderId = logonResponse.FolderIds[4], // Create a message in INBOX which root is mailbox AssociatedFlag = 0x00 // NOT an FAI message }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(createMessageRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); RopCreateMessageResponse createMessageResponse = (RopCreateMessageResponse)this.response; if(Common.IsRequirementEnabled(3017,this.Site)) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R3017"); // Verify MS-OXCMSG requirement: MS-OXCMSG_R3017 this.Site.CaptureRequirementIfAreEqual<uint>( 0x000004FF, createMessageResponse.ReturnValue, 3017, @"[In Appendix A: Product Behavior] [ecNoCreateRight (0x000004FF)] The user does not have permissions to create this message [RopCreateMessage]. (<24> Section 3.2.5.2: Exchange 2007 and Exchange 2010 follow this behavior.)"); } if(Common.IsRequirementEnabled(3018,this.Site)) { // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R3018"); // Verify MS-OXCMSG requirement: MS-OXCMSG_R3018 this.Site.CaptureRequirementIfAreEqual<uint>( 0x80070005, createMessageResponse.ReturnValue, 3018, @"[In Appendix A: Product Behavior] [ecAccessDenied (0x80070005)] The user does not have permissions to create this message [RopCreateMessage]. (Exchange 2013 and above follow this behavior.)"); } #endregion }
public void MSOXCMSG_S05_TC08_RopOpenMessageWithoutRight() { this.CheckMapiHttpIsSupported(); this.ConnectToServer(ConnectionType.PrivateMailboxServer); string commonUser = Common.GetConfigurationPropertyValue("CommonUser", Site); string commonUserPassword = Common.GetConfigurationPropertyValue("CommonUserPassword", Site); string commonUserEssdn = Common.GetConfigurationPropertyValue("CommonUserEssdn", Site); uint pidTagMemberRights; #region Call RopLogon to logon the private mailbox with administrator. RopLogonResponse logonResponse = this.Logon(LogonType.Mailbox, out this.insideObjHandle); #endregion #region Call RopOpenFolder to open the inbox folder. ulong parentFolderId = logonResponse.FolderIds[4]; uint openedInboxFolderHandle = this.OpenSpecificFolder(parentFolderId, this.insideObjHandle); #endregion #region Call RopCreateFolder to create a new subfolder. ulong thirdSubfolderId; uint thirdSubFolderHandle = this.CreateSubFolder(openedInboxFolderHandle, out thirdSubfolderId); LongTermId thirdSubfolderLongTermID = this.GetLongTermIdFormID(thirdSubfolderId, this.insideObjHandle); #endregion #region Call RopCreateMessage and RopSaveChangesMessage to create a Message object in subfolder created. // Create a message in InBox this.MessageHandle = this.CreatedMessage(thirdSubfolderId, this.insideObjHandle); RopSaveChangesMessageResponse saveChangesMessageResponse = this.SaveMessage(this.MessageHandle, (byte)SaveFlags.KeepOpenReadWrite); ulong thirdMessageId = saveChangesMessageResponse.MessageId; LongTermId thirdMessageLongTermID = this.GetLongTermIdFormID(thirdMessageId, this.insideObjHandle); this.ReleaseRop(this.MessageHandle); #endregion #region Add Read permission to "CommonUser" on inbox folder. // Add folder visible permission for the inbox. pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible | (uint)PidTagMemberRights.ReadAny; this.AddPermission(commonUserEssdn, pidTagMemberRights, openedInboxFolderHandle); #endregion #region Add Read and write permission to "CommonUser" on subfolder pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible; this.AddPermission(commonUserEssdn, pidTagMemberRights, thirdSubFolderHandle); #endregion #region Call RopLogon to logon the private mailbox with "CommonUser" this.rawData = null; this.insideObjHandle = 0; this.response = null; this.ResponseSOHs = null; this.MSOXCMSGAdapter.RpcDisconnect(); this.MSOXCMSGAdapter.Reset(); this.MSOXCMSGAdapter.RpcConnect(ConnectionType.PrivateMailboxServer, commonUser, commonUserPassword, commonUserEssdn); string userDN = Common.GetConfigurationPropertyValue("AdminUserEssdn", this.Site) + "\0"; RopLogonRequest logonRequest = new RopLogonRequest() { RopId = (byte)RopId.RopLogon, LogonId = CommonLogonId, OutputHandleIndex = 0x00, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the output Server Object is stored. StoreState = 0, LogonFlags = 0x01, // Logon to a private mailbox OpenFlags = (uint)OpenFlags.UsePerMDBReplipMapping, // Requesting admin access to the mail box EssdnSize = (ushort)Encoding.ASCII.GetByteCount(userDN), Essdn = Encoding.ASCII.GetBytes(userDN) }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(logonRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); logonResponse = (RopLogonResponse)this.response; Site.Assert.AreEqual<uint>(TestSuiteBase.Success, logonResponse.ReturnValue, "Call RopLogon should success."); uint objHandle = this.ResponseSOHs[0][logonResponse.OutputHandleIndex]; #endregion #region Call RopOpenMessage to open a message that the user does not have rights to the message. thirdSubfolderId = this.GetObjectIdFormLongTermID(thirdSubfolderLongTermID, objHandle); thirdMessageId = this.GetObjectIdFormLongTermID(thirdMessageLongTermID, objHandle); RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest() { RopId = (byte)RopId.RopOpenMessage, LogonId = CommonLogonId, InputHandleIndex = CommonInputHandleIndex, OutputHandleIndex = CommonOutputHandleIndex, CodePageId = 0x0FFF, // Code page of Logon object is used FolderId = thirdSubfolderId, OpenModeFlags = (byte)MessageOpenModeFlags.ReadWrite, MessageId = thirdMessageId }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequest, objHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); RopOpenMessageResponse openMessageResponse = (RopOpenMessageResponse)this.response; #region Verify requirements // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R324"); // Verify MS-OXCMSG requirement: MS-OXCMSG_R324 this.Site.CaptureRequirementIfAreNotEqual<uint>( TestSuiteBase.Success, openMessageResponse.ReturnValue, 324, @"[in Receiving a RopOpenMessage ROP Request] RopOpenMessage MUST NOT succeed if the client has insufficient access rights to the folder in which the Message object is stored."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R2184"); // Verify MS-OXCMSG requirement: MS-OXCMSG_R2184 this.Site.CaptureRequirementIfAreEqual<uint>( 0x80070005, openMessageResponse.ReturnValue, 2184, @"[In Receiving a RopOpenMessage ROP Request] [ecAccessDenied(0x80070005)] The user does not have rights to the message."); #endregion #endregion #region Call RopLogon to logon the private mailbox with administrator this.rawData = null; this.insideObjHandle = 0; this.response = null; this.ResponseSOHs = null; this.MSOXCMSGAdapter.RpcDisconnect(); this.MSOXCMSGAdapter.Reset(); this.ConnectToServer(ConnectionType.PrivateMailboxServer); logonResponse = this.Logon(LogonType.Mailbox, out this.insideObjHandle); openedInboxFolderHandle = this.OpenSpecificFolder(logonResponse.FolderIds[4], this.insideObjHandle); #endregion #region Call RopDeleteFolder to delete the subfolder created thirdSubfolderId = this.GetObjectIdFormLongTermID(thirdSubfolderLongTermID, this.insideObjHandle); RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest() { RopId = (byte)RopId.RopDeleteFolder, LogonId = CommonLogonId, InputHandleIndex = CommonInputHandleIndex, DeleteFolderFlags = (byte)DeleteFolderFlags.DeleteHardDelete | (byte)DeleteFolderFlags.DelMessages, FolderId = thirdSubfolderId }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(deleteFolderRequest, openedInboxFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); RopDeleteFolderResponse deleteFolderresponse = (RopDeleteFolderResponse)this.response; Site.Assert.AreEqual<uint>(TestSuiteBase.Success, deleteFolderresponse.ReturnValue, "Call RopDeleteFolder should success."); #endregion }
public void MSOXCMSG_S05_TC07_RopOpenMessageAsBestAccess() { this.CheckMapiHttpIsSupported(); this.ConnectToServer(ConnectionType.PrivateMailboxServer); #region Call RopLogon to logon the private mailbox with administrator. RopLogonResponse logonResponse = this.Logon(LogonType.Mailbox, out this.insideObjHandle); #endregion List<PropertyObj> propertyValues = new List<PropertyObj> { new PropertyObj(PropertyNames.PidTagNormalizedSubject, Common.GetBytesFromUnicodeString(TestDataOfPidTagNormalizedSubject)) }; string commonUser = Common.GetConfigurationPropertyValue("CommonUser", Site); string commonUserPassword = Common.GetConfigurationPropertyValue("CommonUserPassword", Site); string commonUserEssdn = Common.GetConfigurationPropertyValue("CommonUserEssdn", Site); uint pidTagMemberRights; RopSetPropertiesResponse rpmSetResponse; #region Call RopOpenFolder to open the inbox folder. ulong parentFolderId = logonResponse.FolderIds[4]; uint openedInboxFolderHandle = this.OpenSpecificFolder(parentFolderId, this.insideObjHandle); #endregion #region Call RopCreateFolder to create a subfolder in inbox folder. ulong firstSubfolderId; uint firstSubFolderHandle = this.CreateSubFolder(openedInboxFolderHandle, out firstSubfolderId); LongTermId firstSubfolderLongTermID = this.GetLongTermIdFormID(firstSubfolderId, this.insideObjHandle); #endregion #region Call RopCreateMessage and RopSaveChangesMessage to create a Message object in subfolder created by step 3. // Create a message in InBox this.MessageHandle = this.CreatedMessage(firstSubfolderId, this.insideObjHandle); RopSaveChangesMessageResponse saveChangesMessageResponse = this.SaveMessage(this.MessageHandle, (byte)SaveFlags.KeepOpenReadWrite); ulong firstMessageId = saveChangesMessageResponse.MessageId; LongTermId firstMessageLongTermID = this.GetLongTermIdFormID(firstMessageId, this.insideObjHandle); this.ReleaseRop(this.MessageHandle); #endregion #region Call RopCreateFolder to create a new subfolder. ulong secondSubfolderId; System.Threading.Thread.Sleep(1); // Sleep 1 millisecond to generate different named folder uint secondSubFolderHandle = this.CreateSubFolder(openedInboxFolderHandle, out secondSubfolderId); LongTermId secondSubfolderLongTermID = this.GetLongTermIdFormID(secondSubfolderId, this.insideObjHandle); #endregion #region Call RopCreateMessage and RopSaveChangesMessage to create a Message object in subfolder created by step 5. // Create a message in InBox this.MessageHandle = this.CreatedMessage(secondSubfolderId, this.insideObjHandle); saveChangesMessageResponse = this.SaveMessage(this.MessageHandle, (byte)SaveFlags.KeepOpenReadWrite); ulong secondMessageId = saveChangesMessageResponse.MessageId; LongTermId secondMessageLongTermID = this.GetLongTermIdFormID(secondMessageId, this.insideObjHandle); this.ReleaseRop(this.MessageHandle); #endregion #region Add Read permission to "CommonUser" on inbox folder. // Add folder visible permission for the inbox. pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible | (uint)PidTagMemberRights.ReadAny; this.AddPermission(commonUserEssdn, pidTagMemberRights, openedInboxFolderHandle); #endregion #region Add Read permission to "CommonUser" on subfolder created by step 3. // Add folder visible permission for the subfolder1. pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible | (uint)PidTagMemberRights.ReadAny; this.AddPermission(commonUserEssdn, pidTagMemberRights, firstSubFolderHandle); #endregion #region Add Read and write permission to "CommonUser" on subfolder by step 5 pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible | (uint)PidTagMemberRights.ReadAny | (uint)PidTagMemberRights.EditAny; this.AddPermission(commonUserEssdn, pidTagMemberRights, secondSubFolderHandle); #endregion #region Call RopLogon to logon the private mailbox with "CommonUser" this.rawData = null; this.insideObjHandle = 0; this.response = null; this.ResponseSOHs = null; this.MSOXCMSGAdapter.RpcDisconnect(); this.MSOXCMSGAdapter.Reset(); this.MSOXCMSGAdapter.RpcConnect(ConnectionType.PrivateMailboxServer, commonUser, commonUserPassword, commonUserEssdn); string userDN = Common.GetConfigurationPropertyValue("AdminUserEssdn", this.Site) + "\0"; RopLogonRequest logonRequest = new RopLogonRequest() { RopId = (byte)RopId.RopLogon, LogonId = CommonLogonId, OutputHandleIndex = 0x00, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the output Server Object is stored. StoreState = 0, LogonFlags = 0x01, // Logon to a private mailbox OpenFlags = (uint)OpenFlags.UsePerMDBReplipMapping, // Requesting admin access to the mail box EssdnSize = (ushort)Encoding.ASCII.GetByteCount(userDN), Essdn = Encoding.ASCII.GetBytes(userDN), }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(logonRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); logonResponse = (RopLogonResponse)this.response; Site.Assert.AreEqual<uint>(TestSuiteBase.Success, logonResponse.ReturnValue, "Call RopLogon should success."); uint objHandle = this.ResponseSOHs[0][logonResponse.OutputHandleIndex]; #endregion #region Call RopOpenMessage which OpenModeFlags is BestAccess to open the message in subfolder created by step 3. firstSubfolderId = this.GetObjectIdFormLongTermID(firstSubfolderLongTermID, objHandle); firstMessageId = this.GetObjectIdFormLongTermID(firstMessageLongTermID, objHandle); uint openedMessageBestReadOnlyHandle = this.OpenSpecificMessage(firstSubfolderId, firstMessageId, objHandle, MessageOpenModeFlags.BestAccess); #endregion #region Call RopSetProperties to set PidTagNormalizedSubject property of message in subfolder created by step 3. List<TaggedPropertyValue> taggedPropertyValueList = new List<TaggedPropertyValue>(); int valueSize = 0; foreach (PropertyObj propertyObj in propertyValues) { PropertyTag propertyTag = new PropertyTag { PropertyId = (ushort)propertyObj.PropertyID, PropertyType = (ushort)propertyObj.ValueTypeCode }; TaggedPropertyValue taggedPropertyValue = new TaggedPropertyValue { PropertyTag = propertyTag, Value = (byte[])propertyObj.Value }; valueSize += taggedPropertyValue.Size(); taggedPropertyValueList.Add(taggedPropertyValue); } RopSetPropertiesRequest rpmSetRequest = new RopSetPropertiesRequest() { RopId = (byte)RopId.RopSetProperties, LogonId = CommonLogonId, InputHandleIndex = CommonInputHandleIndex, PropertyValueCount = (ushort)taggedPropertyValueList.Count, PropertyValueSize = (ushort)(valueSize + 2), PropertyValues = taggedPropertyValueList.ToArray(), }; uint returnValue; this.response = null; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(rpmSetRequest, openedMessageBestReadOnlyHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None, out returnValue); if(Common.IsRequirementEnabled(3009,this.Site)) { rpmSetResponse = (RopSetPropertiesResponse)this.response; // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R3009"); // Verify MS-OXCMSG requirement: MS-OXCMSG_R3009 this.Site.CaptureRequirementIfAreEqual<uint>( TestSuiteBase.Success, rpmSetResponse.ReturnValue, 3009, @"[In Appendix A: Product Behavior] BestAccess is read/write if the user don't have write permissions. (<12> Section 2.2.3.1.1: Exchange 2010 and above follow this behavior.)"); } if(Common.IsRequirementEnabled(3010,this.Site)) { if (this.response == null) { Site.Assert.AreNotEqual<uint>(0, returnValue, "Call RopSetProperties should fail."); } else { rpmSetResponse = (RopSetPropertiesResponse)this.response; Site.Assert.AreNotEqual<uint>(0, rpmSetResponse.ReturnValue, "Call RopSetProperties should fail."); } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R3010"); // Verify MS-OXCMSG requirement: MS-OXCMSG_R661 // Because when call RopSetProperties to set property of specified Message object that opened by read-only, server will fail and return error code. // R661 will be verified. this.Site.CaptureRequirement( 3010, @"[In Appendix A: Product Behavior] BestAccess is read-only if the user don't have write permissions. (Exchange 2007 follows this behavior.)"); } #endregion #region Call RopRelease to release created message in subfolder created by step 3. this.ReleaseRop(openedMessageBestReadOnlyHandle); #endregion #region Call RopOpenMessage which OpenModeFlags is BestAccess to open the message in subfolder created by step 5. secondSubfolderId = this.GetObjectIdFormLongTermID(secondSubfolderLongTermID, objHandle); secondMessageId = this.GetObjectIdFormLongTermID(secondMessageLongTermID, objHandle); uint openedMessageBestReadWrietHandle = this.OpenSpecificMessage(secondSubfolderId, secondMessageId, objHandle, MessageOpenModeFlags.BestAccess); #endregion #region Call RopSetProperties to set PidTagSubjectPrefix property of message in subfolder created by step 5. this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(rpmSetRequest, openedMessageBestReadWrietHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); rpmSetResponse = (RopSetPropertiesResponse)this.response; // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R665"); // Verify MS-OXCMSG requirement: MS-OXCMSG_R665 this.Site.CaptureRequirementIfAreEqual<uint>( TestSuiteBase.Success, rpmSetResponse.ReturnValue, 665, @"[In RopOpenMessage ROP Request Buffer] [OpenModeFlags] [BestAccess (0x03)] Open for read/write if the user has write permissions for the folder."); #endregion #region Call RopRelease to release created message in subfolder created by step 5. this.ReleaseRop(openedMessageBestReadWrietHandle); #endregion #region Call RopLogon to logon the private mailbox with administrator this.rawData = null; this.insideObjHandle = 0; this.response = null; this.ResponseSOHs = null; this.MSOXCMSGAdapter.RpcDisconnect(); this.MSOXCMSGAdapter.Reset(); this.ConnectToServer(ConnectionType.PrivateMailboxServer); logonResponse = this.Logon(LogonType.Mailbox, out this.insideObjHandle); openedInboxFolderHandle = this.OpenSpecificFolder(logonResponse.FolderIds[4], this.insideObjHandle); #endregion #region Call RopDeleteFolder to delete the subfolder created by 3. firstSubfolderId = this.GetObjectIdFormLongTermID(firstSubfolderLongTermID, this.insideObjHandle); RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest() { RopId = (byte)RopId.RopDeleteFolder, LogonId = CommonLogonId, InputHandleIndex = CommonInputHandleIndex, DeleteFolderFlags = (byte)DeleteFolderFlags.DeleteHardDelete | (byte)DeleteFolderFlags.DelMessages, FolderId = firstSubfolderId }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(deleteFolderRequest, openedInboxFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); RopDeleteFolderResponse deleteFolderresponse = (RopDeleteFolderResponse)this.response; Site.Assert.AreEqual<uint>(TestSuiteBase.Success, deleteFolderresponse.ReturnValue, "Call RopDeleteFolder should success."); #endregion #region Call RopDeleteFolder to delete the subfolder created by 5 secondSubfolderId = this.GetObjectIdFormLongTermID(secondSubfolderLongTermID, this.insideObjHandle); deleteFolderRequest.FolderId = secondSubfolderId; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(deleteFolderRequest, openedInboxFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); deleteFolderresponse = (RopDeleteFolderResponse)this.response; Site.Assert.AreEqual<uint>(TestSuiteBase.Success, deleteFolderresponse.ReturnValue, "Call RopDeleteFolder should success."); #endregion this.ReleaseRop(openedInboxFolderHandle); }
/// <summary> /// Call RopLogon to establish a logon session between the client and the server. /// </summary> /// <param name="logonType">LogonType value</param> /// <param name="objHandle">Unsigned integer value</param> /// <returns>Return RopLogonResponse</returns> protected RopLogonResponse Logon(LogonType logonType, out uint objHandle) { RopLogonRequest logonRequest = new RopLogonRequest() { RopId = (byte)RopId.RopLogon, // RopId 0XFE indicates RopLogon LogonId = CommonLogonId, // The logonId 0x00 is associated with this operation. OutputHandleIndex = 0x00 // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the output Server Object is stored. }; string userDN = Common.GetConfigurationPropertyValue("AdminUserEssdn", this.Site) + "\0"; logonRequest.StoreState = 0; if (LogonType.PublicFolder == logonType) { logonRequest.LogonFlags = 0x00; // Logon to public folders logonRequest.OpenFlags = 0x01000002; logonRequest.EssdnSize = 0; logonRequest.Essdn = null; } else { logonRequest.LogonFlags = 0x01; // Logon to a private mailbox logonRequest.OpenFlags = 0x01000000; logonRequest.EssdnSize = (ushort)Encoding.ASCII.GetByteCount(userDN); logonRequest.Essdn = Encoding.ASCII.GetBytes(userDN); } this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(logonRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); RopLogonResponse logonResponse = (RopLogonResponse)this.response; Site.Assert.AreEqual<uint>(TestSuiteBase.Success, logonResponse.ReturnValue, "Call RopLogon should success."); objHandle = this.ResponseSOHs[0][logonResponse.OutputHandleIndex]; return logonResponse; }