Manage mailbox security with this CDOEXM enhancement
Exchange 2000 Server provides an extension to the Active Directory Service Interfaces (ADSI) called Collaboration Data Objects for Exchange Management (CDOEXM). The aim of this extension is to ease the management of some Exchange 2000 components from ADSI. (The Microsoft TechNet white paper "Automating Exchange 2000 Management with Windows Script Host" at http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechnol/exchange/exchange2000/maintain/featusability/ex2kwsh.asp?frame=true covers this technology in depth.)
In Exchange 2000 Service Pack 2 (SP2), Microsoft made a small but extremely useful CDOEXM enhancement that can help you manage mailbox security. You can use this new CDOEXM feature from Windows Script Host (WSH).
What Is CDOEXM?
CDOEXM provides objects and interfaces for the management of many Exchange 2000 components. For example, you can use CDOEXM to configure Exchange servers and public and mailbox stores, mount and dismount stores, and create and configure mailboxes. More than simply an extension of ADSI, CDOEXM is also an extension of CDO for Exchange 2000 (CDOEX). At the server level, CDOEXM retrieves specific information about the server (e.g., the message-tracking state, server version), as well as the storage groups (SGs) present on the server and stores present in the SGs. From the perspective of a user object, CDOEXM exposes properties and methods to manage the Exchange 2000 mailbox (e.g., garbage-collection information, quota settings, mailbox creation and deletion information). To avoid confusion between CDOEXM and CDOEX, remember that CDOEXM exposes information and management features related to the containers of the mail server components (i.e., server, SGs, mailboxes), whereas CDOEX exposes information and management features related to the elements constituting the mail information (i.e., messages).
Unfortunately, despite CDOEXM's importance as a companion to ADSI and CDOEX in working with Exchange 2000, managing an Exchange 2000 mailbox's security remains a challenge. To get a handle on mailbox security, you need an understanding of the Security Descriptor (SD) structure. (For more information about the SD structure, see the Microsoft Developer Network—MSDN—SECURITY_DESCRIPTOR page at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/security_descriptor.asp.) Then, to understand the real benefits of this CDOEXM enhancement, you need to consider the situation before and after an Exchange 2000 SP2 installation.
Pre-Exchange 2000 SP2
With the initial release of Exchange 2000 and even with the release of SP1, the use of ADSI and CDOEXM to manage the mailbox SD was limited. The reason is that Active Directory (AD) stores all the information required to create an Exchange 2000 mailbox, whereas the Store keeps the "physical" mailbox and its security-access data. I provide details about this implementation later in the article. By initializing a specific set of attributes associated with a user object, you can feasibly use ADSI to create a mailbox—although Microsoft doesn't officially support this method. The supported Microsoft solution is to use the CDOEXM extension to create the mailbox. Essentially, CDOEXM uses a COM method to abstract the set of attributes required to initialize the mailbox. This functionality guarantees reliable code even if Microsoft were to change the underlying logic of mailbox creation—which is the reason Microsoft doesn't officially support the ADSI technique. Think of the ADSI technique as a raw mailbox-creation process and the CDOEXM technique as a process that abstracts the mailbox-creation logic. For more information about how to use both ADSI and CDOEXM to create an Exchange 2000 mailbox, refer to the TechNet white paper that I referenced earlier.
Despite its abstraction layer, the original CDOEXM version doesn't expose any attributes or methods to update mailbox security. Instead, CDOEXM configures the mailbox with default security, which is far from what most administrators require. One solution is to use ADSI and access the msExchMailboxSecurityDescriptor attribute to initialize the Exchange 2000 mailbox SD as necessary. However, this technique works well only for new mailboxes—not existing mailboxes. When you create an Exchange 2000 mailbox, the system stores the information required to define the mailbox in AD. The actual mailbox—the one in the Exchange 2000 Store—isn't created immediately. The "physical" mailbox is created only when the user connects to the new mailbox (through any client) or when a message is delivered to this mailbox. At that moment, the mailbox is created in the Store, and the mailbox security data in the Store is synchronized with the security settings stored in the AD msExchMailboxSecurityDescriptor attribute.
The AD msExchMailboxSecurityDescriptor attribute becomes a mirror copy of the SD in the Store. Thus, you can't use ADSI to modify mailbox security because ADSI doesn't provide access to the SD in the Store. Any change you make to AD's copy of the msExchMailboxSecurityDescriptor attribute won't be reflected in the Store. Therefore, this solution works only for new mailboxes before they're "physically" created in the Store.
The AD msExchMailboxSecurityDescriptor attribute has two purposes. First, the attribute is a placeholder that stores security information that will be written to the mailbox SD in the Store at the moment of "physical" mailbox creation. Second, as the attribute is replicated in the Exchange organization, the mailbox's permissions become accessible to all Exchange servers connected to different Global Catalog (GC) servers. For example, the evaluation of the Send As permission requires that mailbox permissions be accessible by all Exchange servers.
Listing 1 shows the GetSDViaADSI.wsf script, which uses ADSI to read the Exchange 2000 SD for the specified user's mailbox. Accessing the SD in AD is a straightforward process. The script binds to the user object and makes a request for the msExchMailboxSecurityDescriptor attribute value. Next, to decipher the SD, the script invokes the DecipherSecurityDescriptor function, as the code at callout A in Listing 1 shows.
Web Listing 1 (http://www.exchangeadmin.com, InstantDoc ID 38190) shows DecipherSDFunction.vbs. To decipher the ADSI SD representation, the DecipherSecurityDescriptor function uses three ADSI objects:
- IADsSecurityDescriptor—This object contains the SD components—ACLs and access control entries (ACEs)—and exposes some SD properties.
- IADsAccessControlList—This object contains the list of ACLs, which can be the effective rights or the auditing settings. From the ACLs, you can enumerate the ACEs.
- ;IADsAccessControlEntry—This object, the smallest component of an ADSI SD representation, contains an effective right for a granted entity or an auditing setting.
The DecipherSecurityDescriptor function invokes a helper function called DisplayFormattedProperty, which Web Listing 2 shows. The DisplayFormattedProperty function formats and displays the deciphered SD information. Figure 1 shows partial output from the execution of GetSDViaADSI.wsf. You can see how the SD reads from AD and sets the Exchange 2000 user mailbox.
Finally, you need to use the bitmask operations that Web Table 1 and Web Table 2 (http://www.exchangeadmin.com, InstantDoc ID 38190) show to translate the hexadecimal SD property values. For example, an AccessMask value of &h30003 translates into the following AccessMask flags:
An AceFlags value of &h2 implies the use of the CONTAINER_INHERIT_ACE flag, and an AceType value of &h0 implies the use of the ADS_ACETYPE_ACCESS_ALLOWED flag. For a glimpse into how I'm performing these operations, see "Boolean Arithmetic with Hexadecimal Values," June 1999, http://www.winscriptingsolutions.com, InstantDoc ID 5457.
PostExchange 2000 SP2
With Exchange 2000 SP2, you can update the mailbox SD in the Exchange Store by using a new property called MailboxRights, which the IExchangeMailbox CDOEXM interface exposes. CDOEXM acts as an ADSI extension, so the MailboxRights property is associated with the ADSI IADsUser interface. Listing 2, page 3, shows GetSDViaCDOEXM .wsf, which uses CDOEXM to retrieve the Exchange 2000 SD.
Like GetSDViaADSI.wsf, GetSDViaCDOEXM.wsf starts with an ADSI bind operation to the user object. However, instead of getting the msExchMailboxSecurityDescriptor attribute value, the script gets the SD value from the MailboxRights property, as the code at callout A in Listing 2 shows. Interestingly, the SD format is still an ADSI SD. So, the script can use the same DecipherSecurityDescriptor function that GetSDViaADSI.wsf uses to display the SD values.
Unlike the ADSI technique, the CDOEXM technique updates the SD in the Store. Although updating an SD is a good idea for many reasons, a compelling reason is that doing so permits the automatic creation and updating of Exchange 2000 mailbox security. Without this automated feature, a mailbox security update is almost impossible to perform through scripts. This new feature is especially useful in multiforest environments because of the involvement of external accounts. Briefly, in a multiforest environment, the mailbox is hosted by a disabled mailbox-enabled user account in a dedicated Exchange forest called a resource forest. The real user account—the one that the user uses to log on—is in another forest, called an account forest. To grant access to the user account in the account forest on the mailbox located in the resource forest, you must add the real account as an external user account, which is simply a specific right of the Exchange mailbox. (This process assumes that you've properly established the required trusts between the forests.)
Listing 3 shows SetSDViaCDOEXM.wsf, which uses CDOEXM to update the Exchange 2000 SD. In particular, this script shows you how to add an ACE for an external account to the mailbox. This code snippet is the SD update typically used for a multiforest context. Like Listing 2, Listing 3 starts by binding to the user object and reading the SD value. Next, as in the DecipherSecurityDescriptor function, the script extracts the discretionary ACL (DACL) from the SD. Then, the script creates a new ACE to add a new setting to the extracted DACL. To add an external account to the mailbox, the script sets the various ACE properties to different values, as defined in SecurityInclude.vbs, which Web Listing 3 shows. The code at callout A in Listing 3 calls SecurityInclude.vbs into action. After initializing the new ACE, the script updates the DACL to update the SD, as the code at callout B in Listing 3 shows.
The final operation consists of transferring the updated SD back to the Store, as the code at callout C in Listing 3 shows. Note that the script passes the SD back to the MailboxRights property as an array. (This property actually requires a pointer to the ADSI SD object and not the ADSI security descriptor object itself.)
If, by any chance, the script refers to an invalid trustee, CDOEXM will return the message that Figure 2 shows when updating the SD in the Store. An aspect that Listing 3 doesn't consider is ACE ordering, which is particularly sensitive when you deny permissions on objects. ACE ordering is important in avoiding security breaches. For more information about ACE ordering, see the Microsoft article "HOWTO: Use Visual Basic and ADsSecurity.dll to Properly Order ACEs in an ACL" (http://support.microsoft.com/?kbid=269159). After the update is complete, you should see the settings that Figure 3 shows in the Microsoft Management Console (MMC) Active Directory Users and Computers snap-in.
Like any service pack, Exchange 2000 SP2 offers a set of corrections and new features. The new CDOEXM feature eliminates the pain of using scripts to manage Exchange 2000 mailbox security. This small enhancement hides a much more important goal: manageability of Exchange 2000 mailboxes in a multiforest architecture. Because the standard UIs aren't designed for the management of multiforest architectures, such a design requires that you develop extra code to simplify multiforest management.