Hi, When I add a new user to the AD with a home directory specified I want the directory to be created (as if I added the user via the user manager). I want the new user to be the owner and the permissions set correctly. How to I do this? Thanks, /C
There is not a ready, easy-made solution for this. You would have to go out to the server or DFS share and create the directory yourself. Then you would need to apply the appropriate permissions yourself as well. It can be done in code, but requires knowledge
of DACLs and ACEs.
Also, If the server with the home directory on it is authenticating against a differant controller than the web server you can have troubles as well. The user account may not have replicated to that server before you try to change the security on the Home Dir.
If anyone has a good idea of how to do this I would like to know as well.
Hi, I have done this before while I was creating an application to bulk import users that created the users directory on a remote server and then specified permissions on that folder after creation. You will need to get your hands on a dll called "ADsSecurity.dll"
this contains methods to set permissions etc. You will need to import this into .Net and access it via the COM interop. I have posted some code I found for the app below, be warned I have not tested this in a while ( it was my.Net conversion from a VB app
) but it should give you an idea about how to set permissions. The methods need to be called like DeleteEveryone, AddAcl then Reorder.
// ------------------------------------------------------------
//
// Simple wrapping class, publishes one function that sets
// permissions on the specfied folder. It removes the everyone
// DACL and re-orders the DACL's according to the Microsoft
// rules.
//
// ------------------------------------------------------------
///
/// Simple wrapper to allow access to the ADsSecurity
/// library
///
public class AdSecurityWrap
{
///
/// Private reference to the security library
///
private ADsSecurityClass adSec;
///
/// Default Constructor
///
public AdSecurityWrap()
{
// Obtain a reference to the security library
adSec = new ADsSecurityClass();
}
// ---------------------------------------------------------
//
// AdSecurityWrap.DeleteEveryoneDacl( object )
// Iterates through the access control entries on the
// access control list and removes the reference to
// the 'Everyone' access control entry if it is found.
//
// ---------------------------------------------------------
///
/// Deletes the 'Everyone' ACE from the SecurityDescriptors
/// DACL
///
///
/// File/Folder security descriptor
///
private void DeleteEveryoneDacl( object securityDescriptor )
{
// Iterate through the DACL and find the Everone ACE
foreach(object ace in ((AccessControlList)((SecurityDescriptor)securityDescriptor).DiscretionaryAcl) )
{
if( ((AccessControlEntry)ace).Trustee == "Everyone" )
{
((AccessControlList)((SecurityDescriptor)securityDescriptor).DiscretionaryAcl).RemoveAce( ace );
}
}
}
// ---------------------------------------------------------
//
// AdSecurityWrap.ReOrderDacl( object )
// Re-orders the discretionary access control list as
// specified in the Microsoft documentation
//
// ---------------------------------------------------------
///
/// Places the ACE's in the DACL in the correct order
///
/// Discretionary access list
private void ReOrderDacl( object dacl )
{
// Temp access control entry containers
AccessControlListClass newDacl = new AccessControlListClass();
AccessControlListClass impDenyDacl = new AccessControlListClass();
AccessControlListClass inheritedDacl = new AccessControlListClass();
AccessControlListClass impAllowDacl = new AccessControlListClass();
AccessControlListClass inhAllowDacl = new AccessControlListClass();
AccessControlListClass impDenyObjectDacl = new AccessControlListClass();
AccessControlListClass impAllowObjectDacl = new AccessControlListClass();
// Move the parameter dacl into the five bins
foreach( object ace in ((AccessControlList)dacl) )
{
// Check the ACE Flags
if( (((AccessControlEntry)ace).AceFlags &
(int)ADS_ACEFLAG_ENUM.ADS_ACEFLAG_INHERIT_ACE) ==
(int)ADS_ACEFLAG_ENUM.ADS_ACEFLAG_INHERIT_ACE )
{
// We dont care how these are placed in just do it
inheritedDacl.AddAce( ace );
}
else
{
switch( ((AccessControlEntry)ace).AceFlags )
{
case (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_ALLOWED:
// We have an implicit access allow
impAllowDacl.AddAce( ace );
break;
case (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_DENIED:
// We have an implicit deny ace
impDenyDacl.AddAce( ace );
break;
case (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_ALLOWED_OBJECT:
// We have an object allowed ace
impAllowObjectDacl.AddAce( ace );
break;
case (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_DENIED_OBJECT:
// We have an object denied ace
impDenyObjectDacl.AddAce( ace );
break;
default:
// Anything else
break;
}
}
}
// Now combine the ACE's in the proper order
foreach( object ace in impDenyDacl )
{
newDacl.AddAce( ace );
}
foreach( object ace in impDenyObjectDacl )
{
newDacl.AddAce( ace );
}
foreach( object ace in impAllowDacl )
{
newDacl.AddAce( ace );
}
foreach( object ace in impAllowObjectDacl )
{
newDacl.AddAce( ace );
}
foreach( object ace in inheritedDacl )
{
newDacl.AddAce( ace );
}
// Set the appropriate revision level for the DACL
newDacl.AclRevision = ((AccessControlList)dacl).AclRevision;
// Save the new DACL
dacl = (object)newDacl;
}
// ---------------------------------------------------------
//
// AdSecurityWrap.AddAce( string, string )
// Adds an access control list to the specified file or
// folder. Both the user and the file/folder need to
// exist
//
// ---------------------------------------------------------
///
/// Adds an access control list entry to the specfied file or
/// folders discretionary access control list
///
/// Path to the file or folder
/// Name of user object to add
public void AddAce( string objectPath, string usersName )
{
// Get the security descriptor for the file/folder
object fileSecDesc = adSec.GetSecurityDescriptor( objectPath );
// Delete the everone ace
this.DeleteEveryoneDacl( fileSecDesc );
// Create the new Access Control Entry
AccessControlEntryClass newAce = new AccessControlEntryClass();
newAce.Trustee = usersName;
newAce.AccessMask = (int)ADS_RIGHTS_ENUM.ADS_RIGHT_GENERIC_READ |
(int)ADS_RIGHTS_ENUM.ADS_RIGHT_GENERIC_EXECUTE |
(int)ADS_RIGHTS_ENUM.ADS_RIGHT_GENERIC_WRITE |
(int)ADS_RIGHTS_ENUM.ADS_RIGHT_DELETE;
newAce.AceFlags = 1 |
(int)ADS_ACEFLAG_ENUM.ADS_ACEFLAG_INHERIT_ACE;
newAce.AceType = (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_ALLOWED;
// Add the ace to the file/folder dacl
((AccessControlList)((SecurityDescriptor)fileSecDesc).DiscretionaryAcl).AddAce( newAce );
// Reorder the dacl
this.ReOrderDacl( ((SecurityDescriptor)fileSecDesc).DiscretionaryAcl );
// Set the files security descriptor
adSec.SetSecurityDescriptor( fileSecDesc, objectPath );
}
}
Remember this requires the ADsSecurity dll to be registered inside th project and on your computer (regsvr32). Hope
this helps you on your way.
Hi again, also I will post the VB code for creating folders on remote computers, sorry I havnt got time to convert it to .Net but you can see how its down.
Private Sub ShareFolder(strLocalPath As String, shareName As String, _
strCompName As String, bHidden As Boolean)
' Shares the specified folder on the specified computer, and appends
' a dollar sign if it is to be hidden. A share name is always
' created using the users username
Dim ShareSrvObj
Dim NewShareObj
Dim strHide As String
If bHidden Then strHide = "$" Else strHide = vbNullString
Set ShareSrvObj = GetObject("WinNT://" & strCompName & "/LANMANSERVER")
Set NewShareObj = ShareSrvObj.Create("fileshare", shareName & strHide)
NewShareObj.Path = strLocalPath
NewShareObj.Description = "Home area share"
NewShareObj.SetInfo
End Sub
Hi atirez, I used your code and some other articles and converted it to a VB.Net way of re-acling remote folders. However, I just wanted to ask you what is the right order of applying the acls and setting the permissions on a folder. I will appreciate your
answer. I will post the vb.net version if someone is interested later here. Thanks
Ok for those of you who are interested in how to reacl remote folders with Visualbasic.net here it is. The following code creates the file on a remote server, removes the everyone group from the Dacl and ads a user to it. In my case I give the user modify rights
to the folder and all subfolders and subfiles: I have put some extra lines that explain what different attributes could do: Imports ADSSECURITYLib Imports Scripting Imports ActiveDs Public Class applyfolder Inherits System.Web.UI.Page Private Sub Page_Load(ByVal
sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'Put user code to initialize the page here Dim folder As Folder Dim adssec As ADsSecurity Dim sd As SecurityDescriptor Dim fso As New FileSystemObject() Dim ace As New AccessControlEntry()
Dim dir As DirectoryServices.DirectoryEntry Dim folder1 As System.IO.Directory folder = fso.CreateFolder("**Put path to folder here**") Dim anyace As ActiveDs.AccessControlEntry Dim username As String = "**Domain\userName**" Const ads_sid_sam = 2 'if you want
username to showup in dacl Const ads_sid_sddl = 4 'if you want usersid to showup in dacl adssec = New ADsSecurity() sd = adssec.GetSecurityDescriptor("FILE://" & folder.Path) Dim dacl As AccessControlList dacl = sd.DiscretionaryAcl For Each anyace In dacl
If anyace.Trustee = "Everyone" Then dacl.RemoveAce(anyace) End If Next sd.DiscretionaryAcl = dacl Dim sid As ADsSID sid = New ADsSID() Dim sid1 sid.SetAs(ads_sid_sam, CStr(username)) sid1 = sid.GetAs(2) ace = New ActiveDs.AccessControlEntry() ace.Trustee =
sid1 ace.AccessMask = 1245631 '1245631 - modify '&H20000000 Or &H80000000 Or &H40000000 '&H10000000 -- Full control '&H20000000 -- Traverse/Execute '&H80000000 -- Read persmissions '&H40000000 -- Write Permissions ace.AceType = &H0 ace.AceFlags = 3 'aceflags
determine how low the permission restrictions will apply 1-- this folder and files 'aceflags 2 -- subfolder and files 'aceflags 3 -- this folder and subfolder and files 'aceflags 4 -- this folder only 'aceflags 5 -- this folder and files 'aceflags 6 -- this
folder, subfolders, folders control(no full or modify) 'aceflags 8 -- special 'aceglags 9 -- files only '&H40 Or '&H1F -- Subfolders and files only dacl.AddAce(ace) sd.DiscretionaryAcl = dacl adssec.SetSecurityDescriptor(sd) Dim oNewDACL As New AccessControlList()
'object used to temporarily store DACL (during ordering) Dim oInheritedDACL As New AccessControlList() 'object representing list of all Inherited ACEs Dim oDenyDACL As New AccessControlList() 'object representing list of non-Inherited Deny ACEs Dim oAllowDACL
As New AccessControlList() 'object representing list of non-Inherited Allow ACEs Dim oACE As New AccessControlEntry() 'object representing ACE (used for enumeration) '************************************************** '*** Access Control Entry Type Values
'*** Possible values for the IADsAccessContronEntry::AceType property. 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 '*** Constant Declarations '************************************************** '*** Access Control Entry Inheritance Flags '*** Possible values for the IADsAccessControlEntry::AceFlags property. Const ADS_ACEFLAG_UNKNOWN
= &H1 '*** child objects will inherit ACE of current object Const ADS_ACEFLAG_INHERIT_ACE = &H2 '*** prevents ACE inherited by the object from further propagation Const ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE = &H4 '*** indicates ACE used only for inheritance
(it does not affect permissions on object itself) Const ADS_ACEFLAG_INHERIT_ONLY_ACE = &H8 '*** indicates that ACE was inherited Const ADS_ACEFLAG_INHERITED_ACE = &H10 '*** indicates that inherit flags are valid (provides confirmation of valid settings) Const
ADS_ACEFLAG_VALID_INHERIT_FLAGS = &H1F '*** for auditing success in system audit ACE Const ADS_ACEFLAG_SUCCESSFUL_ACCESS = &H40 '*** for auditing failure in system audit ACE Const ADS_ACEFLAG_FAILED_ACCESS = &H80 '**************************************************
For Each oACE In dacl If ((oACE.AceFlags And ADS_ACEFLAG_INHERITED_ACE) = ADS_ACEFLAG_INHERITED_ACE) Then '************************************************** '*** as explained, no sorting is needed for Inherited ACEs, they are simply '*** added to the list
and retrieved at the end of the sub in the same order oInheritedDACL.AddAce(oACE) Else '************************************************** '*** non-Inherited ACEs need to be placed in their respective list to be re-ordered Select Case oACE.AceType Case ADS_ACETYPE_ACCESS_ALLOWED
oAllowDACL.AddAce(oACE) Case ADS_ACETYPE_ACCESS_DENIED oDenyDACL.AddAce(oACE) End Select End If Next '************************************************** '*** Recreate the Access Control List following the appropriate order '*** - non-Inherited Deny ACEs '***
- non-Inherited Allow ACEs '*** - Inherited ACEs For Each oACE In oDenyDACL oNewDACL.AddAce(oACE) Next For Each oACE In oAllowDACL oNewDACL.AddAce(oACE) Next For Each oACE In oInheritedDACL oNewDACL.AddAce(oACE) Next oInheritedDACL = Nothing oDenyDACL = Nothing
oAllowDACL = Nothing '************************************************** '*** Set appropriate DACL revision level oNewDACL.AclRevision = dacl.AclRevision '************************************************** '*** Reset the original DACL dacl = Nothing dacl =
oNewDACL sd.DiscretionaryAcl = dacl adssec.SetSecurityDescriptor(sd) End Sub End Class
I cut and paste the C# code into my project and it works great! Many thanks to Atirez! However, it is only useful for setting permissions on empty folders because it does not set the ACLs of subfolders and files to inherit the new ACE. An open source command
line utility called SetACL.exe may also work, but I think this code is more reliable.
Guten
Member
130 Points
26 Posts
Adding a user with home directory
Dec 17, 2003 07:41 AM|LINK
dunnry
Star
9098 Points
1806 Posts
Re: Adding a user with home directory
Dec 17, 2003 01:17 PM|LINK
Weblog
The Book
LDAP Programming Help
Hitskyn
Member
394 Points
85 Posts
Re: Adding a user with home directory
Dec 17, 2003 05:42 PM|LINK
Atirez
Member
117 Points
27 Posts
Re: Adding a user with home directory
Dec 19, 2003 06:18 AM|LINK
// ------------------------------------------------------------ // // Simple wrapping class, publishes one function that sets // permissions on the specfied folder. It removes the everyone // DACL and re-orders the DACL's according to the Microsoft // rules. // // ------------------------------------------------------------ /// /// Simple wrapper to allow access to the ADsSecurity /// library /// public class AdSecurityWrap { /// /// Private reference to the security library /// private ADsSecurityClass adSec; /// /// Default Constructor /// public AdSecurityWrap() { // Obtain a reference to the security library adSec = new ADsSecurityClass(); } // --------------------------------------------------------- // // AdSecurityWrap.DeleteEveryoneDacl( object ) // Iterates through the access control entries on the // access control list and removes the reference to // the 'Everyone' access control entry if it is found. // // --------------------------------------------------------- /// /// Deletes the 'Everyone' ACE from the SecurityDescriptors /// DACL /// /// /// File/Folder security descriptor /// private void DeleteEveryoneDacl( object securityDescriptor ) { // Iterate through the DACL and find the Everone ACE foreach(object ace in ((AccessControlList)((SecurityDescriptor)securityDescriptor).DiscretionaryAcl) ) { if( ((AccessControlEntry)ace).Trustee == "Everyone" ) { ((AccessControlList)((SecurityDescriptor)securityDescriptor).DiscretionaryAcl).RemoveAce( ace ); } } } // --------------------------------------------------------- // // AdSecurityWrap.ReOrderDacl( object ) // Re-orders the discretionary access control list as // specified in the Microsoft documentation // // --------------------------------------------------------- /// /// Places the ACE's in the DACL in the correct order /// /// Discretionary access list private void ReOrderDacl( object dacl ) { // Temp access control entry containers AccessControlListClass newDacl = new AccessControlListClass(); AccessControlListClass impDenyDacl = new AccessControlListClass(); AccessControlListClass inheritedDacl = new AccessControlListClass(); AccessControlListClass impAllowDacl = new AccessControlListClass(); AccessControlListClass inhAllowDacl = new AccessControlListClass(); AccessControlListClass impDenyObjectDacl = new AccessControlListClass(); AccessControlListClass impAllowObjectDacl = new AccessControlListClass(); // Move the parameter dacl into the five bins foreach( object ace in ((AccessControlList)dacl) ) { // Check the ACE Flags if( (((AccessControlEntry)ace).AceFlags & (int)ADS_ACEFLAG_ENUM.ADS_ACEFLAG_INHERIT_ACE) == (int)ADS_ACEFLAG_ENUM.ADS_ACEFLAG_INHERIT_ACE ) { // We dont care how these are placed in just do it inheritedDacl.AddAce( ace ); } else { switch( ((AccessControlEntry)ace).AceFlags ) { case (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_ALLOWED: // We have an implicit access allow impAllowDacl.AddAce( ace ); break; case (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_DENIED: // We have an implicit deny ace impDenyDacl.AddAce( ace ); break; case (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_ALLOWED_OBJECT: // We have an object allowed ace impAllowObjectDacl.AddAce( ace ); break; case (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_DENIED_OBJECT: // We have an object denied ace impDenyObjectDacl.AddAce( ace ); break; default: // Anything else break; } } } // Now combine the ACE's in the proper order foreach( object ace in impDenyDacl ) { newDacl.AddAce( ace ); } foreach( object ace in impDenyObjectDacl ) { newDacl.AddAce( ace ); } foreach( object ace in impAllowDacl ) { newDacl.AddAce( ace ); } foreach( object ace in impAllowObjectDacl ) { newDacl.AddAce( ace ); } foreach( object ace in inheritedDacl ) { newDacl.AddAce( ace ); } // Set the appropriate revision level for the DACL newDacl.AclRevision = ((AccessControlList)dacl).AclRevision; // Save the new DACL dacl = (object)newDacl; } // --------------------------------------------------------- // // AdSecurityWrap.AddAce( string, string ) // Adds an access control list to the specified file or // folder. Both the user and the file/folder need to // exist // // --------------------------------------------------------- /// /// Adds an access control list entry to the specfied file or /// folders discretionary access control list /// /// Path to the file or folder /// Name of user object to add public void AddAce( string objectPath, string usersName ) { // Get the security descriptor for the file/folder object fileSecDesc = adSec.GetSecurityDescriptor( objectPath ); // Delete the everone ace this.DeleteEveryoneDacl( fileSecDesc ); // Create the new Access Control Entry AccessControlEntryClass newAce = new AccessControlEntryClass(); newAce.Trustee = usersName; newAce.AccessMask = (int)ADS_RIGHTS_ENUM.ADS_RIGHT_GENERIC_READ | (int)ADS_RIGHTS_ENUM.ADS_RIGHT_GENERIC_EXECUTE | (int)ADS_RIGHTS_ENUM.ADS_RIGHT_GENERIC_WRITE | (int)ADS_RIGHTS_ENUM.ADS_RIGHT_DELETE; newAce.AceFlags = 1 | (int)ADS_ACEFLAG_ENUM.ADS_ACEFLAG_INHERIT_ACE; newAce.AceType = (int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_ALLOWED; // Add the ace to the file/folder dacl ((AccessControlList)((SecurityDescriptor)fileSecDesc).DiscretionaryAcl).AddAce( newAce ); // Reorder the dacl this.ReOrderDacl( ((SecurityDescriptor)fileSecDesc).DiscretionaryAcl ); // Set the files security descriptor adSec.SetSecurityDescriptor( fileSecDesc, objectPath ); } }Remember this requires the ADsSecurity dll to be registered inside th project and on your computer (regsvr32). Hope this helps you on your way.Atirez
Member
117 Points
27 Posts
Re: Adding a user with home directory
Dec 19, 2003 06:21 AM|LINK
Private Sub ShareFolder(strLocalPath As String, shareName As String, _ strCompName As String, bHidden As Boolean) ' Shares the specified folder on the specified computer, and appends ' a dollar sign if it is to be hidden. A share name is always ' created using the users username Dim ShareSrvObj Dim NewShareObj Dim strHide As String If bHidden Then strHide = "$" Else strHide = vbNullString Set ShareSrvObj = GetObject("WinNT://" & strCompName & "/LANMANSERVER") Set NewShareObj = ShareSrvObj.Create("fileshare", shareName & strHide) NewShareObj.Path = strLocalPath NewShareObj.Description = "Home area share" NewShareObj.SetInfo End Subivanr80
Member
395 Points
79 Posts
Re: Adding a user with home directory
Dec 26, 2003 10:54 PM|LINK
ivanr80
Member
395 Points
79 Posts
Re: Adding a user with home directory
Dec 30, 2003 12:02 AM|LINK
GJoy
Member
65 Points
13 Posts
Re: Adding a user with home directory
Aug 27, 2004 08:54 PM|LINK