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

In reply to Using Perl with WMI to set folder level permissions by IndiePendent79

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.