
badgerbeard
Members-
Posts
5 -
Joined
-
Last visited
Everything posted by badgerbeard
-
Setting DACL using WMI
badgerbeard replied to badgerbeard's topic in AutoIt General Help and Support
I've figured out a way of doing this if anyone's interested... Instead of spawning instances of the Win32_ACE and Win32_trustee, I just copy the existing objACE values to the dictionary object, then alter the last one to have the user name, SID etc that I want and tag that on the end of the dictionary, then overwrite the full DACL with the values in the dictionary array. Works like a charm! ;$realPath is local to server eg d:\home\username $objWMI = ObjGet("winmgmts:{(Security,Restore)}\\yourserver\root\CIMV2") Dim $objFolderSecuritySettings = $objWMI.get("Win32_LogicalFileSecuritySetting='"&$realPath&"'") Dim $objSD Dim $intRetVal = $objFolderSecuritySettings.GetSecurityDescriptor ($objSD) Dim $intControlFlags = $objSD.ControlFlags Dim $ACLUser DIM $PermissionBitMask = 1245695 ;<<<<like modify If $intControlFlags And $SE_DACL_PRESENT Then Dim $strMsg = "", $objACE Dim $arrACEs = $objSD.DACL $changed=0 For $objACE In $arrACEs $ACLUser = $objACE.Trustee.Domain & "\" & $objACE.Trustee.Name $strMsg &= $objACE.Trustee.Domain & "\" & $objACE.Trustee.Name & ", " & $objACE.AceFlags If $objACE.AceType = $ACCESS_ALLOWED_ACE_TYPE Then $strMsg &= @TAB & "Allowed:" & @CRLF ElseIf $objACE.AceType = $ACCESS_DENIED_ACE_TYPE Then $strMsg &= @TAB & "Denied:" & @CRLF EndIf if StringCompare($objace.Trustee.Name,$username,0)=0 Then ;user already in DACL $objACE.AccessMask = $PermissionBitMask ;change permissions $changed=$changed+1 endIf Next Else $strMsg = "No DACL present in security descriptor" EndIf $oDictionary =ObjCreate("Scripting.Dictionary") $key=0 For $objACE In $arrACEs If Not BitAND($objACE.AceFlags,16) Then $oDictionary.Add($key, $objACE) $key=$key+1 ;ConsoleWrite(">>>>>>"&$objace.Trustee.Domain & "\" & $objACE.trustee.name & " " & $objACE.Trustee.SIDString&@CRLF) EndIf ; ConsoleWrite(">>>>>>"&$objace.Trustee.Domain & "\" & $objACE.trustee.name & " " & $objACE.Trustee.SIDString&@CRLF) ; ConsoleWrite(">>>>>>"&vargettype($objACE.Trustee.SID)&@CRLF) Next if $changed = 0 Then ;user not found, need to add to the DACL $aAccount = _Security__LookupAccountName($domain&"\"&$username) $SID=$aAccount[0] $objWMI = ObjGet("winmgmts:\\.\root\cimv2") ;local connection, trusted $objSID=$objWMI.get("Win32_SID.SID='"&$SID&"'") ;Set the properties, overwrite last accessed ACE from above loop.... $objACE.AccessMask = $PermissionBitMask $objACE.Trustee.Domain = $objSID.ReferencedDomainName $objACE.Trustee.Name = $objSID.AccountName $objACE.Trustee.SID = $objSID.BinaryRepresentation $objACE.Trustee.SIDLength = $objSID.SidLength $objACE.Trustee.SIDString = $objSID.SID $objACE.AceType = 0 ;Allow $objACE.AceFlags = 3 ;Inheritance to sub-folders and files $oDictionary.Add($oDictionary.count, $objACE) EndIf ;overwrite current DACL with dictionary, will either amend existing user or add them if not already in DACL. $objSD.DACL = $oDictionary.items $intRetVal = $objFolderSecuritySettings.SetSecurityDescriptor ($objSD) -
Setting DACL using WMI
badgerbeard replied to badgerbeard's topic in AutoIt General Help and Support
Eventually.... -
Setting DACL using WMI
badgerbeard replied to badgerbeard's topic in AutoIt General Help and Support
Sorry, not sure how the first part-post happened! I was tidying the code, removing consolewrites etc and a few times hit tab to indent, but that jumps to the post/preview/cancel links, so must have hit one of them by accident then clicked on the back button without realising I'd posted. -
Setting DACL using WMI
badgerbeard replied to badgerbeard's topic in AutoIt General Help and Support
Hi all, hope someone can help... I'm converting a VB Script to Autoit. The VB Script is something I came across and adapted a few years ago that sets ACL on a network folder. The first part checks if the specified user already is listed, it alters the permissions, and that works in autoit. Here's that bit of code... #Include <Security.au3> Dim $SE_DACL_PRESENT = 0x4 Dim $server="SERVERNAME" Dim $username="AB12345" Dim $realPath="D:\USERS\"&"$username Dim $PermissionBitMask=1245695 ;like modify, plus allow delete folders and files $objWMI = ObjGet("winmgmts:{(Security,Restore)}\\"&$Server&"\root\CIMV2") Dim $objFolderSecuritySettings = $objWMI.get("Win32_LogicalFileSecuritySetting='"&$realPath&"'") Dim $objSD Dim $intRetVal = $objFolderSecuritySettings.GetSecurityDescriptor ($objSD) Dim $intControlFlags = $objSD.ControlFlags Dim $ACLUser If $intControlFlags And $SE_DACL_PRESENT Then Dim $arrACEs = $objSD.DACL For $objACE In $arrACEs if StringCompare($objace.Trustee.Name,$username,0)=0 Then $objACE.AccessMask = $PermissionBitMask endIf Next EndIf $intRetVal = $objFolderSecuritySettings.SetSecurityDescriptor ($objSD) If they aren't found the original VB script creates a new array using a dictionary object to copy the existing DACL explicit entries, then adds an entry for the new user. This works fine in the VB script, but I can't quite get it to work in autoit. Here's my attempt at the autoit conversion. $aAccount = _Security__LookupAccountName($domain&"\"&$username) $SID=$aAccount[0] $objWMI = ObjGet("winmgmts:") ;local connection, trusted $objSID=$objwmi.get("Win32_SID.SID='"&$SID&"'") $objTrusteeClass=$objwmi.get("Win32_Trustee") $objTrustee=$objTrusteeClass.SpawnInstance_() ;Set the properties $objTrustee.Domain = $objSID.ReferencedDomainName $objTrustee.Name = $objSID.AccountName $objTrustee.SID = $objSID.BinaryRepresentation $objTrustee.SidLength = $objSID.SidLength $objTrustee.SIDString = $objSID.SID ;Create a new blank Win32_ACE object $objACEClass = $objWMI.Get("Win32_ACE") $objACE2 = $objACEClass.SpawnInstance_() ;Set the properties $objACE2.AccessMask = $PermissionBitMask $objACE2.Trustee = $objTrustee $objACE2.AceType = 0 ;Allow $objACE2.AceFlags = 3 ;Inheritance to sub-folders and files $oDictionary =ObjCreate("Scripting.Dictionary") $key=0 For $objACE In $arrACEs If Not BitAND($objACE.AceFlags,16) Then ;not inherited, explicitly set $oDictionary.Add($key, $objACE) ;** $key=$key+1 EndIf Next $oDictionary.Add($key, $objACE2) ;** $objSD.DACL = $oDictionary.items ;*** $intRetVal = $objFolderSecuritySettings.SetSecurityDescriptor ($objSD) The problem is either with the way I'm adding to the dictionary array ( marked with **) or the assigning of the dictionary array to the DACL (***) And here's the original vb, (1) Get the SID has been replaced with _Security__LookupAccountName... '(1) Get the SID of the user or group account. 'Create a WMI object on the local computer (Assuming the local computer is in the 'same domain (or in a trusted domain) as the one specified Set objWMI = GetObject("winmgmts:\\.\root\cimv2") 'Get a collection of Users objects, using ExecQuery Set colUsers = objWMI.ExecQuery("SELECT * FROM WIN32_ACCOUNT WHERE Domain = '" & _ Domain & "' AND Name = '" & Username & "'") 'The collection should only have one user in it. Loop through the one user collection 'and create a user object For Each UserName in colUsers Set objUserName = Username Next 'Next, we need both the binary and string representation of the user's SID to create a new 'Win32_Trustee. objUser.SID only returns the string version. Create a Win32_SID object by 'referencing the objUser's SID Set objSID = objWMI.Get("Win32_SID.SID='" & objUserName.SID & "'") '(2) Create a new blank Win32_Trustee object, and set it's properties to the appropriate ' values 'Create a new blank Win32_Trustee object Set objTrusteeClass = objWMI.Get("Win32_Trustee") Set objTrustee = objTrusteeClass.SpawnInstance_() 'Set the properties objTrustee.Domain = objSID.ReferencedDomainName objTrustee.Name = objSID.AccountName objTrustee.SID = objSID.BinaryRepresentation objTrustee.SidLength = objSID.SidLength objTrustee.SIDString = objSID.SID '(3) Create a new blank Win32_ACE object, and set it's properties to the appropriate ' values. The Trustee property should point to the newly created Win32_Trustee 'Create a new blank Win32_ACE object Set objACEClass = objWMI.Get("Win32_ACE") Set objACE = objACEClass.SpawnInstance_() 'Set the properties objACE.AccessMask = PermissionBitMask objACE.Trustee = objTrustee objACE.AceType = 0 'Allow objACE.AceFlags = 3 'Inheritance to sub-folders and files '(4) Add the ACE to the DACL. This is the hard part, because to keep the existing ' ACEs means we have to resize the array. The DACL array is not a dynamic array, so ' the solution is to create a new array of the right size, copy the explicit contents ' of the existing DACL (and the new ACE) into it, and then replace the existing ' DACL with the new one. 'Create a Dictionary object (a hash). We're using a dictionary object, because it 'can be dynamically resized Set objDictionary = CreateObject("Scripting.Dictionary") 'Loop through the DACL array and populate the Dictionary object only with ACE objects 'that have EXPLICIT PERMISSIONS. This can be tested by checking the AceFlags property. 'If the 5th bit (16) is set to 1 then, the permission is inherited (See AceFlags 'description above. 'Doesn't matter what the Dictionary key is, The corresponding item is all that matters, 'being the ACE of the existing DACL. We just use i as the key here For i = LBound(objSD.DACL) to UBound(objSD.DACL) If NOT objSD.DACL(i).AceFlags AND 16 Then objDictionary.Add i, objSD.DACL(i) End If Next 'Add the new ACE. objDictionary.Add "Empty Key", objACE 'Use the items method to return a list of just the items, and overwrite the existing 'DACL with the new list of ACEs objSD.DACL = objDictionary.Items '(5) Finally, write back the Security Descriptor If objSecurity.SetSecurityDescriptor(objSD) = 0 Then SetPermissions = 0 Else SetPermissions = 1 Err.Clear End If -
Hi all, hope someone can help... I'm converting a VB Script to Autoit. The VB Script is something I came across and adapted a few years ago that sets ACL on a network folder. The first part checks if the specified user already is listed, it alters the permissions, and that works in autoit. Here's that bit of code... $objWMI = ObjGet("winmgmts:{(Security,Restore)}\\work\"&$Server&"\CIMV2") Dim $objFolderSecuritySettings = $objWMI.get("Win32_LogicalFileSecuritySetting='"&$realPath&"'") Dim $objSD Dim $intRetVal = $objFolderSecuritySettings.GetSecurityDescriptor ($objSD) Dim $intControlFlags = $objSD.ControlFlags Dim $ACLUser If $intControlFlags And $SE_DACL_PRESENT Then Dim $arrACEs = $objSD.DACL For $objACE In $arrACEs if StringCompare($objace.Trustee.Name,$username,0)=0 Then $objACE.AccessMask = $PermissionBitMask endIf Next Else $strMsg = "No DACL present in security descriptor" EndIf ;ConsoleWrite($strMsg) $intRetVal = $objFolderSecuritySettings.SetSecurityDescriptor ($objSD)