AdminSDHolder, Protected Groups, SDProp and moving mailboxes in Exchange

When you move a mailbox in Exchange 2000 or newer, you sometimes encounter an error saying that you have insufficient permissions to move the mailbox. Although that may be the case, usually this error is caused by the user object associated with the mailbox you are trying to move not having inheritable permissions enabled in Active Directory. This is also known as that the DACL is protected, i.e. it is special and should not be changed. But why is it protected?

Usually it is protected because the user was once a member of one of the protected administrative groups in Active Directory. (Notice the word ‘once’, it will be important later!) These groups are (per Windows Server 2008 R2):

  • Enterprise Admins
  • Schema Admins
  • Domain Admins
  • Administrators
  • Account Operators
  • Server Operators
  • Print Operators
  • Backup Operators
  • Cert Publishers

Any user who is a direct or indirect member of any of these groups will get a protected DACL (inheritable permissions turned off) and the attribute adminCount set to 1. SDProp, or the Security Descriptor Propagator, thread within the LSASS.EXE process is responsible for checking and applying these settings once an hour. Any change you make to a protected object will be reset within the hour.

So back to moving mailboxes.

If the user is a member of any of the protected groups, the move mailbox process completes successfully since Exchange is aware of how to handle that scenario. But if the user has been removed from all protected groups the move process fails (remember I said “once a member of”).

The reason is that the user still has a protected DACL and the adminCount attribute set to 1. SDProp does not reverse its changes when you remove a user from a protected group. This is a scenario that Exchange does not know how to handle and so throws the insufficient permissions error. The easiest way to resolve the problem is to go into the Security tab of the user object, select Advanced and hit the Restore Defaults button. That will enable inheritance of permissions and remove any ACEs that SDProp (or any other process) has set explicitly. One important thing to know is that the Restore Defaults button does not reset the adminCount attribute back to 0, so you still have a user object in a non-consistent state (it is inheriting permissions, but still flagged as a special object). The best practice would be to manually clear adminCount with you favorite DS tool when you also enable permission inheritance.

Now that we know this it would be a good idea to find all the users that would fail when we tried to move them. To do this we would need to construct a query with the following criteria:

  • Not a member of any of the protected groups
  • Has a mailbox
  • Has a protected DACL

My choice would be PowerShell. Here is an example using the Quest Active Directory cmdlets:

  1. Put all the known protected groups in an array:
    $ADProtectedGroups = @(“Enterprise Admins”,”Schema Admins”,”Domain Admins”,”Administrators”,”Account Operators”,”Server Operators”,”Print Operators”,”Backup Operators”,”Cert Publishers”)
  2. Find all the users and put them in an array:
    $mismatchedUsers = Get-qaduser -sizelimit 0 -securitymask DACL –NotIndirectMemberOf $ADProtectedGroups -IncludedProperties homeMDB | Where-Object {(($_.DirectoryEntry.PSBase.ObjectSecurity.AreAccessRulesProtected) –
    and ($_.homeMDB -ne $null))}
  3. View the users if you like:
    $mismatchedUsers | ft
  4. Fix the users:
    $mismatchedUsers | ForEach { Set-QADObjectSecurity $_ –UnLockInheritance | Set-QADObject -ObjectAttributes @{adminCount=$null} }

Note: You may also want to include adminCount=1 in your search to see which objects have it set, but you could then get back users that have been fixed before by pressing Restore Defaults or enabling inheritable permissions.

To search for users with adminCount=1:

$admincountUsers = Get-qaduser -sizelimit 0 -NotIndirectMemberOf $ADProtectedGroups -IncludedProperties homeMDB,adminCount | Where-Object {(($_.adminCount -eq 1) -and ($_.homeMDB -ne $null))}

Or to just find everything with adminCount=1:

Get-ADObject –LDAPFilter “(adminCount=1)”

Exchange Move Mailbox logon info

Event IDs related to Mailbox moves

The Event source for Mailbox moves is Exchange Migration, and the events are logged in the Application log on the server where an administrator started the move. Meaning; where the admin was logged on and used the EMC or EMS to start the mailbox move. It would be nice to have all the mailbox move events gathered in one place, and that can be performed with Event collection.

Event ID Level  
1006 Information Indicates the start of a mailbox move
1022 Error Logon failure on database, caused by the mailbox move
9660 Warning User X failed to log on because their mailbox is in the process of being moved
9873 Information A named property has been created for database XX. Meaning the new mailbox has been created in the destination database.
1007 Information The mailbox was successfully moved.
9354 Information The mailbox is deleted from the source database
1154 Information Rule synchronization between old and new mailbox has completed successfully.
1205 Error Failed to create mailbox

Last logged on user

Whenever you move a mailbox in Exchange Server the LastLoggedOnUserAccount attribute of the mailbox is changed to the user running the mailbox move. This is confusing since that user does not need permission to log on to the mailbox to perform the move.

It can also present a problem if you are trying to figure out which users have yet to log on to their mailboxes after moving them between servers. Let’s say you run this command:

Get-MailboxStatistics | where { $_.LastLogonTime -eq $null }

This would show you which users have never logged on to their mailboxes. Whichever servers they originally were located on cannot be removed before they have logged on at least once and been redirected to their new mailbox servers. Unfortunately, since the user performing the mailbox move is added to the LastLoggedOnUserAccount this command will probably return no users.

‘Remove Exchange Attributes’ á la PowerShell

The extensions to Active Directory Users and Computers for Exchange 2000 and Exchange 2003 have a task called Remove Exchange Attributes that is accessible from the Exchange Tasks menu. It removes all Exhange related attributes from the objects on which it is run. This is useful when an object is in an inconsistent state, as regards to Exchange. For example if an Exchange attribute has invalid data or not all required attributes are present.
If you remove the last Exchange 2000/2003 server from your organization you will not be able to use the Remove Exchange Attributes task, even if the extensions are still installed on a computer. I recently found myself in just that situation and had to come up with a workaround. My favorite tool lately is PowerShell so I decided to use that. This is the command I came up with, using the cmdlets from Quest Software for Active Directory:

As you can see, this command targets groups, but it can be easily changed to apply to other object types.
I found a list of all the Exchange attributes that the Remove Exchange Attributes task removes here: