Fixing Permissions on Home Drive Folders
Last week I found that a lot of our users offline files were not syncing to their laptops. After testing multiple laptops, with multiple users, I was getting mixed results of “Access Denied” and “Unable to sync at this time.” Bringing Powershell to the rescue by fixing user permission on home drive.
All laptops are running Windows 8.1, and are fully patched and up to date.
“Access Denied” obviously points to a permission issue but as far as i could see the security groups had full access to the root level, and all sub folders. When looking at some of the “sub folders” I noticed that permissions were being inherited, but those inheritances were not present at the level above. So I decided that i need to wipe out all of the user permission from a root level, and start from scratch.
On the server, (I use DFS so that when files move servers over the years through upgrades etc, the paths do not change.) all permissions were removed from the “users$” folder, and replaced all child objects to inherit permissions from this folder.
My folder structure looks like this:
The user folder is shared as “user$” so it is a hidden share, then admin staff have their folders under admin, staff under staff and pupils under their intake year.
Once the permissions had propagated to the sub folders I searched the internet and found the script below. (A link to the original script on the spiceworks community page is also below) This script helped me reset the file permissions on the users folders as each of the user folders had the same name as the username.
The script requires that you update two fields: “$homeDriveDir” & “$domainName” and that user running the script has full control over the files/folders that are having the permissions altered. (i.e. is a member of the administrators group”) I ran the script from my own computer rather than the server, and edited it for each of the folders, (Admin, Staff, and then each of the pupil intake folders.) File paths were changed to “\\dfspath\users$\curric\staff” “\\dfspath\users$\curric\pupils\2010” “\\dfspath\users$\admin”
Then let the script work its magic.
Minimum offline file share permissions can be found in the Microsoft article here.
In the example they used has all user folders under the top share and this wasn’t deep enough for me. I applied the same security permissions i.e. “admin users” and “staff users” to the folders “admin”, “curric/staff” as well as both to the users folder (referred to as “Security group of users that need permissions” on the Microsoft article).
After a couple of days of testing offline files for all my staff now seems to be working OK and other than the occasional “a file was changed while you were offline” conflict everything seems to be working OK.
I do not claim the script below as my own work. I simply added the “-path” and “-aclobject” arguments to fix an error that kept occouring. The original Script can be found here
############################################################################# # Script: changePermissions.ps1 # Author: Internet & Luis Goncalves & Rui Duarte & Karl Woods # Date: 17/07/2013 # Keywords: # Comments: # Pre-Requisites: Full Control over destination folder. # # # DISCLAIMER # ========== # THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE # RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. ############################################################################# # ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # Variables # # Where is the root of the home drives? $homeDrivesDir="ADDYOURHOMEDRIVEHERE" # Report only? ($false = fix problems) $reportMode = $false # Print all valid directories? $verbose = $false # What domain are your users in? $domainName = "ADDYOURFQDNHERE" # ####################################################################### # Save the current working directory before we change it (purely for convenience) pushd . # Change to the location of the home drives set-location $homeDrivesDir # Warn the user if we will be fixing or just reporting on problems write-host "" if ($reportMode) { Write-Host "Report mode is on. Not fixing problems" } else { Write-Host "Report mode is off. Will fix problems" } write-host "" # Initialise a few counter variables. Only useful for multiple executions from the same session $goodPermissions = $unfixablePermissions = $fixedPermissions = $badPermissions = 0 $failedFolders = @() # For every folder in the $homeDrivesDir folder foreach($homeFolder in (Get-ChildItem $homeDrivesDir | Where {$_.psIsContainer -eq $true})) { # dump the current ACL in a variable $acl= (Get-Item $homeFolder).GetAccessControl("Access") #$Acl = Get-Acl $homeFolder # create a permission mask in the form of DOMAIN\Username where Username=foldername # (adjust as necessary if your home folders are not exactly your usernames) $compareString = "*" + $domainName + "\" + $homeFolder.Name + " Allow FullControl*" # if the permission mask is in the ACL if ($Acl.AccessToString -like $compareString) { # everything's good, increment the counter and move on. if ($verbose) {Write-Host "Permissions are valid for" $homeFolder.Name -backgroundcolor green -foregroundcolor white} $goodPermissions += 1 } else { # Permissions are invalid, either fix or report # increment the number of permissions needing repair $badPermissions += 1 # if we're in report mode if ($reportMode -eq $true) { # reportmode is on, don't do anything Write-Host "Permissions not valid for" $homeFolder.Name -backgroundcolor red -foregroundcolor white } else { # reportmode is off, fix the permissions Write-Host "Setting permissions for" $homeFolder.Name -backgroundcolor red -foregroundcolor white # Add the user in format DOMAIN\Username $username = $domainName + "\" + $homeFolder.Name # Grant the user full control $accessLevel = "FullControl" # Should permissions be inherited from above? $inheritanceFlags = "ContainerInherit, ObjectInherit" #$inheritanceFlags = "None" # Should permissions propagate to below? $propagationFlags = "None" # Is this an Allow/Deny entry? $accessControlType = "Allow" try { # Create the Access Rule $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($username,$accessLevel,$inheritanceFlags,$propagationFlags,$accessControlType) # Attempt to apply the access rule to the ACL $Acl.SetAccessRule($accessRule) Set-Acl -path $homeFolder -AclObject $Acl # if it hasn't errored out by now, increment the counter $fixedPermissions += 1 } catch { # It failed! # Increment the fail count $unfixablePermissions += 1 # and add the folder to the list of failed folders $failedFolders += $homeFolder } } #/if } #/if } #/foreach # Print out a summary Write-Host "" Write-Host $goodPermissions "valid permissions" Write-Host $badPermissions "permissions needing repair" if ($reportMode -eq $false) {Write-Host $fixedPermissions "permissions fixed"} if ($unfixablePermissions -gt 0) { Write-Host $unfixablePermissions "ACLs could not be repaired." foreach ($folder in $failedFolders) {Write-Host " -" $folder} } # Cleanup popd