Create user by script then CACLS home directory

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,

I have just created a HTA application that uses ADSI to add a new user to the domain, give the first name, last name and description.

This is based on the Scriptomatic tools from TechNet and scripts segments from the TechNet scripting centre.

Everything works great, except for setting the permissions on the home and profile directories.

Having found no scripting object I could use to set permissions, I resorted to the following.

set winShell = CreateObject("WScript.Shell")
winShell.Run "cacls " & profilepath & " /t /e /g " & username & ":F", 1, True

This sometimes works and sometimes doesn't (roughly 50/50). I get the error "No mapping between account names and security IDs was done".

I believe the problem is with the directory not being synchronized between the two Domain Controllers at the time I was attempting to run CACLS (so therefore CACLS was not seeing the user because it somehow managed to always see the other Domain controller, not the one on which the user was created).

If I wait a while before running CACLS, it runs fine. However, just waiting an arbitrary amount of time doesn't seem like a good method to me.

How do the built-in administration tools deal with this issue? Does anyone know of a better way? What determines which DC the ADSI script and the CACLS command looks at?

We're using Windows 2000 Server with two domain controllers, running the script from a Windows 2000 Pro machine.
 
Mr Brownstone said:
Hi,

I have just created a HTA application that uses ADSI to add a new user to the domain, give the first name, last name and description.

This is based on the Scriptomatic tools from TechNet and scripts segments from the TechNet scripting centre.

Everything works great, except for setting the permissions on the home and profile directories.

Having found no scripting object I could use to set permissions, I resorted to the following.

set winShell = CreateObject("WScript.Shell")
winShell.Run "cacls " & profilepath & " /t /e /g " & username & ":F", 1, True

This sometimes works and sometimes doesn't (roughly 50/50). I get the error "No mapping between account names and security IDs was done".

I believe the problem is with the directory not being synchronized between the two Domain Controllers at the time I was attempting to run CACLS (so therefore CACLS was not seeing the user because it somehow managed to always see the other Domain controller, not the one on which the user was created).

If I wait a while before running CACLS, it runs fine. However, just waiting an arbitrary amount of time doesn't seem like a good method to me.

How do the built-in administration tools deal with this issue? Does anyone know of a better way? What determines which DC the ADSI script and the CACLS command looks at?

We're using Windows 2000 Server with two domain controllers, running the script from a Windows 2000 Pro machine.


You may be better off posting this question in one of the scripting
newsgroups. But..., I have scripted setting permissions using
AdsSecurity.dll.

'---------------------------------------
'*******************************
'** ADS_RIGHTS_ENUM constants **
'*******************************
Const ADS_RIGHT_DELETE = &h10000
Const ADS_RIGHT_READ_CONTROL = &h20000
Const ADS_RIGHT_WRITE_DAC = &h40000
Const ADS_RIGHT_WRITE_OWNER = &h80000
Const ADS_RIGHT_SYNCHRONIZE = &h100000
Const ADS_RIGHT_ACCESS_SYSTEM_SECURITY = &h1000000
Const ADS_RIGHT_GENERIC_READ = &h80000000
Const ADS_RIGHT_GENERIC_WRITE = &h40000000
Const ADS_RIGHT_GENERIC_EXECUTE = &h20000000
Const ADS_RIGHT_GENERIC_ALL = &h10000000
Const ADS_RIGHT_LIST = &h120001
Const ADS_RIGHT_DS_CREATE_CHILD = &h1
Const ADS_RIGHT_DS_DELETE_CHILD = &h2
Const ADS_RIGHT_ACTRL_DS_LIST = &h4
Const ADS_RIGHT_DS_SELF = &h8
Const ADS_RIGHT_DS_READ_PROP = &h10
Const ADS_RIGHT_DS_WRITE_PROP = &h20
Const ADS_RIGHT_DS_DELETE_TREE = &h40
Const ADS_RIGHT_DS_LIST_OBJECT = &h80
Const ADS_RIGHT_DS_CONTROL_ACCESS = &h100

