Summary: Superhero BATCHman restores NTFS security permissions using Windows PowerShell.
Microsoft Scripting Guy Ed Wilson here. Well, it is time once again for BATCHman. This time, it is Episode 12. Take it away, Sean.
When the digital crash
In a blink and a splash
A gleam in the night
To make all wrongs right
Our heroes fly out
And there is no doubt
That evil will fall true
At the sight of the blue
The one and only .NET duo—BATCHman and Cmdlet.
It’s a nice morning. BATCHman is playing with a new test module he has been encoding to stop criminals directly with Windows PowerShell. “BATCHpause” is what he is going to call it (patent pending patent pending). Cmdlet has just walked in from his early morning session of watching Electric Company reruns when off in the corner a large blue phone begins flashing.
“It’s the BATCHphone!” BATCHman leaps through the air pommelling poor Cmdlet in the process just to answer it.
Cmdlets staggers to his feet. “Mmmmmphphh…you know…*ugh*…there was an extension right beside you? *urrgghhh*”
“Wouldn’t have been as dramatic!” BATCHman responded as he picked up the phone. “Hello, BATCHman here!”
“BATCHman! I need your help now.” It was the principal at Redmond High School “Nobody can access their home drives! Little Johnny was trying to “help” the school administrator and somehow locked us out of our personal drives! Help us BATCHman!”
BATCHman knew only ONE thing could stop a problem like this, and only one duo. Quickly tossing Cmdlet an ice pack and a box of aspirin, he began to announce, “Cmdlet to the…”
Cmdlet staggered to his feet, ice pack in hand. “Yes, to the WinMobile. I know, I know”
“Actually, my good chum, I was going to use the new vehicle, the BATCHmobile. It’s powered by WP7 with Mango! The WinMobile needed an update.”
“Cooool!” burst out Cmdlet, forgetting his concussion. Leaping into the air, he landed on the new BATCHmobile, doing a triple flip as he landed.
“New Gorilla Glass,” muttered BATCHman. “Very smooth,” as they fired off into the city.
Moments later they arrive upon a scene that was absolute chaos.
“I can’t access my homework!”
“My locker combination is locked away from me!”
“I can’t see who I was supposed to have on detention!”
The entire high school had been turned into a zoo! (Or more of a zoo than usual anyway.)
The principal, disheveled and worn, is marching down the hall with scraggly-haired youth wearing a combination lock about his neck, and held by the collar, presenting him to the BATCHman.
“THIS! THIS caused all of the trouble! Little Johnny Loc…”
“Stand back, puny creature!” it barked out “I am the Locksmith, the newest member of the V.I.T. program. The world will bow before me! Buah ha ha ha haaaa!”
BATCHman scratched his head. “V.I.T.?”
“’Villains In Training!” announced The Locksmith. “Of course, I’m the first, but there will be more!” and he waved his “Official VIT” card written in crayon, feigning his invisible and useless villainy powers to the world.
Cmdlet shook his head. “A waste of good crayon, if you ask me.”
Undeterred BATCHman pressed on. “So no access to home folders? Please. Lock our little friend here into detention for the moment while we examine the issue.”
Accessing a server with the home folder structure, our hero checked the folders but found he could access them. “Hmmmm,” a puzzled look crossed over his face. He ran the following command on a user’s folder the check the NTFS rights.
$SecurityRights=GET-ACL E:\Home\Student542
Cmdlet looked over “Whatcha’ doin’?
BATCHman nearly forgot his experience in Windows PowerShell was a little more advanced. “I am using Get-ACL on a folder to see what the NTFS rights are. I suspect our little fiend has removed the access to the individual users.”
Scratching his eyeball, the sidekick wondered. “How did you guess that so easily?”
“Well,” the Tilley-hatted one continued, “usually if the user cannot access the files but the administrator can, it’s a rights problem. We can verify this by running Get-Member against the $SecurityRights object we just created to see the available methods.”
“I see near the very top that there is a property called Access, so if I type this, I can see the various groups able to access this object.”
$SecurityRights.Access
Practicing origami on his arms, Cmdlet stretched and then blurted out. “Hang on one sec. How did you know to use that and without browsing, how did you come to that conclusion?”
“In answer to your first question, I could say I used msdn.com and pulled up details on SYSTEM.SECURITY.ACCESSCONTROL, but the honest answer is I just plugged in values in the BATCHcave to learn what they might contain.”
Reasonable, thought Cmdlet. You can use research but sometimes just “playing about” produces the answer. “And the second?”
“There’s a note here on the desk: ‘I can browse these folders as administrator. !?#$?!%%$ Why isn’t anything working? ARGGGGHHH!!! $$#@@@?’”
“And they bothered to write the asterisk and punctuation marks?”
“Meh,” shrugged BATCHman. “So if you see the list presented on this folder under the HOME$ share called STUDENT542, you’ll see it is in fact missing access for the student.”
$SecurityRights.Access
“Now what I need to see is the normal permissions assigned when a home folder is created on this system, to see what’s missing exactly on a normal home drive for NTFS permissions.”
BATCHman created a temporary student in Active Directory with an appropriate 752-character long password. He then applied the settings for a home folder and noted the differences when running Get-ACL again on the new home folder.
$NewUserSecurity=GET-ACL C:\Home\Student160
$NewUserSecurity.Access
“Aha! As I suspected, we merely need to add the rights that a UserID would normally have on its own home drive. Now, I just need to find a script to do this.” BATCHman quickly queries the TechNet Script Center.
Cmdlet paused “You don’t know everything? But you’re…you’re BATCHman!” his jaw dropped to the ground like a child being told he couldn’t play Kinect for another three hours.
“True little buddy. I am skilled, but sometimes the ability to say ‘I don’t know’ is an even greater power. In these cases, I do know how to leverage many online resources for Wndows PowerShell such as the Hey, Scripting Guy! Blog, online MSDN articles, and community support.”
BATCHman searched and found something on the Script Repository.
“Aha! The power of online resources!” he exclaimed referencing a Windows PowerShell Tip of the Week on the TechNet Script Center.
Reading the instructions, he defined the various variables needed, explaining it all to Cmdlet as he went along.
“So our challenge is we must create a .NET object for access control. It comprises several additional objects. All of them are represented in the view of any of the access lists we just saw. We’ll use one of the access rules that is missing.”
“We start by getting the permissions on the folder in question.”
$Access=GET-ACL E:\Home\Student169
“First, we will specify the type of access for the file or folder.”
$FileSystemRights=[System.Security.AccessControl.FileSystemRights]"FullControl"
“Next, we are setting whether this right is allowed or denied.”
$AccessControlType =[System.Security.AccessControl.AccessControlType]"Allow"
“Next, we’re going to specify whether particular access control will inherit rights and how these rights propagate to child objects in a directory or files.”
$InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]"None"
$PropagationFlags = [System.Security.AccessControl.PropagationFlags]"None"
“Finally we need to specify the user or group they will apply to. In our case, this will be a UserID in Active Directory. It will be in the format of “REDMONDHD\UserId.”
$IdentityReference=’REDMONDHS\STUDENT169”
“Sounds like you’ve encountered this once before BATCHman,” Cmdlet noted.
He shrugged. “I goofed one day. Before I was the BATCHman I once worked in a large network. I made a mistake. I learned,” he said grinning sheepishly.
“Next we build the FileSystemAccessRule object.”
$FileSystemAccessRule= = New-Object System.Security.AccessControl.FileSystemAccessRule ($IdentityReference, $FileSystemrRights, $InheritanceFlags, $PropagationFlags, $AccessControlType)
“Then finally we set the new Access rule in place.”
$Access.AddAccessRule($FileSystemAccessRule)
SET-ACL E:\HOME\Student169 $Access
Cmdlet thought. “So it looks like we’ll need to run a second Set-ACL because we have two permissions I see missing. Can I try setting those variables? I think I see the pattern they have to follow.”
Cmdlet looked at the other permission that would have been missing.
$FileSystemRights=[System.Security.AccessControl.FileSystemRights]"268435456"
$AccessControlType =[System.Security.AccessControl.AccessControlType]"Allow"
$InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
$PropagationFlags = [System.Security.AccessControl.PropagationFlags]"InheritOnly"
$IdentityReference=’REDMONDHS\STUDENT169”
“Dead on the nose, Cmdlet! Now, quick! We have the answer. Because each folder name is the same as a UserID, we can leverage that. We’ll use Get-ChildItem, grab the FolderName, and build the username from that, applying the security as we go along.”
$HomeFolders=GET-CHILDITEM E:\HOME
Foreach ( $Folder in $HomeFolders )
{
$Username=’REDMONDHS\’+$Folder.Name
$Access=GET-ACL $Folder
$FileSystemRights=[System.Security.AccessControl.FileSystemRights]"268435456"
$AccessControlType =[System.Security.AccessControl.AccessControlType]"Allow"
$InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
$PropagationFlags = [System.Security.AccessControl.PropagationFlags]"InheritOnly"
$IdentityReference=$Username
$FileSystemAccessRule= = New-Object System.Security.AccessControl.FileSystemAccessRule ($IdentityReference, $FileSystemrRights, $InheritanceFlags, $PropagationFlags, $AccessControlType)
$Access.AddAccessRule($FileSystemAccessRule)
SET-ACL $Folder $Access
$FileSystemRights=[System.Security.AccessControl.FileSystemRights]"FullControl"
$AccessControlType =[System.Security.AccessControl.AccessControlType]"Allow"
$InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]"None"
$PropagationFlags = [System.Security.AccessControl.PropagationFlags]"None"
$FileSystemAccessRule= = New-Object System.Security.AccessControl.FileSystemAccessRule ($IdentityReference, $FileSystemrRights, $InheritanceFlags, $PropagationFlags, $AccessControlType)
$Access.AddAccessRule($FileSystemAccessRule)
SET-ACL $Folder $Access
}
They quickly ran the script on the thousands of user folders on the server. Moments later, peace was restored. Flustered and happy, the principal quickly thanked BATCHman and Cmdlet. Too busy with a zoo full of kids, he had to head straight back to work.
Moments later, they were back in the BATCHcave. A long month of crime fighting, BATCHman sat back to relax. Cmdlet was playing on the computer with Windows PowerShell and a new strange toy.
“Hey, little buddy, that looks cool! What are you playing with?”
“A used teleporter I picked up on eBay. It came with a very early alpha version of a Windows PowerShell module. It’s pretty cool and I…”
BATCHman had only just looked over Cmdlet’s shoulder when he burst out “No. You didn’t—wait…”, seeing the one-liner before they vanished into the night.
GET-PERSON –name ‘BATCHman’,’Cmdlet’ | INVOKE-TELEPORT –random
BATCHman and Cmdlet have left the building. I want to thank Sean Kearney for writing a tremendous series of fun, entertaining, and educational articles. Tomorrow, I begin a week of random topics that should be quite interesting.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy