Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Using Perl with WMI to set folder level permissions

by IndiePendent79 (Initiate)
on Feb 14, 2007 at 16:22 UTC ( #599978=perlquestion: print w/replies, xml ) Need Help??

IndiePendent79 has asked for the wisdom of the Perl Monks concerning the following question:

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 = ""; # 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. Is this a WMI issue or a Perl issue also? Thanks, Derek

Replies are listed 'Best First'.
Re: Using Perl with WMI to set folder level permissions
by Anonymous Monk on Jul 16, 2007 at 12:32 UTC
    Regarding your yell for any hint or help at all: Why not use SubInACL (SubInACL.exe)?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://599978]
Approved by holli
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (4)
As of 2021-06-13 07:22 GMT
Find Nodes?
    Voting Booth?
    What does the "s" stand for in "perls"? (Whence perls)

    Results (54 votes). Check out past polls.