jtokach
|
(Seasoned Scripter)
|
2003-12-15 08:07 PM
|
|
|
|
|
Using WMI to set ownership
|
|
Hey all,
I've done some investigating into settings directory ownership through WMI rather than FSO. There is very little VB type code out there, and none in the SDK. Specifically, the MS Technet scripting site skips right over these objects??? Anyone want to help out on this?
|
|
Re: Using WMI to set ownership
|
|
See for example NEWS: ownership of files and direcotry or NEWS: Re: TakeOwnerShip: Attn Scott McNairy
|
jtokach
|
(Seasoned Scripter)
|
2003-12-15 08:23 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Hmmm... What's starting to scare me is that most of the code I've seen offers methods to "take" ownership rahter than "assign" it to another user... This project may quickly go belly up.
|
|
Re: Using WMI to set ownership
|
|
I have an EXE to recursively set ownership on directories and files. It is not currently posted to my web site as I have not tested it extensively. I could email a copy to you if you want to give it whirl.
|
jtokach
|
(Seasoned Scripter)
|
2003-12-15 08:32 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Howard, I'm going to keep that in mind. I wanted to stay away from subinacl and xcacls, etc. in favor of using COM. We'll see where this leads and punt if necessary.
|
|
Re: Using WMI to set ownership
|
|
Does not use subinacl, xcalcs, etc. This is pure Perl and Win32 API.
Usage: SetOwner c:\directoryA domain\user
|
jtokach
|
(Seasoned Scripter)
|
2003-12-15 09:56 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
I've found something. MSDN link to vbs code What, I'm not sure yet. I can decipher everything, I'm assuming this is bitwise, but have no idea how it's generated:
Code:
wmiAce.AccessMask = 131072
|
|
Re: Using WMI to set ownership
|
|
This should help: Win32_ACE
|
jtokach
|
(Seasoned Scripter)
|
2003-12-15 10:54 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Indeed!
Here's where I'm at. The line 18 and 27 conversions from VBS don't seem to be working properly. Does the syntax need to follow different guidelines in kix?
Code:
Break On ; Connect to WMI and get the file security object for the testfolder directory $wmiFileSecSetting = GetObject ("winmgmts:Win32_LogicalFileSecuritySetting.path='c:\\temp'")
; Use the Win32_LogicalFileSecuritySetting Caption property to create a simple header before ; dumping the discretionary access control list (DACL).
? "Caption: " $wmiFileSecSetting.Caption ? "ControlFlags: " $wmiFileSecSetting.ControlFlags ? "Description: " $wmiFileSecSetting.Description ? "OwnerPermissions: " $wmiFileSecSetting.OwnerPermissions ? "Path: " $wmiFileSecSetting.Path ? "SettingID: " $wmiFileSecSetting.SettingID ? ?
; Obtain existing security descriptor for folder $wmiFileSecSetting.GetSecurityDescriptor(wmiSecurityDescriptor) If @error <> 0 ? "GetSecurityDescriptor failed" + @crlf + @Error + @crlf + @SError Exit Else ? "GetSecurityDescriptor suceeded" ? EndIf
$wmiOwner = wmiSecurityDescriptor.Owner
? "Win32_SecurityDescriptor" ? "------------------------" ? "Owner Name: " $wmiOwner.Name ? "Owner SIDString: " $wmiOwner.SIDString ? "Owner Domain: " $wmiOwner.Domain
|
|
Re: Using WMI to set ownership
|
|
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/setsecuritydescriptor_method_in_class_win32_logicalfilesecuritysetting.asp staest that in Quote:
uint32 GetSecurityDescriptor( Win32_SecurityDescriptor Descriptor );
Descriptor is actually Quote:
Descriptor [out] Expression that resolves to an instance of Win32_SecurityDescriptor
which mean that the return parameter is actually in wmiSecurityDescriptor, thus this should be a variable and I am not sure whether Kixtart even supports this way of returning parametrs, which seems to be ByVal instead of ByRef. So, might not be doable.
|
jtokach
|
(Seasoned Scripter)
|
2003-12-15 11:28 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Yeah, this is pretty much out of my league. Shawn or Chris can you guys confirm?
On another note, got this from the SDK. There seems to be many other ways to call methods. But, like I said, this is trial and error for me with little logic and less understanding of why. Tell me if you can see anything in here worth following up on.
Code:
'******************************************************************* ' Name : CreateShare.vbs ' ' Purpose : This example creates a new share and sets the ' security descriptor for the new share. '******************************************************************** '*** Connect to WMI and set security settings. ****** '*** You should substitute the name of the remote system for "\\myserver" *** Set objservices = GetObject("WINMGMTS:" _ & "{impersonationLevel=impersonate,(Security)}" _ & "!\\myserver\ROOT\CIMV2")
'*** Get the Win32_SecurityDescriptor class and spawn a new instance **** Set objclass = objservices.Get("Win32_SecurityDescriptor") Set objSecDescriptor = objclass.SpawnInstance_() '****** Prepare the security descriptor for the new share ****** objSecDescriptor.Properties_.Item("ControlFlags") = 4 Set ACE1 = SetACE(objservices, 2032127, _ 3, _ 0, _ SetTrustee(objservices, "myserver", _ "user1", _ Array(1, 5, 0, 0, 0, 0, 0, 5, 21, _ 0, 0, 0, 160, 101, 207, 126, _ 120, 75, 155, 95, 231, 124, _ 135, 112, 119, 238, 0, 0))) Set ACE2 = SetACE(objservices, 2032127, _ 3, _ 0, _ SetTrustee(objservices, Null, _ "EVERYONE", _ Array(1, 1, 0, 0, 0, 0, 0, 1, 0, _ 0, 0, 0))) objSecDescriptor.Properties_.Item("DACL") = Array(ACE1, ACE2) '************************ Create the new share ********************* Set objShare = objservices.Get("Win32_Share") Set objInParam = objShare.Methods_("Create").InParameters.SpawnInstance_() objInParam.Properties_.Item("Access") = objSecDescriptor objInParam.Properties_.Item("Description") = "New share created by WMI script" objInParam.Properties_.Item("Name") = "NewShare" objInParam.Properties_.Item("Path") = "C:\temp" objInParam.Properties_.Item("Type") = 0 'objInParam.Properties_.item("MaximumAllowed") = 10 'optional - default is 'max allowed' 'objInParam.Properties_.item("Password") = "Password" 'optional - default is no password '************************ Execute the method ********************** Set objOutParams = objShare.ExecMethod_("Create", objInParam) If objOutParams.ReturnValue = 0 Then wscript.echo "Share created successfully" Else If objOutParams.ReturnValue = 22 Then wscript.echo "Share may already exist" Else wscript.echo "Unable to create share, return value was : " _ & objOutParams.ReturnValue End If End If
'************************* HELPER FUNCTIONS ********************* Function SetTrustee(objservices, strDomain, strName, SID) Set objTrustee = objservices.Get("Win32_Trustee").SpawnInstance_ objTrustee.Domain = strDomain objTrustee.Name = strName objTrustee.Properties_.Item("SID") = SID Set SetTrustee = objTrustee End Function
Function SetACE(objservices, AccessMask, AceFlags, AceType, objTrustee) Set objAce = objservices.Get("Win32_Ace").SpawnInstance_ objAce.Properties_.Item("AccessMask") = AccessMask objAce.Properties_.Item("AceFlags") = AceFlags objAce.Properties_.Item("AceType") = AceType objAce.Properties_.Item("Trustee") = objTrustee Set SetACE = objAce End Function '******************************************************************
|
|
Re: Using WMI to set ownership
|
|
You might want to search the BBS for this. I think we had a discussion of rewriting the "set acls" VBS code that Microsoft made available with KiXtart code.
|
Shawn
|
(KiX Supporter)
|
2003-12-16 01:56 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
This line here:
$wmiFileSecSetting.GetSecurityDescriptor(wmiSecurityDescriptor)
is a Kixtart killer - was reading-up on this on MSDN and the GetSecurityDescriptor method takes a single [out] parameter. afaik Kixtart doesn't support this. I tried faking it by passing an initialized security descriptor object to it - no worky (although it didn't complain about it either).
|
jtokach
|
(Seasoned Scripter)
|
2003-12-16 05:02 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
I'm on a never say die kick. From the SDK: Quote:
GetSecurityDescriptor(Descriptor) This method gets the properties and embedded objects of a descriptor object that you provide as a input parameter. If the method is successful, you can examine the properties of the descriptor object to determine the specific security settings for the file.
Now come on. By definition, shouldn't I be able to pass a variable that receives the new object???
|
|
Re: Using WMI to set ownership
|
|
Nope.
The results of GetSecurityDescriptor(Descriptor) is in Descriptor.
Code:
rc = GetSecurityDescriptor(Descriptor)
Thus, you have to pass a variable into the GetSecurityDescriptor() function as a ByRef in order for the function to return the results in Descriptor. KiXtart does not support this type of passing variables into COM objects, it only supports the ByVal passing, which essentially copies the value into the function. The ByRef passes the reference to the value into the function which gives the function the ability to update said reference so that once the funciton exits the referenced variable contaisn the new value.
We already requested a couple of times to include ByRef passing as this would enable you to pass e.g. three parameters into a funciton and have the function return with updated values in these three variables. This would save the kludge of using arrays to return multiple parameters out of a UDF.
Code:
; demo code
$a=1
$b=2
$c=3
? $a
? $b
? $c
$rc=byreffun($a, %b, $c)
? $a
? $b
? $c
function byreffun(ByRef $var1, ByRef $var2, ByRef $var3)
$var1='aaa'
$var2='bbb'
$var3='ccc'
endfunction
The output of this script would beCode:
1
2
3
aaa
bbb
ccc
|
jtokach
|
(Seasoned Scripter)
|
2003-12-16 05:51 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
My C is sketchy at best but this sounds like a pointer.
I was hoping that a function could be called as Descriptor that would receive the object. Such as:
Code:
$rt=$wmiFileSecSetting.GetSecurityDescriptor(CreateObject("Win32_SecurityDescriptor.$foo"))
Really grasping at straws here as you can see.
|
|
Re: Using WMI to set ownership
|
|
Yes, it's like passing a pointer instead of a value in C.
And no, your code won't work as KiXtart just does not support it.
|
Shawn
|
(KiX Supporter)
|
2003-12-16 06:40 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Jim - here's the code I was playing with last night. Basically trying to create an "blank" instance of Win32_SecurityDescriptor and passing that to the function. You can tell that an object was indeed created. And when one queries the ControlFlags property it returns success (but I guess since its not a real instance of a security descriptor (ie a blank one) that no flags are present. If you substitute a bad property name, you do get an error - so definitetly talking to a real object here. But the passing out from GetSecurityDescriptor still doesn't work. tbh - don't think OUT parms work this way. If this was an IN/OUT parm it would probably work.
Code:
Break On $wmiFileSecSetting = GetObject ("winmgmts:Win32_LogicalFileSecuritySetting.path='c:\\temp'") $wmiSecurityDescriptor = GetObject ("winmgmts:Win32_SecurityDescriptor") ?"GetObject = " + @SERROR if $wmiSecurityDescriptor ? "ControlFlags=" + $wmiSecurityDescriptor.ControlFlags ? "QueryControlFlags = " + @SERROR endif $= $wmiFileSecSetting.GetSecurityDescriptor( $wmiSecurityDescriptor ) ? "GetSecurityDescriptor = " + @SERROR
|
jtokach
|
(Seasoned Scripter)
|
2003-12-17 12:07 AM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Shawn, why doesn't this work???
Code:
$Class = $wmiFileSecSetting.Get("Win32_SecurityDescriptor") $wmiSecurityDescriptor = $Class.SpawnInstance_()
|
Shawn
|
(KiX Supporter)
|
2003-12-17 01:39 AM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
I just traversed the inheritance tree from Win32_LogicalFileSecuritySetting that inherits from Win32_SecuritySetting which inherits from CIM_Setting but I see no support for reflection here with this class, like using get and put. But then again, I could be totally off base here.
-Shawn
|
|
Re: Using WMI to set ownership
|
|
I still think it boils down to KiXtart not supporting ByRef in the COM-automation aprt of the code. Thus, even spawning another instance will not work as the COM implementation cannot return values.
|
Shawn
|
(KiX Supporter)
|
2003-12-17 02:29 AM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Wonder if the script-friendly ADsSecurity DLL can be of any assistance here. It's pretty sophisticated.
|
|
Re: Using WMI to set ownership
|
|
I see an opportunity...but it won't be WMI
|
Shawn
|
(KiX Supporter)
|
2003-12-17 04:07 AM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
what you got in mind hoby ?
|
|
Re: Using WMI to set ownership
|
|
Well I can already set owner via Perl EXE. I can see if it can be added to HABobjects.dll. It won't be WMI but it may be KiXtart COM. I have been exploring a new Perl Module not yet public that handles most Win32 security including a definable recursor routine.
I always wanted to provide COM access to DACL, ACLs, ACE'a etc. If I get some additional time I may be able to provide something to test in a week or two.
|
Shawn
|
(KiX Supporter)
|
2003-12-17 04:21 AM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
hmmm, and it would be extra-special nice if you could make it easy to use - I don't know about you, but I think these WMI and ADsSecurity objects are terribly overly complicated.
|
|
Re: Using WMI to set ownership
|
|
Do I ever make things overly complited?
|
jtokach
|
(Seasoned Scripter)
|
2003-12-17 05:11 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Shawn, here's the ASP code where it's written using get:
Code:
'*** Get Win32_SecurityDescriptor class and create an instance of it ***
Set oClass = oConnectCIMv2.Get("Win32_SecurityDescriptor")
Set oSecDescriptor = oclass.SpawnInstance_()
'*** End Get Win32_SecurityDescriptor class and create an instance of it ***
'*** Prepare the security descriptor ***
'A set the control flags property of the security descriptor
'this value designates a set of control bits that qualify the
'meaning of a security descriptor or its individual members.
'a value of 4 (SE_DACL_PRESENT) indicates a security descriptor
'containing a DACL.
oSecDescriptor.Properties_.Item("ControlFlags") = SE_DACL_PRESENT
Set oClass = Nothing
'*** End Prepare the security descriptor ***
'*** Add a new ACE to the DACL ***
Set ACE = SetACE(oConnectCIMv2, sPermission, _
CUSTCON_ACE_INHERIT, _
ACETYPE_ACCESS_ALLOWED, _
SetTrustee(oConnectCIMv2, _
sDomain, _
sAccountName, _
sidval))
'build the array containing all ACEs. In this case, one ACE is being
'added to the security descriptor.
oSecDescriptor.Properties_.Item("DACL") = Array(ACE)
'clean up
Set ACE = Nothing
'*** End Add a new ACE to the DACL ***
'*** Modify the security descriptor ***
Set oDir = oConnectCIMv2.Get("Win32_Directory='" & sHomePath & "'")
Set oInParam = oDir.Methods_("ChangeSecurityPermissions"). _
InParameters.SpawnInstance_()
oInParam.Properties_.Item("Option") = CHANGE_DACL_SECURITY_INFORMATION
oInParam.Properties_.Item("SecurityDescriptor") = oSecDescriptor
oSecDescriptor.Properties_.Item("ControlFlags") = CUSTCON_ALLOW_INHERIT
'*** End Modify the security descriptor ***
'*** Execute the method ***
Set oOut = oDir.ExecMethod_("ChangeSecurityPermissions", oInParam)
If not oOut is nothing then
Response.Write "<li>The folder permissions were " & _
"successfully updated."
Else
Response.Write "<li class = warning>The folder permissions were " & _
"not successfully applied to the directory. "
End If
Regarding complication, I found an opensource tool that's miles ahead of subinacl and doesn't suffer the dreaded "ACL reodering". SetACL It, like subinacl, is not exactly user friendly. They developed a front end to write command lines. They're developing an ActiveX dll, so again we're SOL. Anyway, point is, the architecture of the SD is insane. Simplifying it is not possible. Sounds like a challenge Howard! =)
|
|
Re: Using WMI to set ownership
|
|
Just to clear the air about subinacl. Only some older versions of this tool have the ACL order issue. The newest version that I have no longer supports NT4.
I use version 2.6.0.1397 for NT4 and version 4.0.3.1615 for W2K and XP.
I will tried to put some time in on the security COM objects. What specifically do you want to do first?
|
Shawn
|
(KiX Supporter)
|
2003-12-17 05:25 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Jim, can you post the entire code. Especially the part that creates the oConnectCIMv2 object. On a side note ... when I was playing around with this I got the feeling that Ruud has made some changes to Kixtart to support "special" hadling of the GET and PUT methods. I can't put my finger on it - just a gut feeling really - but it seems that Kixtart is treating these methods special - and may not be quite fully working 100% ...
Howard - weren't you involved in some sort of issue with get/put and working directly with Ruud on it ?
-Shawn
|
|
Re: Using WMI to set ownership
|
|
PutEx and GetEx were not working correctly.
COM Bug still unresolved in 4.22rc1
$Obj.PutEx issue
|
jtokach
|
(Seasoned Scripter)
|
2003-12-17 05:31 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
The properties of my subinacl doesn't contain version information??? It's from an early Win2k Reskit though. I wasn't aware that they fixed it. Last I saw in the MSKB, it still had the issue and M$ was aware of it. [Jim wipes the sweat off of his brow] Thank goodness M$ is aware! =P
As far as features, I'd like to see the ability to set ownership to another User ID.
|
jtokach
|
(Seasoned Scripter)
|
2003-12-17 05:36 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Shawn, here's the code. Howard's follow up explains all though.
Code:
<%@ Language=VBScript %>
<% Option Explicit On Error Resume Next %> <HTML> <HEAD> <META NAME="GENERATOR" Content="by Ethan Wilansky"> <LINK REL="STYLESHEET" HREF="stylesheet.css" TYPE="text/css"> </HEAD> <BODY>
<%
' ------------------------- CONSTANT DEFINITIONS ------------------------------
'*** Security related constants used in the script ***
'ACE flags Const OBJECT_INHERIT_ACE = 1 Const CONTAINER_INHERIT_ACE = 2 Const CUSTCON_ACE_INHERIT = 3
'ACE types Const ACETYPE_ACCESS_ALLOWED = 0 Const ACETYPE_ACCESS_DENIED = 1 'Const
'Access masks Const CUSTCON_FULL_CONTROL = 2032127 Const CUSTCON_CHANGE = 1245631 Const CUSTCON_READ = 1179785
'Security descriptor control flag Const SE_DACL_PRESENT = 4 Const SE_DACL_AUTO_INHERITED = 1024 Const SE_SELF_RELATIVE = 32768 Const CUSTCON_ALLOW_INHERIT = 33796
'This constant is for the ChangeSecurityPermission method. 'An option value of 4 in this method means change DACL information. 'The values in the current version of the WMI sdk are wrong. 'The legal values are 0, 2, 4 and 8. Const CHANGE_DACL_SECURITY_INFORMATION = 4
' --- END CONSTANT DEFINITIONS ---
' --------------------------- GLOBAL VARIABLES --------------------------------
Dim sFileServer, sDomainController, sNameSpacePath, Sidval, CheckVarType Dim oFso, bFol, bParentPath, sParentPath, sDirectoryName, iLength, sHomePath Dim oConnectLDAP, oConnectCIMv2 Dim sPath, sAccountName, sDomain, sPermission Dim oClass, oSecDescriptor, ACE Dim oDir, oInParam, oOut Dim iRetVal, oMethod, oDescriptor, oSecuritySettings
' --- END GLOBAL VARIABLES ---
' ----------------------------- PROCEDURES ------------------------------------ 'Check for the parent folder Sub CheckForFolder() 'local variables Dim sDriveLetter, iPruneLength, sRemainingPath
'Initialize sDriveLetter to the drive letter in sPath sDriveLetter = Left(sPath,1)
'Initialize sRemainingPath to sPath less the first two characters that 'represent the drive letter designation iPruneLength = iLength - 2 sRemainingPath = Right(sPath, iPruneLength)
'Check to see if the pathspec exists before continuing sParentPath = "\\" & sFileServer & "\" & sDriveLetter & "drive$" & _ sRemainingPath bParentPath = oFso.FolderExists(sParentPath) End Sub
'Check for or create the home folder Sub CheckOrCreateHomeFolder() Dim oCreateFolder, sDriveLetter, sRemainingPath
'Create a UNC and assign it to the sDirectoryName variable. sDirectoryName = sParentPath & "\" & sAccountName 'Check to see if the folder exists bFol = oFso.FolderExists(sDirectoryName)
If bFol = False Then
set oCreateFolder = oFso.CreateFolder(sDirectoryName)
End If 'clean up Set oCreateFolder = Nothing End Sub
'Adjust the path if the operator entered a backslash at the end of the path Sub AdjustPathSpec()
iLength = Len(sPath)
If Right(sPath,1) = "\" Then iLength = iLength - 1 sPath=Left(sPath,iLength)
End If End Sub
'Create an entry form Sub Form %>
<h3>Create Home Folders and Set Permissions</h3> <p>Use this form to create and set permissions for home directories using the FileSystemObject and WMI.</p> <FORM ACTION="HomeFolderPerms.asp" METHOD=post name=FeedBackForm> <table border=0 width=520px> <tr> <td nowrap> User account domain: </td> <td align=left> <!--Replace the options here with the names of your domains--> <SELECT ID=SelectList1 name=DomainName> <OPTION selected>DOMAIN01</OPTION> <OPTION>DOMAIN02</OPTION> </SELECT> </td> <td width=100px> </td> </tr> <tr> <td> Local domain controller: </td> <td align=left> <!--Replace the name value for this field with the name of a local domain controller--> <INPUT type="text" id=Text1 name=DomainController value=SERVER1> </td> <td width=100px> </td> </tr> <tr> <td class = definition colspan=3>The name of a local domain controller containing the user account. </td> </tr> <tr> <td> User account name: </td> <td align=left> <INPUT type="text" id=textinput2 name=UserAccountName> </td> <td width=100px> </td> </tr> <tr> <td> Server name: </td> <td align=left> <!--Replace the options here with the names of your home directory servers--> <SELECT ID=SelectList2 name=ServerName> <OPTION selected>SERVER1</OPTION> <OPTION>SERVER2</OPTION> </SELECT> </td> <td width=100px> </td> </tr> <tr> <td class=definition colspan=3> This is the server that will contain the user's home directory. </td> </tr> <tr> <td nowrap> Path to parent directory: </td> <td align=left> <INPUT type="text" id=textinput3 name=PathSpec value=e:\home> </td> <td width=100px> </td> </tr> <tr> <td class = definition colspan=3> This is the full physical path on the server, including the drive letter. </td> </tr> </table> <b>Permissions:</b> <INPUT ID=RADIO type="radio" id=radio1 name=permission value=Read> Read <INPUT type="radio" checked id=Radio2 name=permission value=Change> Change <INPUT type="radio" id=Radio3 name=permission value=FullControl> Full Control <p class = definition>Select the permission to assign the user account for the directory.</p> <p><INPUT type="checkbox" checked name="inherit" ID=Checkbox1> Allow inheritable permissions from parent to propagate to this directory.</p> <INPUT type="submit" value="Submit" id=submit name=submit> <INPUT type="reset" value="Reset" id=reset name=reset> </FORM> <% End Sub
' --- END PROCEDURES ---
' ------------------------ SERVER-SIDE FUNCTIONS ------------------------------
'Determine the SID of a user in the Active Directory Function QuerySid(sAccountName) 'Local variables Dim ServiceSet, Item Set ServiceSet = oConnectLDAP.ExecQuery _ ("SELECT DS_objectSID FROM ds_user " & _ " WHERE ds_samaccountname ='" & sAccountName & "'") For Each Item In ServiceSet QuerySid = (Item.DS_objectSID.value) Next 'Clean up Set ServiceSet = Nothing
End Function
'Prepare the trustee information for the ACE
Function SetTrustee(oConnectCIMv2, sDomain, sAccountName, SID) 'Declare any local variables Dim oTrustee
Set oTrustee = oConnectCIMv2.Get("Win32_Trustee").SpawnInstance_
oTrustee.Domain = sDomain
oTrustee.Name = sAccountName
oTrustee.Properties_.Item("SID") = SID
Set SetTrustee = oTrustee 'clean up Set oTrustee = Nothing
End Function
'Prepare the ACE for the DACL
Function SetACE(oConnectCIMv2, AccessMask, AceFlags, AceType, oTrustee)
'Declare any local variables Dim oAce
Set oAce = oConnectCIMv2.Get("Win32_Ace").SpawnInstance_
oAce.Properties_.Item("AccessMask") = AccessMask
oAce.Properties_.Item("AceFlags") = AceFlags
oAce.Properties_.Item("AceType") = AceType
oAce.Properties_.Item("Trustee") = oTrustee
Set SetACE = oAce 'clean up Set oAce = Nothing
End Function
' --- END SERVER-SIDE FUNCTIONS ---
%> <!-----------------------------CLIENT-SIDE FUNCTIONS-------------------------->
<SCRIPT LANGUAGE="VBScript"> <!-- Function FeedbackForm_OnSubmit() Dim iNumeric, sType 'Disallow submit until the form fields have been validated. FeedbackForm_OnSubmit = False
'Get a reference to the form. Set theForm = Document.FeedbackForm
'First, check for the domain controller name value. If Trim(theForm.DomainController.Value) = "" Then MsgBox "Enter the name of a domain controller.", vbCritical, "Input Required" theForm.DomainController.Focus Else 'Next, check for the user account name value. If Trim(theForm.UserAccountName.Value) = "" Then MsgBox "Enter a user account name.", vbCritical, "Input Required" theForm.UserAccountName.Focus Else 'Next, check for the path value. If Trim(theForm.PathSpec.Value) = "" Then MsgBox "Enter the parent directory path.", vbCritical, "Input Required" theForm.PathSpec.Focus Else 'Next, check that the path spec. value is in the correct format. GetValue = theForm.PathSpec.Value If Mid(GetValue,2,2) <> ":\" Then MsgBox "The form of this input is: drive_letter:\path", _ vbCritical, "Invalid Path Specification" theForm.PathSpec.Focus Else 'Continue with submission. FeedbackForm_OnSubmit = True End If End If End If
End If
End Function --> </SCRIPT>
<!--- END CLIENT-SIDE FUNCTIONS --->
<% ' ---------------------------- MAIN SCRIPT BODY -------------------------------
'Determine whether to load the blank form or validate the form, create the home 'directory if it isn't already there and set permissions on the directory. Response.Write "<BODY>"
'*** Form call logic ***
If Request.Form("UserAccountName") = "" _ or Request.Form("DomainController") = "" _ or Request.Form("PathSpec") = "" Then Call Form
'*** Data initialization ***
Else 'initialize the variables required in the script. sDomain=Request.Form("DomainName") sAccountName=Request.Form("UserAccountName") sFileServer=Request.Form("ServerName") sDomainController=Request.Form("DomainController") sPath=Request.Form("PathSpec") 'Adjust the pathspec so that if the operator adds 'a backslash at the end of the pathspec, remove it Call AdjustPathSpec() 'initialize the path to the home folder sHomePath=sPath & "\" & sAccountName 'initialize the permission to grant Select Case Request.Form("Permission") Case "Read" sPermission = CUSTCON_READ Case "Change" sPermission = CUSTCON_CHANGE Case Else sPermission = CUSTCON_FULL_CONTROL End Select '*** End Data intialization *** '*** WMI Connection Strings ***
'connect to the CIMv2 namespace on the appropriate remote server sNameSpacePath = "\root\cimv2"
Set oConnectCIMv2 = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}" _ & "!\\" & sFileServer & sNameSpacePath)
'connect to the LDAP namespace on a local domain controller sNameSpacePath = "\root\directory\LDAP" Set oConnectLDAP = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}" _ & "!\\" & sDomainController & sNameSpacePath) '*** End WMI Connection Strings *** '*** Get the SID if the user account exists *** 'initialize the variables used here. SidVal = QuerySid(sAccountName) CheckVarType = varType(SidVal) 'Clean up Set oConnectLDAP = Nothing 'A value of vbEmpty or 0 indicates that the SidVal variable is uninitialized 'and therefore, the user account was not found. If CheckVarType = vbEmpty Then Response.Write "<p>The user account you entered, <b>" & sAccountName & _ "</b>, cannot be found on <b>" & sDomainController & "</b>." & _ "You might not have the necessary permission to check the directory." & _ " <br>If you do have enough permissions, Press the <b>Back</b> button" & _ " and specify an existing user account on<b> " & _ sDomainController & "<b>.</p>" Response.End End If '*** End Get the SID if the user account exists ***
'*** File system operations ***
'Create an instance of the file system object and save 'a reference to it in the oFSO variable set oFso = CreateObject("Scripting.FileSystemObject")
bParentPath = "False" 'Call the sub procedure to see if the parent folder exists Call CheckForFolder() If bParentPath = False Then Response.Write "<p>The parent folder, <b>" & sPath & _ "</b>, cannot be found on <b>" & sFileServer & "</b>." & _ "You might not have the necessary permission to access the directory." & _ " <br>If you do have enough permission, press the <b>Back</b> button " & _ "and specify an existing parent folder on<b> " & _ sFileServer & "<b>.</p>" Response.End End If bFol = "False" 'Call the sub procedure to check for the home directory and create 'it if necessary. Call CheckOrCreateHomeFolder() If bFol = True Then Response.Write "<li>The home folder, " & sDirectoryName & _ ", already exists." Else Response.Write "<li>The folder, " & sDirectoryName & ", was created" End If 'clean up Set oFSO = Nothing '*** End file system operations ***
'*** Get Win32_SecurityDescriptor class and create an instance of it ***
Set oClass = oConnectCIMv2.Get("Win32_SecurityDescriptor")
Set oSecDescriptor = oclass.SpawnInstance_() '*** End Get Win32_SecurityDescriptor class and create an instance of it ***
'*** Prepare the security descriptor ***
'A set the control flags property of the security descriptor 'this value designates a set of control bits that qualify the 'meaning of a security descriptor or its individual members. 'a value of 4 (SE_DACL_PRESENT) indicates a security descriptor 'containing a DACL. oSecDescriptor.Properties_.Item("ControlFlags") = SE_DACL_PRESENT Set oClass = Nothing '*** End Prepare the security descriptor ***
'*** Add a new ACE to the DACL *** Set ACE = SetACE(oConnectCIMv2, sPermission, _ CUSTCON_ACE_INHERIT, _ ACETYPE_ACCESS_ALLOWED, _ SetTrustee(oConnectCIMv2, _ sDomain, _ sAccountName, _ sidval))
'build the array containing all ACEs. In this case, one ACE is being 'added to the security descriptor. oSecDescriptor.Properties_.Item("DACL") = Array(ACE) 'clean up Set ACE = Nothing '*** End Add a new ACE to the DACL *** '*** Modify the security descriptor *** Set oDir = oConnectCIMv2.Get("Win32_Directory='" & sHomePath & "'")
Set oInParam = oDir.Methods_("ChangeSecurityPermissions"). _ InParameters.SpawnInstance_()
oInParam.Properties_.Item("Option") = CHANGE_DACL_SECURITY_INFORMATION
oInParam.Properties_.Item("SecurityDescriptor") = oSecDescriptor
oSecDescriptor.Properties_.Item("ControlFlags") = CUSTCON_ALLOW_INHERIT '*** End Modify the security descriptor ***
'*** Execute the method ***
Set oOut = oDir.ExecMethod_("ChangeSecurityPermissions", oInParam)
If not oOut is nothing then
Response.Write "<li>The folder permissions were " & _ "successfully updated."
Else
Response.Write "<li class = warning>The folder permissions were " & _ "not successfully applied to the directory. " End If 'Clean up Set oDir = Nothing Set oInParam = Nothing Set oOut = Nothing
'*** End Execute the method *** '*** Reset the DACL to allow inheritance *** If Request.Form("inherit") = "on" Then 'Get the existing security descriptor and store it. Set oSecuritySettings = oConnectCIMv2. _ Get("Win32_LogicalFileSecuritySetting='" & sHomePath & "'")
'Clean up Set oConnectCIMv2 = Nothing If oSecuritySettings Is Nothing Then Response.Write "<li class = warning>Unable to retrieve the " & _ "Win32_LogicalFileSecurity Setting of " & sHomePath Else 'retrieve the descriptor and store it in oDescriptor iRetval = oSecuritySettings.getsecuritydescriptor(oDescriptor) If iRetval = 0 And Err.Number = 0 Then oSecDescriptor.ControlFlags = CUSTCON_ALLOW_INHERIT Set oMethod = oSecuritySettings.Methods_("SetSecurityDescriptor") Set oInParam = oMethod.inParameters.SpawnInstance_()
oInParam.Properties_.item("Descriptor") = oSecDescriptor
'Execute the method to reassign the security descriptor Set iRetVal = oSecuritySettings. _ ExecMethod_("SetSecurityDescriptor", oInParam)
With Response .Write "<li>" & sDomain & "\" & sAccountName & " has been granted " & _ Request.Form("Permission") & " permission to " & _ sHomePath & " on " & sFileServer & _ ".<li>Permissions from the parent folder are" & _ " inherited by this directory.<br>" .Write "<br><A HREF=HomeFolderPerms.asp>Return to the form.</a>" End With Else Response.Write "<li class = warning>Error# " & Err.Number & ": " _ & Err.Description & _ " occurred when retrieving the security descriptor" End If End If '*** End Reset the DACL to allow inheritance *** Else With Response .Write "<li>" & sDomain & "\" & sAccountName & " has been granted " & _ Request.Form("Permission") & " permission to " & _ sHomePath & " on " & sFileServer & "." & _ "<li>Permissions from the parent folder are NOT " & _ " inherited by this directory.<br>" .Write "<br><A HREF=HomeFolderPerms.asp>Return to the form</a>" End With End If 'Clean up Set oSecDescriptor = Nothing Set oSecuritySettings = Nothing Set oMethod = Nothing Set oInParam = Nothing Set iRetVal = Nothing End If
'*** End Form call logic ***
%> </BODY> </HTML>
|
|
Re: Using WMI to set ownership
|
|
I don't know what MS support knows - just sent a email to Premier to ask them what versions that have available. I get mine direct from the developer of SubInACL. Several of the current functions and ablilites like using an offline sam file were added per my request.
Use the "/help" switch on the command line.
C:\Data>\\bullpup\Integrate\SubInAcl\4.0.3.1615\subinacl /help
Code:
SubInAcl version 4, 0, 3, 1615
USAGE
-----
Usage :
SubInAcl [/option...] /object_type object_name [[/action[=parameter]...]
/options :
/outputlog=FileName /errorlog=FileName
/noverbose /verbose (default)
/notestmode (default=/notestmode) /testmode
/alternatesamserver=SamServer /offlinesam=FileName
/stringreplaceonoutput=string1=string2
/expandenvironmentsymbols (default) /noexpandenvironmentsymbols
/statistic (default) /nostatistic
/dumpcachedsids=FileName /separator=character
/applyonly=[dacl,sacl,owner,group]
/object_type :
/service /keyreg /subkeyreg
/file /subdirectories[=directoriesonly|filesonly]
/clustershare /kernelobject /metabase
/printer /onlyfile /process
/share /samobject
/action :
/display[=dacl|sacl|owner|primarygroup|sdsize|sddl] (default)
/setowner=owner
/replace=[DomainName\]OldAccount=[DomainName\]New_Account
/accountmigration=[DomainName\]OldAccount=[DomainName\]New_Account
/changedomain=OldDomainName=NewDomainName[=MappingFile[=Both]]
/migratetodomain=SourceDomain=DestDomain=[MappingFile[=Both]]
/findsid=[DomainName\]Account[=stop|continue]
/suppresssid=[DomainName\]Account
/confirm
/ifchangecontinue
/cleandeletedsidsfrom=DomainName[=dacl|sacl|owner|primarygroup|all]
/testmode
/accesscheck=[DomainName\]Username
/setprimarygroup=[DomainName\]Group
/grant=[DomainName\]Username[=Access]
/deny=[DomainName\]Username[=Access]
/sgrant=[DomainName\]Username[=Access]
/sdeny=[DomainName\]Username[=Access]
/revoke=[DomainName\]Username
/perm
/audit
/compactsecuritydescriptor
/pathexclude=pattern
/objectexclude=pattern
/sddl=sddl_string
|
jtokach
|
(Seasoned Scripter)
|
2003-12-17 05:44 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
I have access to the Premier site as well if you find a link. Running the /help still doesn't display any version info.
|
jtokach
|
(Seasoned Scripter)
|
2003-12-17 06:23 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Howard, from what I can see, the newer version of subinacl still lacks the ability to set inheritance. That's a nice feature found in SetACL
|
Les
|
(KiX Master)
|
2003-12-17 06:24 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Quote:
I'd like to see the ability to set ownership to another User ID.
SubInAcl can do that. I ran it against my users' home folders and set them as owners.
|
jtokach
|
(Seasoned Scripter)
|
2003-12-17 06:42 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
The original plan was to do this through scripting without an external binary.
|
Les
|
(KiX Master)
|
2003-12-17 07:02 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
I am aware of your aspirations and so sat on my hands until now but had to defend SubInAcl as you seemed to have the misconception it cannot give ownership to any user.
I am less a purist and more results (with the least effort) oriented. SubInAcl worked fine for me. In fact, I didn't even wrap it in a KiX script. I did a DIR /B >DIRLIST.TXT and then brought in into Excel. There, the line was all that was needed: Quote:
=CONCATENATE("subinacl /subdirectories \\server\home$\users\",A1,"\ /setowner=domain\",A1," >>Results.txt")
Copy the formula to all the cells and then copy the output to a DOS box, and Bob's your uncle. We do our whole AD migration the same way. 3000 users done and 3000 more to go!
|
jtokach
|
(Seasoned Scripter)
|
2003-12-17 08:35 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Les,
Seems like we're getting our wires crossed here. The only deficiencies that I pointed out in subinacl where that it use to have the problem of incorrectly ordering the ACL and that it couldn't set inheritance. I don't recall stating that it could not set ownership and in fact have used it in the past for this operation.
|
Les
|
(KiX Master)
|
2003-12-17 10:18 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Well, you're not the first to accuse me of having my wires crossed, but from what you said (andd I quote you), it is hard not to infer... Quote:
The properties of my subinacl doesn't contain version information??? It's from an early Win2k Reskit though. I wasn't aware that they fixed it. Last I saw in the MSKB, it still had the issue and M$ was aware of it. [Jim wipes the sweat off of his brow] Thank goodness M$ is aware! =P
As far as features, I'd like to see the ability to set ownership to another User ID.
Not sure why you say you would "like to see" something that already exists.
|
jtokach
|
(Seasoned Scripter)
|
2003-12-17 10:39 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Ahh, yes. Blame that on threaded view vs. flat. I intended to reply to Howard's question of what I'd like to see worked on first in the previous thread.
Hoby's thread Quote:
I will tried to put some time in on the security COM objects. What specifically do you want to do first?
Anyone else struggling with getting used to these damn threads?
|
|
Re: Using WMI to set ownership
|
|
Nope, I'm using the flat view. threaded can cause too much confusion as someone using the flat view will not realize the flow of replies.
|
|
Re: Using WMI to set ownership
|
|
Hi Everyone, you are going to hate me for digging this post up, but how was this left.
Was it decided that it cannot be done via WMI, and it is best to use SetACL.
Thanks
|
jtokach
|
(Seasoned Scripter)
|
2004-03-19 05:47 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
If you read further down it should say something about Kix not supporting the object methods.
|
|
Re: Using WMI to set ownership
|
|
Thanks Jim, got dizzy reading all the posts
|
jtokach
|
(Seasoned Scripter)
|
2004-03-19 06:06 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Tell me about it, this threading system complicates things...
|
|
Re: Using WMI to set ownership
|
|
Then display the posts in flat mode instead of threaded mode.
|
Arend_
|
(MM club member)
|
2008-02-01 02:18 PM
|
|
|
|
|
Re: Using WMI to set ownership
|
|
Draggin up this old post again, just to point these things out:
1. No KiX still doesn't support this type of call (Ruud?!?!) 2. AdsSecurity does NOT allow to SET control flags. 3. The new and improved AdsSecurityUtility doesn't allow SET control flags either.
Unfortunately to set Control flags you're going to need external .exe files or vbs.
Here is a small example to set inhertiance Flags on in vbs
Sub AllowInheritance(str_path)
Set objSecurity = GetObject("winmgmts:{(Security,Restore)}\\.\root\cimv2:Win32_LogicalFileSecuritySetting='" & str_path & "'")
'Get the Security Descriptor object (objSD)
objSecurity.GetSecurityDescriptor objSD
objSD.ControlFlags = 33796
'Write back the Security Descriptor
'j=objSecurity.SetSecurityDescriptor(objSD)
End sub
AllowInheritance("D:\test")
|