Removing Unresolved SIDs in Exchange 2010
In this post, I'm going to describe how to remove unresolved SIDs from public folders in Exchange 2010. But first, let’s talk about what they are and why we care about them.
What are unresolved SIDs?
When you view the permissions on a file in Windows or an object in Active Directory, you get a nice friendly list of names, each one with its associated access rights displayed. However, the security descriptor does not actually contain the names of the users – it only contains their SIDs. When an application such as Explorer or ADUC displays the permissions, it attempts to resolve each SID to a name, so when you look at it you can make some sense of what you’re seeing.
An unresolved SID is a SID that no longer resolves, usually because the user has been deleted. If you look at an object in ADUC, it looks like this:
In Exchange, folders have security descriptors that are very similar to the ones in Windows, except that things are ordered differently. But you still have SIDs and rights, and when a SID doesn’t resolve anymore, you’ll see that in Outlook:
Why do we care about them?
Unresolved SIDs don’t cause a problem; they just look ugly. Some customers want to remove them for that reason alone, and some customers have other reasons. A lot of customers used PFDAVAdmin for this, but there was a specific reason PFDAVAdmin removed these.
Back in Exchange 2000 and Exchange 2003, it was possible to expose the Information Store database as a drive in Windows. This was the infamous M: drive. It became infamous because applications that were not Exchange-aware would access folders through the M: drive and mess up the permissions. Above, I briefly mentioned that things are ordered differently in an Exchange ACL than a Windows ACL. Applications that looked at the folders in M: and thought they were plain old Windows folders would reorder the stuff in the security descriptor to fit the Windows format. This meant it no longer matched the Exchange canonical format, and the permissions wouldn’t work as expected.
After an application had run through the M: drive and made all the ACLs non-canonical, it was a huge pain to go through and manually correct them. This was one of the main reasons I wrote the PFDAVAdmin tool. PFDAVAdmin provided an easy way to put all the ACLs back in canonical order.
One thing about Exchange canonical order is that the SIDs need to go in a particular order based on the object type. Users need to be at the top of the ACL, followed by groups. If you’re trying to reorder the ACL to make it canonical again, and you run into an unresolved SID, this presents a problem. Since you can’t resolve the SID, you don’t know what type of object it is, so where should it go?
There are a few ways you could approach this problem. For instance, you could just pretend it’s a user SID. If the object has been deleted, then the SID will never again resolve, so it won’t matter. If the SID is only unresolvable because of a temporary issue with a DC or something, then this could result in the ACL becoming non-canonical once the SID resolves again.
However, the approach I took with PFDAVAdmin was to have it remove the unresolved SIDs. I couldn’t be sure what they were and why they were unresolvable, and the whole point was to force the ACL into a canonical state, so this seemed like a sensible approach.
Why doesn’t ExFolders remove them?
When I rewrote the guts of PFDAVAdmin for Exchange 2010, I renamed it ExFolders. While the GUI looks almost identical, the code underneath is not the same and required a lot of rewriting. When it came time to look at the “Fix Folder DACL” code and decide whether to move it into ExFolders, I just didn’t see any need for it. The widespread non-canonical ACL issues from the Exchange 2000/2003 days were gone, so I left this functionality out of ExFolders entirely. Unresolved SID removal was a side-effect of fixing the DACL, so it likewise fell by the wayside.
How can I remove them now?
OK, so you want to remove them from your public folders in Exchange 2010, but there’s no tool to do that anymore. Fortunately, it’s easy to remove them with a simple script. I’ve included one below. This script will be far slower than PFDAVAdmin was, but it will get the job done.
If you run it with the following syntax, it will only report the unresolved SIDs:
.\Check-UnresolvedSIDs.ps1 -Server MyPFServer
If you want it to actually remove them, you must add the –Remove parameter:
.\Check-UnresolvedSIDs.ps1 -Server MyPFServer -Remove $true
The output will look something like this:
\Folder1: Checking folder
\Folder2: Checking folder
\Folder2 has unresolved SIDs:
NT User:S-1-5-21-1016452943-3003584382-490080582-2161
\Folder3: Checking folder
\MyNewFolder: Checking folder
\SomeOtherFolder: Checking folder
\SomeOtherFolder has unresolved SIDs:
NT User:S-1-5-21-1016452943-3003584382-490080582-1136
NT User:S-1-5-21-1016452943-3003584382-490080582-1135
If you add the –Remove parameter, it will also tell you that it’s removing them.
Here’s the script. Enjoy!
# Check-UnresolvedSIDs.ps1
#
# This script will remove all unresolved SIDs from public folder permissions.
# This will take quite some time to run against a large hierarchy.
param([string]$Server, [bool]$Remove)
if ([System.String]::IsNullOrEmpty($Server))
{
"You must specify a server."
return
}
function CheckUnresolvedForFolder($folder)
{
($folder.Identity.ToString() + ": Checking folder")
$unresolved = Get-PublicFolderClientPermission -Identity $folder -Server $Server| WHERE { $_.User -like "NT User:S-*" }
if ($unresolved -ne $null)
{
($folder.Identity.ToString() + " has unresolved SIDs:")
foreach ($item in $unresolved)
{
(" " + $item.User.ToString())
}
if ($Remove)
{
(" Removing the unresolved SIDs...")
foreach ($item in $unresolved)
{
$item | Remove-PublicFolderClientPermission -Identity $folder -Server $Server -Confirm:$false
}
(" Unresolved SIDs were removed.")
}
}
}
function DoFolderRecursive($folder)
{
CheckUnresolvedForFolder($folder)
$subfolders = Get-PublicFolder -Identity $folder -GetChildren
if ($subfolders -ne $null)
{
foreach ($subfolder in $subfolders)
{
DoFolderRecursive($subfolder)
}
}
}
$ipmSubtree = Get-PublicFolder "\" -Server $Server
DoFolderRecursive($ipmSubtree)
$nonIpmSubtree = Get-PublicFolder "\NON_IPM_SUBTREE" -Server $Server
DoFolderRecursive($nonIpmSubtree)
"Done!"
Comments
Anonymous
January 01, 2003
Awesome! I was wondering why that would be the case. So far I've only run into that behavior when removing duplicate ACEs.Anonymous
January 01, 2003
Hi Bill - nice script, however I've noticed that SIDs are not removed if the permission level is set to "None". Is there a way to get around this you've found? Regards MattAnonymous
January 01, 2003
Yes, you could modify this script or write a new one to accomplish that. In fact, I have a generic "do all mailbox folders" script that I use as the basis for other scripts. You can find that one here:https://gist.github.com/bill-long/8677221. I should probably add some more documenting comments and blog about it.
I'm also looking at adding that functionality to my new (beta) MAPIFolders tool (http://mapifolders.codeplex.com), but it's not in there yet.Anonymous
January 01, 2003
The script has the same requirement as MAPIFolders, to change permissions the public folder/s must reside in the mailbox that is the primary hierarchy. This has created issues with one of our customers in that you have to exit Outlook after the public folders are moved or you cannot mark multiple items or an entire folder as read. I am seeing unresolved SIDS as NT:S- instead of NT User:S-.Anonymous
January 01, 2003
Nice! Thanks Jeremy. I'm also considering adding this functionality to a new MAPI-based tool, which would be much faster.Anonymous
January 01, 2003
You could do it that way. However, I like to avoid building massive result sets like that when I can, because it is harder on the server in larger environments. Remember, the server is going to hold all that info in memory until the script is done iterating over the folders. That's why this script only enumerates one level at a time. In most environments it's not a big deal, but I've seen environments with staggering numbers of public folders. :)Anonymous
January 01, 2003
I tested the script against Exchange 2013 and had to modify it to use -Mailbox in place of -Server and it appears to work. Be sure you specify the mailbox that contains the primary hierarchy.Anonymous
January 01, 2003
As a admin in a Hosted environment, I was very disturbed to see that this feature was gone from ExFolders. We use that option many many times as new customers migrate with existing PF data numerous times a week and want the SIDs gone. The script is a viable workaround although when you have 100K PF folders (1.5TB+ of data) it could take forever and ever to finish especially since PF cmdlets are already slow. So for us, we would have to tweak the script to start at the top of customer1's PF structure to get results sooner than days later :) So please add it back to ExFolders for us in the Hosting world, we will send you the biggest cookie we can find.Anonymous
January 01, 2003
Each PF database has a copy of the hierarchy. The hierarchy contains the security descriptor of the folder, and changes to the security descriptor on one copy of the hierarchy will replicate to all the other copies. You need to specify a server just to tell the script which copy to use to make the changes. Once those changes are made, they will replicate to the other servers, typically within 15 minutes.Anonymous
January 01, 2003
Thanks for the feedback, DJ. I'll keep this on my radar for when I have more time to work on ExFolders.Anonymous
January 01, 2003
The comment has been removedAnonymous
January 01, 2003
Hi Matt, somehow I missed your comment. I would have responded earlier. It certainly should remove entities that have a role of "None". However, keep in mind that Default and Anonymous should always appear in the ACL, so even if you clear the permissions, those will still be there, and will appear with "None". Were you talking about those, or actual users? Hi Max, yes you can use this with an Exchange 2007 server as the target server. However, ExFolders itself must be executed from an Exchange 2010 server.Anonymous
January 01, 2003
I was incorrect above. The public folders do NOT have to be in the public folder mailbox that is the primary hierarchy for the script to remove permissions.Anonymous
October 24, 2011
why don't you use this? $ipmSubtree = Get-PublicFolder "" -Server $Server -Recurse -Resultsize unlimited Btw. the -ResultSize parameter is necessary if this should work in unknown environments.Anonymous
March 12, 2012
Hi Bill, is this working for exchange 2007 public folders too?Anonymous
April 04, 2013
Hey Bill why do i need to specify the server? I have mutiple copies of PF running accross different MBX servers. WIll doing this on just one server handle them all, or do i need to run this on each server? Thanks!Anonymous
April 04, 2013
Excellent my friend. No more 2028 errors!Anonymous
September 06, 2013
Sadly, I too am having the same problem Matt has. If the permission level is none, the script says it removes them, but doesn't.Anonymous
April 24, 2014
Bill Can this script (or something like it) be used to remove unresolved SID's from mailboxes? I have a lot of "resource" mailboxes with unresolved SID's because of employee turnover and I'm looking for an easy way to remove them.Anonymous
April 25, 2014
Thanks Bill. Unfortunately, I'm too inexperienced to write this stuff, but am looking forward to your new MapiFolders. I hope you can add the remove unresolved SID's functionality to it for both public folders and mailboxes.Anonymous
May 04, 2015
Just confirmed...everyone on here stating that the removal of Orphaned accounts is NOT possible if the Permission Level is set to NONE...is accurate for Exchange 2010.
Just went through and ran a test account 14 accounts....flipped Permission Level from NONE to Reviewer.....then executed the following:
$perms = (Get-PublicFolder "" | Get-PublicFolderClientPermission | ?{$_.User -like "NT User:S*"})
ForEach($perm in $perms)
{
Remove-PublicFolderClientPermission -Identity $perm.Identity -User $perm.User -AccessRights $perm.AccessRights –Confirm:$False
}
......and viola!!!! No more SIDs hanging around!
CheersAnonymous
January 29, 2016
It looks like Microsoft has "fixed" the Remove-PublicFolderClientPermission command. Now all that I get is "Public folder user "NT User:S-1-5-21-1116015673-1802451004-6498272-166128" doesn't exist. A valid public folder user should be a mail-enabled user, mailbox, or distribution group."Anonymous
January 29, 2016
Interesting. What version of Exchange, Matt?