用来搜索不正确的 msExchMasterAccountSid 状态的示例脚本

 

上一次修改主题: 2005-10-12

以下脚本示例说明了搜索 Active Directory® 目录服务以查找 msExchMasterAccountSid 状态不正确的 Microsoft® Exchange Server 邮箱帐户的方法。它将搜索启用了 Exchange 邮箱的启用的和禁用的 Active Directory 帐户。此脚本还会从启用的 Active Directory 帐户中删除“关联的外部帐户”权限,这同时会清除 msExchMasterAccountSid;还会为禁用的帐户设置“关联的外部帐户”权限,这同时会设置 msExchMasterAccountSid。如果已启用邮箱的禁用的 Active Directory 帐户没有“关联的外部帐户”权限,则“关联的外部帐户”和 msExchMasterAccountSid 将设置为已知的自身安全标识符 (SID)。对发现的问题和所做的更改进行记录的日志文件名为 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

有关详细信息

有关 msExchMasterAccountSid 属性的详细信息,请参阅检测并纠正 msExchMasterAccountSid 问题