
IndiePendent79
New User
Feb 14, 2007, 8:32 AM
Post #1 of 2
(5800 views)
|
Using Perl with WMI to set folder level permissions
|
Can't Post
|
|
In an effort to automate LAN account creation I have designed a Perl script that will take specific information that is input by a user and create a "personal drive" on a network storage device and the automatically set the permissions on the folder so that the user can access it. Unfortunately, I am running into issue with not correctly adding the new ACE back to the existing security descriptor. I have found that it is unnecessary to create an array of the existing ACEs as they are all inherited and will be repopulated if a new array of the single new ACE is added. If anyone has any experience with using WMI to set folder permissions in Perl ANY and ALL advice is welcome as I have reached a dead end with every solution I try. Here is the following applicable code for what I am attempting to accomplish:
use Win32::OLE::Variant; $Win32::OLE::Warn = 3; # ACE access mask, flag, and type constants our $ADS_ACCESSMASK_READ_WRITE_EXECUTE_DELETE = -536805376; our $ADS_ACCESSMASK_FULL = 268435456; our $ADS_ACEFLAG_UNKNOWN = 0x1; our $ADS_ACEFLAG_INHERIT_ACE = 0x2; our $ADS_ACEFLAG_INHERITED_ACE = 0x10; our $ADS_ACETYPE_ACCESS_ALLOWED = 0; our $ADS_ACETYPE_ACCESS_DENIED = 0x1; our $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = 0x5; our $ADS_ACETYPE_ACCESS_DENIED_OBJECT = 0x6; our $NTFS_MODIFY = 0x1245631; our $NTFS_FULL_CONTROL = 0x2032127; # get a SWbemLocator object my $objLocator = Win32::OLE->new('WbemScripting.SWbemLocator') or die "can't create locator object: ".Win32::OLE->LastError( )."\n"; # set the impersonate level to "impersonate" $objLocator->{Security_}->{impersonationlevel} = 3; $objLocator->{Security_}->{Privileges}->AddAsString("seRestorePrivileg +e"); my $server = "servername.domain.com"; # use it to get a an SWbemServices object my $objServices = $objLocator->ConnectServer($server, 'root\cimv2') or + die "can't create server object: ".Win32::OLE->LastError( )."\n"; my $path = "d:\\userdata\\user"; print "Win32_LogicalFileSecuritySetting.Path='$path'\n"; my $objDirectorySecSetting = $objServices->Get("Win32_LogicalFileSecur +itySetting.Path='$path'"); my $objSecDescriptor = Win32::OLE::Variant-> new (VT_DISPATCH|VT_BYREF +); my $retval = $objDirectorySecSetting->GetSecurityDescriptor($objSecDes +criptor); # Get the Win32_SecurityDescriptor from the variant. my $sd = $objSecDescriptor->Get(); print "$sd\n"; # Get the ACL, which is just an array of Win32_ACE objects. my @dacl = @{$sd->{'DACL'}}; #open local wmi instance my $wmi = Win32::OLE->GetObject('WinMgmts:{impersonationlevel=imperson +ate}!root/cimv2'); my $strName = "USER"; my $strDomain = "DOMAIN"; #create instance of Win32_Account bound to user (doing this so we can +get the user's SID) my $account = $wmi->Get('Win32_Account.Domain=\'' . $strDomain . '\',N +ame=\'' . $strName . '\''); #create instance of Win32_SID populated using account instance from ab +ove, this lets us get SID in different formats my $accountSID = Win32::OLE->GetObject('Winmgmts:{impersonationlevel=i +mpersonate}!root/cimv2:Win32_SID.SID=\'' . $account->SID . '\''); #create instance of Win32_Trustee and populate (note: uses Sid instanc +e from above) my $objTrustee = $wmi->Get("Win32_Trustee")->SpawnInstance_; $objTrustee->{Domain} = $strDomain; $objTrustee->{Name} = $strName; $objTrustee->{SID} = $accountSID->BinaryRepresentation; #Create instance of Win32_Ace and populate values (note: uses trustee +instance from above) my $newACE = $wmi->Get("Win32_Ace").Spawninstance_; $newACE->{AccessMask} = $NTFS_MODIFY; $newACE->{AceFlags} = $ADS_ACEFLAG_UNKNOWN | $ADS_ACEFLAG_INHERIT_ACE; $newACE->{AceType} = $ADS_ACETYPE_ACCESS_ALLOWED; $newACE->{Trustee} = $objTrustee; my $ACEArray; #Add the newACE above to the ACEArray push(@$ACEArray,$newACE); print "New ACE list:\n"; foreach my $ace (@ACEArray) { $trustee = $ace->{'Trustee'}; $acetype = $ace->{'AceType'}; $aceflag = $ace->{'AceFlags'}; $acemask = $ace->{'AccessMask'}; $name = $trustee->{'Name'}; print "Name: $name\n"; print "$acetype\n"; print "$aceflag\n"; print "$acemask\n"; } # Replace the DACL with the ACEArray containing the new ACE $sd->{DACL} = $ACEArray; #Write DACL back to security descriptor of the folder my $retval = $objDirectorySecSetting->SetSecurityDescriptor($sd); My main issue occurs when attempting to write the new security descriptor back out to the folder. Thanks, Derek
|