Sample Script to Search Incorrect msExchMasterAccountSid Status
The following script sample demonstrates a way to search Active Directory® directory service for Microsoft® Exchange Server mailbox accounts that have an incorrect msExchMasterAccountSid status. It will search for both enabled and disabled Active Directory accounts that are Exchange mailbox-enabled. The script also removes the Associated External Account right from enabled Active Directory accounts, which also clears msExchMasterAccountSid, and sets the Associated External Account for disabled accounts, which also sets msExchMasterAccountSid. If a disabled Active Directory account that is mailbox-enabled has no Associated External Account, the Associated External Account and msExchMasterAccountSid will be set to the well-known Self security identifier (SID). The log file that records problems found and changes made is called NoMAS_VBS.log.
' Begin script
Option Explicit
const LOGFILE = "NoMAS_VBS.log"
' Do not change anything below here unless you really know what you are doing.
const ACCESS_ALLOWED = &h0
const FULL_MAILBOX_ACCESS = &h1
const SEND_AS = &h2
const CONTAINER_INHERIT_ACE = &h2
const ASSOCIATED_EXTERNAL = &h4
const READ_PERMISSIONS = &h20000
Dim oConnection
Dim oRecordSet
Dim oRecordSet2
Dim oCommand
Dim strQuery
Dim strDomainNC
Dim oRootDSE
Dim i
Dim FSO
Set FSO = CreateObject("Scripting.FileSystemObject")
Dim TextStream
Set TextStream = FSO.OpenTextFile(LOGFILE, 8, TRUE)
TextStream.WriteLine("****************************************************************************")
TextStream.WriteLine("NoMAS.vbs, v0.2005.1.20, Microsoft Product Support Services")
TextStream.WriteLine("Started logging " + Cstr(Date()) + ", " + Cstr(Time()))
TextStream.WriteLine("****************************************************************************")
Dim oAce
Set oAce = CreateObject("AccessControlEntry")
oAce.Trustee = "NT AUTHORITY\SELF"
oAce.AccessMask = (FULL_MAILBOX_ACCESS + SEND_AS + ASSOCIATED_EXTERNAL + READ_PERMISSIONS)
oAce.AceFlags = CONTAINER_INHERIT_ACE
oAce.AceType = ACCESS_ALLOWED
set oRootDSE = GetObject("LDAP://RootDSE")
strDomainNC = oRootDSE.Get("defaultNamingContext")
set oRootDSE = Nothing
Set oConnection = CreateObject("ADODB.Connection")
oConnection.Provider = "ADsDSOObject"
oConnection.Open "Active Directory Provider"
Set oCommand = CreateObject("ADODB.Command")
Set oCommand.ActiveConnection = oConnection
Dim strDomainQuery
strDomainQuery = "<LDAP://cn=System," + strDomainNC + ">;(objectCategory=trustedDomain);trustPartner;onelevel"
oCommand.CommandText = strDomainQuery
Set oRecordSet = oCommand.Execute
If oRecordSet.Eof Then
TextStream.WriteLine("Didn't find any trusts, assuming single domain...")
PerDomain(strDomainNC)
Else
While Not oRecordSet.Eof
strDomainNC = oRecordSet.Fields(0)
PerDomain(strDomainNC)
oRecordSet.MoveNext
Wend
End If
'Clean up
oRecordSet.Close()
oRecordSet2.Close()
oConnection.Close()
TextStream.WriteLine("Finished at " + Cstr(Date()) + ", " + Cstr(Time()))
TextStream.WriteBlankLines(1)
TextStream.Close()
Set oRecordSet = Nothing
Set oRecordSet2 = Nothing
Set oConnection = Nothing
Sub PerDomain(strDomainNC)
Dim strDisabledQuery
strDisabledQuery = "<LDAP://"&strDomainNC&">;(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=2)(!(msExchMasterAccountSid=*))(msExchHomeServerName=*)(homeMDB=*));AdsPath;subTree"
oCommand.CommandText = strDisabledQuery
oCommand.Properties("Page Size") = 100
Set oRecordSet2 = oCommand.Execute
if oRecordSet2.Eof then
TextStream.WriteLine("No broken disabled users were found.")
Else
i = 1
While Not oRecordSet2.Eof
Dim oUser
Set oUser = GetObject(oRecordSet2.Fields("AdsPath").Value)
TextStream.WriteLine("Disabled user " + vbTab + oRecordSet2.Fields("AdsPath").Value + vbTab + " is missing msExchMasterAccountSid")
Dim mailboxSD
On Error Resume Next
Set mailboxSD = oUser.MailboxRights
If (Err.Number <> 0) Then
TextStream.WriteLine("Failed to get MailboxRights, error 0x" + CStr(Hex(Err.Number)) + " : " + Err.Description)
Err.Clear()
End If
Dim oDACL
Set oDACL = mailboxSD.DiscretionaryAcl
Dim bFoundMASInSD
bFoundMASInSD = FALSE
Dim ace
for each ace in oDACL
if ( ace.AccessMask And ASSOCIATED_EXTERNAL ) then
bFoundMASInSD = TRUE
end if
next
if (FALSE = bFoundMASInSD) then
oDACL.AddAce(oACE)
end if
ReorderDACL(oDACL)
mailboxSD.DiscretionaryAcl = oDACL
oUser.MailboxRights = Array(mailboxSD)
On Error Resume Next
oUser.SetInfo
If (Err.Number <> 0) Then
TextStream.WriteLine("Failed to SetInfo, error 0x" + CStr(hex(Err.Number)) + " : " + Err.Description)
Err.Clear()
End If
oDACL = Nothing
mailboxSD = Nothing
oUser = Nothing
i = i+1
On Error Goto 0
oRecordSet2.MoveNext
Wend
TextStream.WriteLine("No more broken disabled users were found.")
End if
'Clean up
oRecordSet2.Close()
Dim strEnabledQuery
strEnabledQuery = "<LDAP://"&strDomainNC&">;(&(objectCategory=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)((msExchMasterAccountSid=*))(msExchHomeServerName=*)(homeMDB=*));AdsPath;subTree"
oCommand.CommandText = strEnabledQuery
Set oRecordSet2 = oCommand.Execute
if oRecordSet2.Eof then
TextStream.WriteLine("No broken enabled users were found.")
Else
i = 1
' Iterate through the objects that match the filter
While Not oRecordSet2.Eof
Set oUser = GetObject(oRecordSet2.Fields("AdsPath").Value)
TextStream.WriteLine("Enabled user " + vbTab + oRecordSet2.Fields("AdsPath").Value + vbTab + " has msExchMasterAccountSid")
On Error Resume Next
Set mailboxSD = oUser.MailboxRights
If (Err.Number <> 0) Then
TextStream.WriteLine("Failed to get MailboxRights, error 0x" + CStr(hex(Err.Number)) + " : " + Err.Description)
Err.Clear()
End If
Set oDACL = mailboxSD.DiscretionaryAcl
for each ace in oDACL
if ((ace.AccessMask And ASSOCIATED_EXTERNAL) = ASSOCIATED_EXTERNAL) then
ace.AccessMask = ace.AccessMask And Not ASSOCIATED_EXTERNAL
end if
next
ReorderDACL(oDACL)
mailboxSD.DiscretionaryAcl = oDACL
oUser.MailboxRights = Array(mailboxSD)
On Error Resume Next
oUser.SetInfo
If (Err.Number <> 0) Then
TextStream.WriteLine("Failed to SetInfo, error 0x" + CStr(hex(Err.Number)) + " : " + Err.Description)
Err.Clear()
End If
oDACL = Nothing
mailboxSD = Nothing
oUser = Nothing
i = i+1
On Error Goto 0
oRecordSet2.MoveNext
Wend
TextStream.WriteLine("No more broken enabled users were found.")
End If
end Sub
Sub ReorderDACL(dacl)
Set newdacl = CreateObject("AccessControlList")
Set ImpDenyDacl = CreateObject("AccessControlList")
Set InheritedDacl = CreateObject("AccessControlList")
Set ImpAllowDacl = CreateObject("AccessControlList")
Set InhAllowDacl = CreateObject("AccessControlList")
Set ImpDenyObjectDacl = CreateObject("AccessControlList")
Set ImpAllowObjectDacl = CreateObject("AccessControlList")
For Each ace In dacl
If ((ace.AceFlags And ADS_ACEFLAG_INHERITED_ACE) = ADS_ACEFLAG_INHERITED_ACE) Then
InheritedDacl.AddAce ace
Else
Select Case ace.AceType
Case ADS_ACETYPE_ACCESS_ALLOWED
ImpAllowDacl.AddAce ace
Case ADS_ACETYPE_ACCESS_DENIED
ImpDenyDacl.AddAce ace
Case ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
ImpAllowObjectDacl.AddAce ace
Case ADS_ACETYPE_ACCESS_DENIED_OBJECT
ImpDenyObjectDacl.AddAce ace
Case Else
End Select
End If
Next
For Each ace In ImpDenyDacl
newdacl.AddAce ace
Next
For Each ace In ImpDenyObjectDacl
newdacl.AddAce ace
Next
For Each ace In ImpAllowDacl
newdacl.AddAce ace
Next
For Each ace In impAllowObjectDacl
newdacl.AddAce ace
Next
For Each ace In InheritedDacl
newdacl.AddAce ace
Next
Set InheritedDacl = Nothing
Set ImpAllowDacl = Nothing
Set ImpDenyObjectDacl = Nothing
Set ImpDenyDacl = Nothing
newdacl.AclRevision = dacl.AclRevision
Set dacl = nothing
Set dacl = newdacl
end Sub
'End Script
For more information about the msExchMasterAccountSid attribute, see Detecting and Correcting msExchMasterAccountSid Issues.