HOWTO: Programmatically enumerate permissions on Exchange 2003 Mailbox Store
This was a tough one and was lots of learning for me as well. Me and my colleague was working on a customer issue where his intentions were to list all the permissions on Exchange 2003 Mailbox Store. Of course one can go to Exchange System Manager (ESM), but considering an environment with 20+ Exchange server and over 100 Mailbox stores it could be a tedious task to satisfy the Auditing Team.
There are tools that can give you that information to some extend like, PFDavAdmin and DSACLS but the information provided with those tools are not good enough when it comes to auditing the permissions.
I have come up with a sample script which uses CDOEXM to list down all the Mailbox Stores. CDOEXM is no good in giving you permissions on the store but you can get the distinguishedName for the store where actually the permissions are stored in AD
The distinguishedName would be something similar to this
CN=Mailbox Store (R2-A),CN=First Storage Group,CN=InformationStore,CN=R2-A,CN=Servers,CN=First Administrative Group,CN=Administrative Groups,CN=Contoso Exchange Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=contoso,DC=com
You can map these permissions under ADSIEdit here
Using the script you can list the permissions in this format
Please find the script below and make sure you know what you are doing.
This script should be run on an Exchange 2003 server since it uses CDOEXM. or atleast a machine where ESM is installed, do not copy-paste CDOEXM on another machine.
'===================================================================
' DISCLAIMER:
'-------------------------------------------------------------------
'
' This sample is provided as is and is not meant for use on a
' production environment. It is provided only for illustrative
' purposes. The end user must test and modify the sample to suit
' their target environment.
'
' Microsoft can make no representation concerning the content of
' this sample. Microsoft is providing this information only as a
' convenience to you. This is to inform you that Microsoft has not
' tested the sample and therefore cannot make any representations
' regarding the quality, safety, or suitability of any code or
' information found here.
'
'===================================================================
'
' Define some constants:
'
'
' Define a ADS_RIGHTS_ENUM constants constants:
'
Const ADS_RIGHT_DELETE = &H10000
Const ADS_RIGHT_READ_CONTROL = &H20000
Const ADS_RIGHT_WRITE_DAC = &H40000
Const ADS_RIGHT_WRITE_OWNER = &H80000
Const ADS_RIGHT_SYNCHRONIZE = &H100000
Const ADS_RIGHT_ACCESS_SYSTEM_SECURITY = &H1000000
Const ADS_RIGHT_GENERIC_READ = &H80000000
Const ADS_RIGHT_GENERIC_WRITE = &H40000000
Const ADS_RIGHT_GENERIC_EXECUTE = &H20000000
Const ADS_RIGHT_GENERIC_ALL = &H10000000
Const ADS_RIGHT_DS_CREATE_CHILD = &H1
Const ADS_RIGHT_DS_DELETE_CHILD = &H2
Const ADS_RIGHT_ACTRL_DS_LIST = &H4
Const ADS_RIGHT_DS_SELF = &H8
Const ADS_RIGHT_DS_READ_PROP = &H10
Const ADS_RIGHT_DS_WRITE_PROP = &H20
Const ADS_RIGHT_DS_DELETE_TREE = &H40
Const ADS_RIGHT_DS_LIST_OBJECT = &H80
Const ADS_RIGHT_DS_CONTROL_ACCESS = &H100
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'
' Ace Type definitions
'
Const ADS_ACETYPE_ACCESS_ALLOWED = 0
Const ADS_ACETYPE_ACCESS_DENIED = &H1
Const ADS_ACETYPE_SYSTEM_AUDIT = &H2
Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &H5
Const ADS_ACETYPE_ACCESS_DENIED_OBJECT = &H6
Const ADS_ACETYPE_SYSTEM_AUDIT_OBJECT = &H7
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'
' Ace Flag Constants
'
Const ADS_ACEFLAG_UNKNOWN = &H1
Const ADS_ACEFLAG_INHERIT_ACE = &H2
Const ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE = &H4
Const ADS_ACEFLAG_INHERIT_ONLY_ACE = &H8
Const ADS_ACEFLAG_INHERITED_ACE = &H10
Const ADS_ACEFLAG_VALID_INHERIT_FLAGS = &H1F
Const ADS_ACEFLAG_SUCCESSFUL_ACCESS = &H40
Const ADS_ACEFLAG_FAILED_ACCESS = &H80
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Flags constants for AD objects
'
Const ADS_FLAG_OBJECT_TYPE_PRESENT = &H1
Const ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = &H2
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Sub EnumStores(strServer)
Dim objServer
Dim objSG
Dim objMSDB
Dim iDS
Dim storageGroup
Dim MBX
Set objServer = CreateObject("CDOEXM.ExchangeServer")
Set objSG = CreateObject("CDOEXM.StorageGroup")
Set objMSDB = CreateObject("CDOEXM.MailboxStoreDB")
Set iDS = objServer.GetInterface("IDataSource")
iDS.Open strServer
For Each storageGroup In objServer.StorageGroups
objSG.DataSource.Open storageGroup
For Each MBX In objSG.MailboxStoreDBs
objMSDB.DataSource.Open MBX
wscript.echo "Permissions on : " & MBX
ListPermissions objMSDB.Fields("adsPath").Value
Next
Next
End Sub
Sub ListPermissions(adspath)
Dim objSecurityDescriptor
Dim objDacl
Dim oAce
Dim objMailbox
'Get target User object
Set objMailbox = GetObject(adspath)
Set objSecurityDescriptor = objMailbox.ntsecuritydescriptor 'Get the security descriptors for mailbox rights
Set objDacl = objSecurityDescriptor.DiscretionaryAcl
For Each oAce In objDacl
If ((oAce.AceFlags And ADS_ACEFLAG_INHERITED_ACE) = ADS_ACEFLAG_INHERITED_ACE) Then
Select Case oAce.AceType
Case ADS_ACETYPE_ACCESS_ALLOWED
If oAce.AccessMask = oAce.AccessMask = ADS_RIGHT_DELETE Or _
ADS_RIGHT_READ_CONTROL Or ADS_RIGHT_WRITE_DAC Or ADS_RIGHT_WRITE_OWNER Or _
ADS_RIGHT_DS_CREATE_CHILD Or ADS_RIGHT_DS_DELETE_CHILD Or ADS_RIGHT_ACTRL_DS_LIST Or _
ADS_RIGHT_DS_SELF Or ADS_RIGHT_DS_READ_PROP Or ADS_RIGHT_DS_WRITE_PROP Or _
ADS_RIGHT_DS_DELETE_TREE Or ADS_RIGHT_DS_LIST_OBJECT Or ADS_RIGHT_DS_CONTROL_ACCESS Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Full Control => ACCESS_ALLOWED"
'
' We have a implicit Deny ACE
'
If oAce.ObjectType = "{AB721A56-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo " Receive As => ACCESS_ALLOwED"
End If
If oAce.ObjectType = "{AB721A54-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo " Send As => ACCESS_ALLOWED"
End If
End If
Case ADS_ACETYPE_ACCESS_DENIED
If oAce.AccessMask = oAce.AccessMask = ADS_RIGHT_DELETE Or _
ADS_RIGHT_READ_CONTROL Or ADS_RIGHT_WRITE_DAC Or ADS_RIGHT_WRITE_OWNER Or _
ADS_RIGHT_DS_CREATE_CHILD Or ADS_RIGHT_DS_DELETE_CHILD Or ADS_RIGHT_ACTRL_DS_LIST Or _
ADS_RIGHT_DS_SELF Or ADS_RIGHT_DS_READ_PROP Or ADS_RIGHT_DS_WRITE_PROP Or _
ADS_RIGHT_DS_DELETE_TREE Or ADS_RIGHT_DS_LIST_OBJECT Or ADS_RIGHT_DS_CONTROL_ACCESS Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Full Control => ACCESS_DENIED"
'
' We have a implicit Deny ACE
'
If oAce.ObjectType = "{AB721A56-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo " Receive As => ACCESS_DENIED"
End If
If oAce.ObjectType = "{AB721A54-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo " Send As => ACCESS_DENIED"
End If
End If
Case ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
'
' We have an object allowed ace
' Does it apply to a property? or an Object?
'
If oAce.ObjectType = "{AB721A56-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Receive As => ACCESS_ALLOWED_OBJECT"
End If
If oAce.ObjectType = "{AB721A54-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Send As => ACCESS_ALLOWED_OBJECT"
End If
Case ADS_ACETYPE_ACCESS_DENIED_OBJECT
'
' We have a object Deny ace
'
If oAce.ObjectType = "{AB721A56-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Receive As => ACCESS_DENIED_OBJECT"
End If
If oAce.ObjectType = "{AB721A54-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Send As => ACCESS_DENIED_OBJECT"
End If
Case Else
'
' Missed a bin?
'
End Select
Else
'
' We have an Implicit ACE, lets put it the proper pool
'
Select Case oAce.AceType
Case ADS_ACETYPE_ACCESS_ALLOWED
'
' We have an implicit allow ace
'
If oAce.ObjectType = "{AB721A56-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Receive As => ACCESS_ALLOWED"
End If
If oAce.ObjectType = "{AB721A54-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Send As => ACCESS_ALLOWED"
End If
Case ADS_ACETYPE_ACCESS_DENIED
'
' We have a implicit Deny ACE
'
If oAce.ObjectType = "{AB721A56-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Receive As => ACCESS_DENIED"
End If
If oAce.ObjectType = "{AB721A54-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Send As => ACCESS_DENIED"
End If
Case ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
'
' We have an object allowed ace
' Does it apply to a property? or an Object?
'
If oAce.ObjectType = "{AB721A56-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Receive As => ACCESS_ALLOWED_OBJECT"
End If
If oAce.ObjectType = "{AB721A54-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Send As => ACCESS_ALLOWED_OBJECT"
End If
Case ADS_ACETYPE_ACCESS_DENIED_OBJECT
'
' We have a object Deny ace
'
If oAce.ObjectType = "{AB721A56-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Receive As => ACCESS_DENIED_OBJECT"
End If
If oAce.ObjectType = "{AB721A54-1E2F-11D0-9819-00AA0040529B}" Then
wscript.echo "Trustee : " & oAce.Trustee
wscript.echo " Send As => ACCESS_DENIED_OBJECT"
End If
Case Else
'
' Missed a bin?
'
End Select
End If
Next
End Sub
EnumStores "Put Your Server Name Here"
Comments
Anonymous
November 13, 2008
Great Script. When I get time, I'll convert it to Powershell. I just recently had to create a PS script to enumerate Mbx and AD permissions per mailbox basis. Using this script, I can expand on the idea and report on the organization level objects.Anonymous
March 27, 2009
We can use ADSI VBScript sample given below to enumerate mailbox permission from the exchange server.Anonymous
December 09, 2010
I have a suggestion: output to a text file instead of echo since there's a lot of info that will displayed. Thank you.Anonymous
March 09, 2011
@SysAdmin... Sure you can output the text to anything you like. I kept it simple to dump it to console. You can redirect the output of console to file with following command c:> cscript perm_script.vbs > c:output.txt