Click here to Skip to main content
Click here to Skip to main content

Setting Exchange Folder Permissions Remotely

, 3 Feb 2005
Rate this:
Please Sign up or sign in to vote.
A way to remotely set permissions on folders in the Exchange Server using an Exchange SDK-based COM in-proc wrapped into a .NET class and exposed to a client with Remoting technique.

Introduction

This article is addresses a specific problem related to security of Microsoft Exchange Server: the ability to programmatically set permissions on folders in the Exchange information store.

To perform such an operation manually, Exchange Server administrator may use Exchange System Management (ESM) utility, which is a part of Exchange Server installation:

  1. Create public folders aaa and bbb with ESM, and create users with mailbox userAAA and userBBB in the Active Directory.
  2. Then in ESM, open aaa Properties dialog by selecting Folder Properties item in the right-click menu on public folder aaa.
  3. Activate Client Permissions dialog (depicted in figure below) by pressing the appropriate button.
  4. Using Add..., Remove... and Properties... buttons, modify roles and permissions given to users userAAA and userBBB on folder aaa (see figure below).

Client Permissions

Background

I faced this problem (among many others) while developing a component for managing Active Directory and Exchange Server. Starting to deal with the problem, I thought that all I needed was to take a huge and generally well written book [1] by Thomas Rizzo and just find some ready-made solution there. Unfortunately, it was not the case. First, I found in the book the following information:

How you created the format for your security descriptor will depend on whether you are working in a MAPI public folder top-level hierarchy (TLH) or a non-MAPI TLH. A MAPI TLH requires that you create your security descriptor using the MAPI canonical format. This is what clients, such as Outlook, expect to see: the importance of this requirement cannot be overemphasized. If you create your security descriptor using the Windows canonical format, you will break Outlook! It is also possible to lock yourself out from being able to modify existing items or folders. Therefore, you must be very careful when you work with security descriptors. I highly recommend that you just take advantage of the Security Module that ships with the Exchange SDK. It understands how to correctly create both MAPI and Windows canonical formats and includes code to make sure you don't do any harm when working with security descriptors. (Page 890).

Naturally, after such a strong warning and recommendation, I found information about the Exchange SDK Security Module. In the same chapter, I read the following.

The Exchange SDK Application Security Module

Many developers requested the ability to set and get permissions on items and folders in the Exchange information store. Security can be complex and hard to understand, so the Application Security Module included with the SDK is especially valuable. The module is installed when you install the Exchange SDK. You can find it in the SDK directory under the Samples/Security folder. The module includes a set of JavaScript and ASP pages allowing you to access and modify the XML security descriptor in both Exchange and SPS 2001.

followed by:

You need to know some caveats about the security module, however. First, it cannot change permissions on inherited ACEs. This means that if a user's permissions are inherited from the parent folder, you cannot modify these permissions. Second, the module is written in JavaScript …

And then, of course:

If these shortcomings don't affect you, the security module makes the task of working with security easy.

(Pages 901-903).

Generally, it was recommended to run JavaScript on the Exchange machine using ASP for remote control. The problem was that “these shortcomings” did affect me. It apparently was not acceptable for the UI-less component I developed. Besides that, I might be needed to change permissions inherited from the parent folder. In short, I started to look for a more appropriate solution.

Brief Solution Description

Pretty soon, I found a Microsoft sample [2] that seemed to answer my problem. It actually did the job. The only thing left was to operate it remotely on behalf of an account with MAPI profile [3, 4] for Exchange. I chose .NET Remoting technique (unlike IIS WebService, Remoting allows us to run software on behalf of a particular account easily). I wrapped up the sample code in COM in-proc server and put it to my .NET object exported with Remoting. First, I tried to use Multi-Threaded Apartment (MTA) COM wrapper changing MAPI initialization according to [5, 6] recommendation. But apparently, Exchange SDK does not support MTA access: HrOpenExchangePublicStore() method failed with “Unknown Exception” return code. So, the COM STA containing Microsoft sample [2] code exported with Remoting technique seemed the only choice.

Using the Code

The sample solution consists of the following projects:

ClientPermissionHelper. COM STA component wrapped up in Exchange SDK sample [2]; implements IPermission interface containing Add(), Modify() and Remove() methods to deal with permissions. For the sake of simplicity (and because performance is not the main concern for this sample), the component is designed stateless. It implies that each of the interface methods initializes MAPI, creates a MAPI session, does the job, and then releases session and un-initializes the MAPI connection. For the real world applications, a more sophisticated design may be adopted. ClientPermissionHelper uses MAPI profile for Exchange, named "MS Exchange Settings" (name is hardcoded in the sample). The component uses Exchange SDK header files and static libraries that make it difficult to build it in VS .NET. To cope with this, the relevant header files are placed in the Include folder under the project main folder, and static libraries are paced in Lib folder, with appropriate changes in the project settings (thanks to Yuval Nahon who patiently solved the problem).

