Folder Redirection - Resetting Permissions with a Perl Script

If you're using Folder Redirection, Roaming Profiles, etc, it's important to set the permissions correctly at the root of the file share, so that each user directory gets created with the correct permissions (giving the user, administrators, and the system full control, and no access to anyone else).  Usually, that's the easy part, but sometimes those permissions can get broken: when you copy the share to a new server for example, and you need to be able to fix them.

Root Share Permissions
Setting Up the Root Permissions
When you first create the file share to store the user folders, you must setup the NTFS permissions at the root of the share.  This is typically done by granting all users the ability to create a subfolder in the root, and granting the "CREATOR OWNER" full control of subdirectories and files that they create.
If you have a closer look at these permissions, you'll see that Administrators and System have full control at the root, in all subfolders and files.  The other permissions are a little more subtle.  For example, if you look at the entry for Users, you'll see that "Special Permissions is checked".  In order to see what that means, we have to click the Advanced button.  In the
Advanced View of Root Permissions
Advanced dialog, select the Users entry and click Edit.  Now we can see that Users has been granted read & execute, and the ability to create folders, just at the root folder ("This folder only").  So, when the user creates a folder, this permission does not apply to the subfolder.  So how does the user get permissions to the folder they just created?  Through CREATOR OWNER. 

You can see in the Advanced dialog, that CREATOR OWNER is granted full control over subfolders and files (that they own).  So a user creates a folder, and it grants the user full control over that subfolder and everything in it.
User Folder Permissions
Now if you look at the permissions of a folder that a user created, you'll see the user explicitly in the permissions, and the Users group has no permissions at all, just as we want.

If you look at the owner tab in the Advanced dialog, you'll see that the user that created the folder is the owner of the folder.  You'll also notice that the user is granted full control to this folder only, and again, the permissions grant CREATOR OWNER full control over subfolders.  So if the user creates another child folder, they are granted explicit access to that one too.

If ownership is revoked, the user will still have access to their existing folders and files, but they won't be able to create new subfolders.  Weird side effect.  No big deal, but occasionally, you'll run into problems because of this.

Problems with the Permissions
Problems can occur if you copy the share to a new server and loose the ownerships of the folders (you might end up with everything being owned by Administrators).  You might find yourself in the position of having to reset ownership of each folder to the user that is supposed to own it.  That can be a real drag if you have a lot of folders.  You certainly wouldn't want to have to fix each folder by hand.

So, to reset the permissions on the user's folder permissions programmatically, you can use the icacls utility.  It is included with Windows Server 2003 SP2, Windows Vista, and Windows 2008.

To set ownership of the user's folder, you type two commands:

icacls folderPath /setowner userPrincipalName /T /C
icacls folderPath /reset /T /C

The commands are best run locally on the file server, since running it over the network will be slow.  The user principal name (UPN) should be in the form of [email protected].

Pretty obvious, the first command resets ownership of all of the user's folders and files, and the second resets the permissions, based on the user's ownership.  Now again, you wouldn't want to have to lookup the user's UPN and run these commands for each folder in a very large share.  So what now?  Perl.

The following script reads through the folders at the root of a user share.  Each folder's name corresponds with a user name in Active Directory.  The script searches AD for the user, retrieves the UPN, and executes the icacls commands for each folder.
use Win32::OLE;
$¦=1;
$searchDir="f:/users";
 
if(substr($searchDir,length($searchDir)-1) eq "/"){
 $searchDir=substr($searchDir,0,length($searchDir)-1);
}
 
$dse=Win32::OLE->GetObject("LDAP://RootDSE");
$root=$dse->Get("RootDomainNamingContext");
$adpath="GC://$root";
$base="<".$adpath.">";
$c = Win32::OLE->new("ADODB.Connection");
$c->{Provider} = "ADsDSOObject";
$c->Open("ADSI Provider");
$comm=Win32::OLE->new("ADODB.Command");
$comm->{ActiveConnection}=$c;
$comm->{Properties}->{'Page Size'}=200;
$rs = Win32::OLE->new("ADODB.RecordSet");
 
$d=opendir(DIR,$searchDir."/");
@subdirs=map ( $_=$searchDir."/".$_, (grep { !/\./ && !/\.\./ &&  -d "$searchDir/$_"} readdir(DIR)));
foreach $subdir (@subdirs){
 ($sourcedir=$subdir)=~s/\//\\/g;
 @pathparts=split /\\/,$sourcedir;
 $user=$pathparts[$#pathparts];
 $comm->{CommandText}="$base;(&(objectCategory=user)(¦(cn=$user)(samAccountName=$user)));userprincipalname;SubTree";
 $rs=$comm->Execute;
 until ($rs->EOF){
  $upn=$rs->Fields(0)->{Value};
  if($sourcedir & $upn){
   print "$sourcedir\t$upn\n";
   system("icacls $sourcedir /setowner $upn /T /C");  
   system("icacls $sourcedir /reset /T /C");
  }
  $rs->MoveNext;
 }
}

Now, if you have a broken user share, you can simply fix the permissions at the root of the share by hand, and let Perl do the rest!

0 comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...