'********************************
'** ADS_ACETYPE_ENUM constants **
'********************************
Const ADS_ACETYPE_ACCESS_ALLOWED = 0
Const ADS_ACETYPE_ACCESS_DENIED = &h1
Const ADS_ACETYPE_SYSTEM_AUDIT = &h2
Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &h5
Const ADS_ACETYPE_ACCESS_DENIED_OBJECT = &h6
Const ADS_ACETYPE_SYSTEM_AUDIT_OBJECT = &h7

'*********************************
'** ADS_ACEFLAGS_ENUM constants **
'*********************************
Const ADS_ACEFLAG_UNKNOWN = &h1
Const ADS_ACEFLAG_INHERIT_ACE = &h2
Const ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE = &h4
Const ADS_ACEFLAG_INHERIT_ONLY_ACE = &h8
Const ADS_ACEFLAG_INHERITED_ACE = &h10
Const ADS_ACEFLAG_VALID_INHERIT_FLAGS = &h1f
Const ADS_ACEFLAG_SUCCESSFUL_ACCESS = &h40
Const ADS_ACEFLAG_FAILED_ACCESS = &h80

'*****************************
'** ADS_PATH_ENUM constants **
'*****************************
Const ADS_PATH_FILE = 1
Const ADS_PATH_FILESHARE = 2
Const ADS_PATH_REGISTRY = 3

'*****************************
'** ADS_FLAG_ENUM constants **
'*****************************
Const ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = &h2
Const ADS_FLAG_OBJECT_TYPE_PRESENT = &h1

'**********************************
'** ADS_SD_FORMAT_ENUM constants **
'**********************************
Const ADS_SD_FORMAT_IID = 1
Const ADS_SD_FORMAT_RAW = 2
Const ADS_SD_FORMAT_HEXSTRING = 3



strDirPath = "FILE://C:\SomeFolder\SomeFile"

'** Retrieve the Security Descriptor for the file
Set objFileSD = objADsSecurity.GetSecurityDescriptor(CStr(strDirPath))
Set objDacl = objFileSD.DiscretionaryAcl
'** Create new ACE
Set objAce = CreateObject("AccessControlEntry")
objAce.Flags = 0
objAce.Trustee = "Everyone"
objAce.AccessMask = ADS_RIGHT_LIST
objAce.AceFlags = ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE
objAce.AceType = ADS_ACETYPE_ACCESS_ALLOWED
'** Add ACE to DACL
objDacl.AddAce objAce
Set objAce = Nothing

'** Call sub to correctly order the ACEs in the DACL
Call ReorderDacl(objDacl)
'** Replace the DACL into the Objects Discretionary ACL
objFileSD.DiscretionaryACL = objDacl
'** Reset Security Descriptor on file
objADsSecurity.SetSecurityDescriptor objFileSD

'--------------------------------------------------

I'm not sure that that would solve your problem though... Do the Home
and Profile directories reside on a different server to the one on
which you create the user account?

Cheers

John
 
Neat

Thanks for that, John. The permissions scripting looks good. I'll give that a try and, if it doesn't work for me, I'll try reposting in one of the scripting groups

At the moment, the profiles folders live on the DC containing the PDC emulator FSMO. As for which server the new user gets created on, who knows? I suspect that may be part of the problem

Cheer

Mr

----- John wrote: ----

Mr Brownstone said:
Hi
winShell.Run "cacls " & profilepath & " /t /e /g " & username & ":F", 1, Tru


You may be better off posting this question in one of the scriptin
newsgroups. But..., I have scripted setting permissions usin
AdsSecurity.dll

'--------------------------------------
'******************************
'** ADS_RIGHTS_ENUM constants *
'******************************
Const ADS_RIGHT_DELETE = &h1000
Const ADS_RIGHT_READ_CONTROL = &h2000
Const ADS_RIGHT_WRITE_DAC = &h4000
Const ADS_RIGHT_WRITE_OWNER = &h8000
Const ADS_RIGHT_SYNCHRONIZE = &h10000
Const ADS_RIGHT_ACCESS_SYSTEM_SECURITY = &h100000
Const ADS_RIGHT_GENERIC_READ = &h8000000
Const ADS_RIGHT_GENERIC_WRITE = &h4000000
Const ADS_RIGHT_GENERIC_EXECUTE = &h2000000
Const ADS_RIGHT_GENERIC_ALL = &h1000000
Const ADS_RIGHT_LIST = &h12000
Const ADS_RIGHT_DS_CREATE_CHILD = &h
Const ADS_RIGHT_DS_DELETE_CHILD = &h
Const ADS_RIGHT_ACTRL_DS_LIST = &h
Const ADS_RIGHT_DS_SELF = &h
Const ADS_RIGHT_DS_READ_PROP = &h1
Const ADS_RIGHT_DS_WRITE_PROP = &h2
Const ADS_RIGHT_DS_DELETE_TREE = &h4
Const ADS_RIGHT_DS_LIST_OBJECT = &h8
Const ADS_RIGHT_DS_CONTROL_ACCESS = &h10

