Share via


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.

Exchange Mailbox Store Permissions

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

image

Using the script you can list the permissions in this format

image

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