ClientPermission. .NET wrapper for ClientPermissionHelper using COM Interop; exported with Remoting technique and, as such derived from MarshalByRefObject class. The component implements IClientPermission interface which is defined in SvrInterface and consumed by Remoting client. Only one instance of COM object may be used since COM Interop automatically marshals calls from different threads of Remoting built-in thread pool to STA COM thread (of course, at the expense of some performance penalty).

SrvInterface. Defines IClientPermission interface and Permissions enumerator used by both Remoting server and client.

SrvHost. Hosts ClientPermission component and provides its export. It may run on Exchange machine either as a normal application (with /console parameter in command line) or as a Windows service. In both cases, SrvHost should run under the account which has a valid MAPI profile for Exchange (named "MS Exchange Settings"). The component registers an HTTP channel with port number hard-coded for simplicity. In case of Windows service, SrvHost is registered under the name ESClientPermissionServer as shown in the figure below:

Services

Client. Manages Exchange permissions by calling methods of IClientPermission interface implemented in ClientPermission component.

InstExchProfile. Utility for creation of MAPI Exchange profile (as shown e.g., in [4]) named "MS Exchange Settings".

ClientPermissionHelper, ClientPermission, SrvHost and InstExchProfile have to be placed on the Exchange machine, Client has to be placed on the client machine, and SrvInterface on both.

In order to prepare a sample to run, the following steps should be performed:

  1. Build solution (make sure that ClientPermission project contains reference on ClientPermissionHelper COM Interop).
  2. Place ClientPermissionHelper.dll, ClientPermission.dll, SrvInterface.dll, SrvHost.exe and InstExchProfile.exe on Exchange machine, and Client.exe and SrvInterface.dll on client machine.
  3. Register COM ClientPermissionHelper.dll on server machine if it was not done during build. It may be done with either RegSvr32 utility or using ClientPermissionHelper.bat file from SrvHost\bin\Release or SrvHost\bin\Debug.
  4. Set up "MS Exchange Settings" Exchange profile on Exchange machine with InstExchProfile utility.
  5. If you are planning to run SrvHost.exe as Windows service, then it has to be installed as a service either with InstallUtil utility or using the file InstallService.bat under account with "MS Exchange Settings" Exchange profile on Exchange machine.
  6. Create manually public folder aaa and bbb on Exchange, and users userAAA and userBBB with mail boxes in Active Directory. In order to check that this is done correctly, try to add/modify/remove some permission on aaa and bbb for userAAA and userBBB manually.

To run the sample:

  1. Start SrvHost.exe either as a service or as an EXE application (with key /console or using file SrvHost.bat). If server is running as normal application, then it outputs log information to debug view. Thus DbgView utility may be useful.
  2. Run Client.exe on client machine.

    As a result, permission on aaa and bbb for userAAA and userBBB should be changed appropriately.

Discussion

The above described approach actually solves the problem. But it would be also interesting to try to use ACE [7] and ACLObject [8] COM co-classes implemented in ACE.dll first shipped with Microsoft Exchange 5.5. Several publications (e.g., [9, 10 and 11] to mention just a few) describe various operations with Exchange folder permissions locally on Exchange machine. It might be probably possible to use these components from ClientPermission with COM Interop instead of ClientPermissionHelper.

Conclusion

This article describes a way to remotely modify permissions on folders in the Exchange Server information store. To attain this, a special Exchange SDK-based COM in-proc server that actually does the job is designed. It is wrapped into a .NET class exposed to a client with Remoting technique.

References

  • [1] Programming Microsoft Outlook and Microsoft Exchange 2003, Third Edition / Thomas Rizzo. (1074 pages).
  • [2] How To Modify Exchange Folder Permissions Using IExchangeModifyTable (297493).
  • [3] Demystifying Exchange 2003 Custom Recipients, DLs, and Profiles.
  • [4] Configure MAPI profile parameter.
  • [5] FIX: MAPIInitialize() Fails with MAPI_E_INVALID_FLAGS (179116).
  • [6] MAPI_NO_COINIT Flag To Make MAPIInitialize Not Call CoInit (239853).
  • [7] ACE CoClass.
  • [8] ACLObject CoClass.
  • [9] Minding the E-Mail by Bill Boswell, December 2003.
  • [10] How To Add A Delegate To An Exchange Folder with the ACL Component and CDO (1.21) (295558).
  • [11] PRB: ACL: Outlook 2000 Doesn't Properly Read ACL Settings (237924)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Igor Ladnik
Architect
Israel Israel


  • Nov 2010: Code Project Contests - Windows Azure Apps - Winner
  • Feb 2011: Code Project Contests - Windows Azure Apps - Grand Prize Winner

Follow on   LinkedIn

Comments and Discussions

 
GeneralFolder Visibility Permission PinmemberMember 33376312-Oct-08 23:44 
GeneralError running Client Pinmembersandeepspec6-May-05 14:29 
Hi
 
Thanks for providing the application i'm looking for, but when i run the client I get "The application failed to initialize properly 0xc0001035. ..."
 
I guees, i need to install framework on the client machine? Also, do i need anything else.. Any comments???
GeneralRe: Error running Client PinmemberIgor Ladnik7-May-05 20:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141216.1 | Last Updated 4 Feb 2005
Article Copyright 2005 by Igor Ladnik
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid