Skip to main content

Reverse Permissions Audit Scripts Part 2

*****If your looking for a Exchange 2007/2010 solution have a look at this post http://gsexdev.blogspot.com/2008/04/exchange-permission-and-reverse.html *****

In April I posted this script that did a reverse lookup of mailbox permissions that had been assigned via Active Directory Users and Computers. This was to give a view by user of what mailbox’s a particular user had access to (instead of the normal view which is who has access to this mailbox). The second part of the permission story with exchange is the actually MAPI permissions that are set on each of the folders in a mailbox. When you delegate folders in outlook this will modify the rights of each of the folders that you delegate (eg calendar,contact,tasks). To view the Mapi permissions on a folder programmatically from a script there are a few methods that can be used the easiest way to do it is to use the Acl.dll from the platform SDK see KB240911 for details for more details. The basis of this article can be used to create a conventional script that will log the rights on each folder and save this to a CSV file. You can then open the CSV in Excel do a auto filter on the folder you want to audit and you very quick and useful report. I’ve included a conventional version of a script that does just this in the download for this post this script takes the name of the server you want to run it against as a command line parameter. Both these scripts require the acl.dll to be registered on the machine you are running the script on. Acl.dll can be found in the Platform SDK or downloaded as part of this CDOlive sample .

With the reverse MAPI permission script what I’ve done is to take the data shaping logic I used previously and applied it to all the root mailbox folders eg the root of the mailbox tree and the calendar,inbox,contacts,tasks,notes and sent item folders. So what the script will output is a per user view of what other Users’s mailbox folders each user has access to. So this script could be used to answer the question what calendars is fred-blogs able to see. To do this the script first looks up Active Directory for all users that have a mailbox in a domain and creates a parent record-set of these values. Then for every user it tries to establish a MAPI connection to there mailbox via CDO 1.2 and enumerates permissions on the root folders in the mailbox and writes these permissions to the child record-set. The recordset’s are then related on the Exchange LegacyDN and the address retrieved from CDO addressEntry object.

The script tries to connect to every mailbox in a domain and expects that the user running it will have full rights to every mailbox in the domain equiv to http://support.microsoft.com/?kbid=262054 . I’ve put a download copy of both scripts that I’ve talked about here. The code for the reverse permissions script looks like


on error resume next
set conn1 = createobject("ADODB.Connection")
strConnString = "Data Provider=NONE; Provider=MSDataShape"
conn1.Open strConnString
set conn = createobject("ADODB.Connection")
set com = createobject("ADODB.Command")
Set iAdRootDSE = GetObject("LDAP://RootDSE")
strNameingContext = iAdRootDSE.Get("defaultNamingContext")
Conn.Provider = "ADsDSOObject"
Conn.Open "ADs Provider"
Query = "<LDAP://" & strNameingContext & ">;(&(&(&(& (mailnickname=*)" & _
"(!msExchHideFromAddressLists=TRUE) (| (&(objectCategory=person)(objectClass=user)"
& _
"(|(homeMDB=*)(msExchHomeServerName=*))) )))))" & _
";samaccountname,legacyExchangeDN,msExchHomeServerName," &_
"displayname,distinguishedName;subtree"
Com.ActiveConnection = Conn
Com.CommandText = Query
Com.Properties("Page Size") = 1000
set objParentRS = createobject("adodb.recordset")
set objChildRS = createobject("adodb.recordset")
strSQL = "SHAPE APPEND" & _
" NEW adVarChar(255) AS UOADDisplayName, " & _
" NEW adVarChar(255) AS UOADTrusteeName, " & _
" NEW adVarChar(255) AS UOADLegacyDN, " & _
" ((SHAPE APPEND " & _
" NEW adVarChar(255) AS MRmbox, " & _
" NEW adVarChar(255) AS MRFolder, " & _
" NEW adVarChar(255) AS MRTrusteeName, " & _
" NEW adVarChar(255) AS MRRights) " & _
" RELATE UOADLegacyDN TO MRTrusteeName) AS rsUOMR"
objParentRS.LockType = 3
objParentRS.Open strSQL, conn1

Set Rs = Com.Execute
While Not Rs.EOF
objParentRS.addnew
objParentRS("UOADDisplayName") = rs.fields("displayname")
objParentRS("UOADTrusteeName") = rs.fields("samaccountname")
objParentRS("UOADLegacyDN") = rs.fields("legacyExchangeDN")
objParentRS.update
Set objChildRS = objParentRS("rsUOMR").Value
inplinearray = Split(rs.fields("msExchHomeServerName").value, "=", -1, 1)
CDOAddr =
getpermissions(inplinearray(ubound(inplinearray)),rs.fields("samaccountname").value,rs.fields("displayname").value)
rs.movenext
Wend
wscript.echo "Number of Mailboxes Checked " & objParentRS.recordcount
Wscript.echo

objParentRS.MoveFirst
Do While Not objParentRS.EOF
Set objChildRS = objParentRS("rsUOMR").Value
if objChildRS.recordcount <> 0 then wscript.echo objParentRS("UOADDisplayName")
Do While Not objChildRS.EOF
wscript.echo " " & objChildRS.fields("MRmbox") & _
" " & objChildRS.fields("MRFolder") & " " & objChildRS.fields("MRRights")
objChildRS.movenext
loop
objParentRS.MoveNext
loop

function getpermissions(servername,mailboxname,displayname)
wscript.echo "Processing " & mailboxname
Set objSession = CreateObject("MAPI.Session")
objSession.Logon "","",false,true,true,true,servername & vbLF & mailboxname
if err.number <> 0 then wscript.echo err.description
err.clear
set objCuser = objSession.CurrentUser
Set CdoInfoStore = objSession.GetInfoStore
Set CdoFolderRoot = CdoInfoStore.RootFolder
Set ACLObj = CreateObject("MSExchange.aclobject")
ACLObj.CDOItem = CdoFolderRoot
Set FolderACEs = ACLObj.ACEs
For each fldace in FolderACEs
if cstr(objCuser.address) <> cstr(GetACLEntryName(fldace.ID, objSession)) then
objChildRS.addnew
objChildRS("MRmbox") = mailboxname
objChildRS("MRFolder") = "Root"
objChildRS("MRTrusteeName") = GetACLEntryName(fldace.ID, objSession)
objChildRS("MRRights") = DispACERules(fldace)
objChildRS.update
end if
Next
Set CdoFolders = CdoFolderRoot.Folders
Set CdoFolder = CdoFolders.GetFirst
do while Not (CdoFolder Is Nothing)
ACLObj.CDOItem = CdoFolder
Set FolderACEs = ACLObj.ACEs
For each fldace in FolderACEs
if cstr(objCuser.address) <> cstr(GetACLEntryName(fldace.ID, objSession)) then

objChildRS.addnew
objChildRS("MRmbox") = mailboxname
objChildRS("MRFolder") = CdoFolder.Name
objChildRS("MRTrusteeName") = GetACLEntryName(fldace.ID, objSession)
objChildRS("MRRights") = DispACERules(fldace)
objChildRS.update
end if
Next
Set CdoFolder = CdoFolders.GetNext
loop
if Not objSession Is Nothing Then objSession.Logoff
set objSession = nothing
End function

Function GetACLEntryName(ACLEntryID,SubSession)

select case ACLEntryID
case "ID_ACL_DEFAULT"
GetACLEntryName = "Default"
case "ID_ACL_ANONYMOUS"
GetACLEntryName = "Anonymous"
case else
Set tmpEntry = SubSession.GetAddressEntry(ACLEntryID)
tmpName = tmpEntry.address
GetACLEntryName = tmpName
end select
Set objSession = nothing
Set CdoFolderRoot = nothing
Set ACLObj = nothing
Set FolderACEs = nothing
Set objSession = nothing

End Function

Function DispACERules(DisptmpACE)

Select Case DisptmpACE.Rights

Case ROLE_NONE, 0 ' Checking in case the role has not been set on that entry.
DispACERules = "None"
Case 1024 ' Check value since ROLE_NONE is incorrect
DispACERules = "None"
Case ROLE_AUTHOR
DispACERules = "Author"
Case 1051 ' Check value since ROLE_AUTHOR is incorrect
DispACERules = "Author"
Case ROLE_CONTRIBUTOR
DispACERules = "Contributor"
Case 1026 ' Check value since ROLE_CONTRIBUTOR is incorrect
DispACERules = "Contributor"
Case 1147 ' Check value since ROLE_EDITOR is incorrect
DispACERules = "Editor"
Case ROLE_NONEDITING_AUTHOR
DispACERules = "Nonediting Author"
Case 1043 ' Check value since ROLE_NONEDITING AUTHOR is incorrect
DispACERules = "Nonediting Author"
Case 2043 ' Check value since ROLE_OWNER is incorrect
DispACERules = "Owner"
Case ROLE_PUBLISH_AUTHOR
DispACERules = "Publishing Author"
Case 1179 ' Check value since ROLE_PUBLISHING_AUTHOR is incorrect
DispACERules = "Publishing Author"
Case 1275 ' Check value since ROLE_PUBLISH_EDITOR is incorrect
DispACERules = "Publishing Editor"
Case ROLE_REVIEWER
DispACERules = "Reviewer"
Case 1025 ' Check value since ROLE_REVIEWER is incorrect
DispACERules = "Reviewer"
Case Else
DispACERules = "Custom"
End Select

End Function

Popular posts from this blog

Downloading a shared file from Onedrive for business using Powershell

I thought I'd quickly share this script I came up with to download a file that was shared using One Drive for Business (which is SharePoint under the covers) with Powershell. The following script takes a OneDrive for business URL which would look like https://mydom-my.sharepoint.com/personal/gscales_domain_com/Documents/Email%20attachments/filename.txt This script is pretty simple it uses the SharePoint CSOM (Client side object Model) which it loads in the first line. It uses the URI object to separate the host and relative URL which the CSOM requires and also the SharePointOnlineCredentials object to handle the Office365 SharePoint online authentication. The following script is a function that take the OneDrive URL, Credentials for Office365 and path you want to download the file to and downloads the file. eg to run the script you would use something like ./spdownload.ps1 ' https://mydom-my.sharepoint.com/personal/gscales_domain_com/Documents/Email%20attachments/filena

Export calendar Items to a CSV file using EWS and Powershell

Somebody asked about this last week and while I have a lot of EWS scripts that do access the Calendar I didn't have a simple example that just exported a list of the Calendar events with relevant information to a CSV file so here it is. I've talked on this one before in this howto  but when you query the calendar folder using EWS you need to use a CalendarView which will expand any recurring appointments in a calendar. There are some limits when you use a calendarview in that you can only return a maximum of 2 years of appointments at a time and paging will limit the max number of items to 1000 per call. So if you have a calendar with a very large number of appointments you need to break your query into small date time blocks. In this example script I'm just grabbing the next 7 days of appointments if you want to query a longer period you need to adjust the following lines (keeping in mind what I just mentioned) #Define Date to Query $StartDate = (Get-Date) $EndDate

How to test SMTP using Opportunistic TLS with Powershell and grab the public certificate a SMTP server is using

Most email services these day employ Opportunistic TLS when trying to send Messages which means that wherever possible the Messages will be encrypted rather then the plain text legacy of SMTP.  This method was defined in RFC 3207 "SMTP Service Extension for Secure SMTP over Transport Layer Security" and  there's a quite a good explanation of Opportunistic TLS on Wikipedia  https://en.wikipedia.org/wiki/Opportunistic_TLS .  This is used for both Server to Server (eg MTA to MTA) and Client to server (Eg a Message client like Outlook which acts as a MSA) the later being generally Authenticated. Basically it allows you to have a normal plain text SMTP conversation that is then upgraded to TLS using the STARTTLS verb. Not all servers will support this verb so if its not supported then a message is just sent as Plain text. TLS relies on PKI certificates and the administrative issue s that come around certificate management like expired certificates which is why I wrote th
All sample scripts and source code is provided by for illustrative purposes only. All examples are untested in different environments and therefore, I cannot guarantee or imply reliability, serviceability, or function of these programs.

All code contained herein is provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.