badgerbeard Posted March 12, 2010 Posted March 12, 2010 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)
PsaltyDS Posted March 12, 2010 Posted March 12, 2010 AAAAAaaaaaand there's a question in there...? Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
badgerbeard Posted March 12, 2010 Author Posted March 12, 2010 (edited) 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 Edited March 12, 2010 by badgerbeard
Developers Jos Posted March 12, 2010 Developers Posted March 12, 2010 Can you stop making new topics and stick to the original one you created? Will merge this with the first one and the duplicate has been removed. Jos SciTE4AutoIt3 Full installer Download page  - Beta files    Read before posting   How to post scriptsource   Forum etiquette Forum Rules  Live for the present, Dream of the future, Learn from the past.Â
badgerbeard Posted March 13, 2010 Author Posted March 13, 2010 Can you stop making new topics and stick to the original one you created?Will merge this with the first one and the duplicate has been removed.JosSorry, 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.
badgerbeard Posted March 13, 2010 Author Posted March 13, 2010 AAAAAaaaaaand there's a question in there...? Eventually....
badgerbeard Posted March 22, 2010 Author Posted March 22, 2010 (edited) 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! expandcollapse popup;$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) Edited March 22, 2010 by badgerbeard
Igzter Posted June 13, 2010 Posted June 13, 2010 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! expandcollapse popup;$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) That is extremely dangerous on a live filesystem with multiple users/applications if you do not make a filelock.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now