'*******************************
'** ADS_ACETYPE_ENUM constants *
'*******************************
Const ADS_ACETYPE_ACCESS_ALLOWED =
Const ADS_ACETYPE_ACCESS_DENIED = &h
Const ADS_ACETYPE_SYSTEM_AUDIT = &h
Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &h
Const ADS_ACETYPE_ACCESS_DENIED_OBJECT = &h
Const ADS_ACETYPE_SYSTEM_AUDIT_OBJECT = &h

'********************************
'** ADS_ACEFLAGS_ENUM constants *
'********************************
Const ADS_ACEFLAG_UNKNOWN = &h1
Const ADS_ACEFLAG_INHERIT_ACE = &h2
Const ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE = &h4
Const ADS_ACEFLAG_INHERIT_ONLY_ACE = &h8
Const ADS_ACEFLAG_INHERITED_ACE = &h10
Const ADS_ACEFLAG_VALID_INHERIT_FLAGS = &h1f
Const ADS_ACEFLAG_SUCCESSFUL_ACCESS = &h40
Const ADS_ACEFLAG_FAILED_ACCESS = &h80

'*****************************
'** ADS_PATH_ENUM constants **
'*****************************
Const ADS_PATH_FILE = 1
Const ADS_PATH_FILESHARE = 2
Const ADS_PATH_REGISTRY = 3

'*****************************
'** ADS_FLAG_ENUM constants **
'*****************************
Const ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = &h2
Const ADS_FLAG_OBJECT_TYPE_PRESENT = &h1

'**********************************
'** ADS_SD_FORMAT_ENUM constants **
'**********************************
Const ADS_SD_FORMAT_IID = 1
Const ADS_SD_FORMAT_RAW = 2
Const ADS_SD_FORMAT_HEXSTRING = 3



strDirPath = "FILE://C:\SomeFolder\SomeFile"

'** Retrieve the Security Descriptor for the file
Set objFileSD = objADsSecurity.GetSecurityDescriptor(CStr(strDirPath))
Set objDacl = objFileSD.DiscretionaryAcl
'** Create new ACE
Set objAce = CreateObject("AccessControlEntry")
objAce.Flags = 0
objAce.Trustee = "Everyone"
objAce.AccessMask = ADS_RIGHT_LIST
objAce.AceFlags = ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE
objAce.AceType = ADS_ACETYPE_ACCESS_ALLOWED
'** Add ACE to DACL
objDacl.AddAce objAce
Set objAce = Nothing

'** Call sub to correctly order the ACEs in the DACL
Call ReorderDacl(objDacl)
'** Replace the DACL into the Objects Discretionary ACL
objFileSD.DiscretionaryACL = objDacl
'** Reset Security Descriptor on file
objADsSecurity.SetSecurityDescriptor objFileSD

'--------------------------------------------------

I'm not sure that that would solve your problem though... Do the Home
and Profile directories reside on a different server to the one on
which you create the user account?

Cheers

John
 
Yes, I reckon that is your problem... The code sample I gave you is
part of a script for adding users, creating home directory shares,
profile folders etc. It runs on the DC that the shares/folders reside
on.

I beleive that CACLS and the ADsSecurity bits won't error if the
trustee doesn't exist, permissions just don't get applied.

I have no idea how long it takes for all DCs to 'know' about a new
user.... If someone could give you some idea you could make your app
wait.... :-(

Alternatively you could run it only on the box where the profiles
folders reside.

Cheers

John
 
Back
Top