171 Chapter 6. Users Introduction Recipe 6.1. Creating a User Recipe 6.2. Creating a Large Number of Users Recipe 6.3. Creating an inetOrgPerson User Recipe 6.4. Modifying an Attribute for Several Users at Once Recipe 6.5. Moving a User Recipe 6.6. Renaming a User Recipe 6.7. Copying a User Recipe 6.8. Unlocking a User Recipe 6.9. Finding Locked Out Users Recipe 6.10. Troubleshooting Account Lockout Problems Recipe 6.11. Viewing the Account Lockout and Password Policies Recipe 6.12. Enabling and Disabling a User Recipe 6.13. Finding Disabled Users Recipe 6.14. Viewing a User's Group Membership Recipe 6.15. Changing a User's Primary Group Recipe 6.16. Transferring a User's Group Membership to Another User Recipe 6.17. Setting a User's Password Recipe 6.18. Setting a User's Password via LDAP Recipe 6.19. Setting a User's Password via Kerberos Recipe 6.20. Preventing a User from Changing His Password Recipe 6.21. Requiring a User to Change Her Password at Next Logon 172 Recipe 6.22. Preventing a User's Password from Expiring Recipe 6.23. Finding Users Whose Passwords Are About to Expire Recipe 6.24. Setting a User's Account Options (userAccountControl) Recipe 6.25. Setting a User's Account to Expire in the Future Recipe 6.26. Finding Users Whose AccountsAre About to Expire Recipe 6.27. Determining a User's Last Logon Time Recipe 6.28. Finding Users Who Have Not Logged On Recently Recipe 6.29. Setting a User's Profile Attributes Recipe 6.30. Viewing a User's Managed Objects Recipe 6.31. Modifying the Default Display Name Used When Creating Users in ADUC Recipe 6.32. Creating a UPN Suffix for a Forest Introduction User accounts are one of the most frequently used types of objects in Active Directory. Because Windows 2000 and Windows 2003 systems manage users through Active Directory, many key issues that system administrators have to deal with are covered in this chapter. In particular, Active Directory manages all the information regarding passwords, group membership, the disabling or expiration of accounts, and when users have logged in. The Anatomy of a User The default location for user objects in a domain is the cn=Users container directly off the domain root. You can, of course, create user objects in other containers and organizational units in a domain. Table 6-1 contains a list of some of the interesting attributes that are available on user objects. This is by no means a complete list. There are many other informational attributes that I haven't included. Table 6-1. Attributes of user objects Attribute Description accountExpires Large integer representing when the user's account is going to expire. See Recipe 6.25 for more information. 173 Table 6-1. Attributes of user objects Attribute Description cn Relative distinguished name of user objects. This is commonly the username of the user. displayName Typically the full name of a user. This attribute is used in administrative tools to display a user's descriptive "name." givenName First name of the user. homeDirectory Local or UNC path of user's home directory. See Recipe 6.29 for more information. homeDrive Defines the drive letter to map the user's home directory to. See Recipe 6.29 for more information. lastLogon Last logon timestamp, which is not replicated among domain controllers. lastLogonTimestamp Approximate last logon timestamp, which is replicated among domain controllers. This attribute is new in Windows Server 2003. See Recipe 6.27 for more information. managedObjects Multivalued linked attribute (with managedBy) that contains a list of DNs of objects the user manages. lockoutTime Large integer representation of the timestamp for when a user was locked out. See Recipe 6.9 for more information. memberOf List of DNs of the groups the user is a member of. See Recipe 6.14 for more information. objectSID Octet string representing the SID of the user. primaryGroupID ID of the primary group for the user. See Recipe 6.15 for more information. profilePath UNC path to profile directory. See Recipe 6.29 for more information. pwdLastSet Large integer that can be translated into the last time the user's password was set. See Recipe 6.23 for more information. sAMAccountName NetBIOS style name of the user. sidHistory Multivalued attribute that contains a list of SIDs that is associated with the user. scriptPath Path to logon script. See Recipe 6.29 for more information. sn Last name of user. tokenGroups List of SIDs for the groups in the domain the user is a member of (both directly and via nesting). 174 Table 6-1. Attributes of user objects Attribute Description unicodePwd Octet string that contains the password for the user. This attribute cannot be directly queried. userAccountControl Account flags that define such things as account status and password change status. userPrincipalName Email-style account name for user, which a user can use to logon to a computer. userWorkstations Multivalued list of computers a user can logon to. Recipe 6.1 Creating a User 6.1.1 Problem You want to create a user object. 6.1.2 Solution 6.1.2.1 Using a graphical user interface 1. Open the Active Directory Users and Computers (ADUC) snap-in. 2. If you need to change domains, right-click on "Active Directory Users and Computers" in the left pane, select Connect to Domain, enter the domain name, and click OK. 3. In the left pane, browse to the parent container of the new user, right-click on it, and select New User. 4. Enter the values for the first name, last name, full name, and user logon name fields as appropriate and click Next. 5. Enter and confirm password, set any of the password flags, and click Next. 6. Click Finish. 6.1.2.2 Using a command-line interface > dsadd user "<UserDN>" -upn <UserUPN> -fn "<UserFirstName>" -ln "<UserLastName>"[RETURN] -display "<UserDisplayName>" -pwd <UserPasswd> 6.1.2.3 Using VBScript ' Taken from ADS_USER_FLAG_ENUM Const ADS_UF_NORMAL_ACCOUNT = 512 set objParent = GetObject("LDAP://<ParentDN>") set objUser = objParent.Create("user", "cn=<UserName>") ' e.g. joes objUser.Put "sAMAccountName", "<UserName>" ' e.g. joes objUser.Put "userPrincipalName", "<UserUPN>" ' e.g. joes@rallencorp.com 175 objUser.Put "givenName", "<UserFirstName>" ' e.g. Joe objUser.Put "sn", "<UserLastName>" ' e.g. Smith objUser.Put "displayName", "<UserFirstName> <UserLastName>" ' e.g. Joe Smith objUser.Put "userAccountControl", ADS_UF_NORMAL_ACCOUNT objUser.SetInfo objUser.SetPassword("<Password>") objUser.AccountDisabled = FALSE objUser.SetInfo 6.1.3 Discussion The only mandatory attribute that must be set when creating a user is sAMAccountName, which is the account name that is used to interoperate with down-level domains. To make the account immediately available for a user to use, you'll need to make sure the account is enabled, which is accomplished by setting userAccountControl to 512, and setting a password (see Recipe 6.17). If you allow UPN logons, you'll want to make sure the userPrincipalName attribute is set. With Windows Server 2003, you can also create user accounts using the inetOrgPerson class, which is described in Recipe 6.3 . inetOrgPerson objects can be used for user authentication and restricting access to resources in much the same way as user objects. 6.1.3.1 Using a graphical user interface To set additional attributes, double-click on the user account after it has been created. There are several tabs to choose from that contain attributes that are grouped together based on function (e.g., Profile). 6.1.3.2 Using a command-line interface Several additional attributes can be set with the dsadd user command. Run dsadd user /? for the complete list. 6.1.3.3 Using VBScript Take a look at Recipe 6.24 for more information on the userAccountControl attribute and the various flags that can be set for it. 6.1.4 See Also Recipe 6.2 for creating users in bulk, Recipe 6.3 for creating an inetOrgPerson user, and MSDN: ADS_USER_FLAG_ENUM 176 Recipe 6.2 Creating a Large Number of Users 6.2.1 Problem You want to create a large number of user objects, either for testing purposes or to initially populate Active Directory with your employee, customer, or student user accounts. 6.2.2 Solution The following examples will create 1,000 users in the rallencorp.com domain under the Bulk OU. The password is set, but no other attributes are configured. You can modify the examples to populate whatever attributes you need. 6.2.2.1 Using a command-line interface > for /L %i in (1,1,1000) do dsadd user cn=User%i,ou=bulk,dc=rallencorp,dc=com -pwd[RETURN] User%i 6.2.2.2 Using VBScript ' This code creates a large number of users with incremented user names ' e.g. User1, User2, User3, ' SCRIPT CONFIGURATION intNumUsers = 1000 ' Number of users to create strParentDN = "<ParentDN>" ' e.g. ou=bulk,dc=emea,dc=rallencorp,dc=com ' END CONFIGURATION ' Taken from ADS_USER_FLAG_ENUM Const ADS_UF_NORMAL_ACCOUNT = 512 set objParent = GetObject("LDAP://" & strParentDN) for i = 1 to intNumUsers strUser = "User" & i Set objUser = objParent.Create("user", "cn=" & strUser) objUser.Put "sAMAccountName", strUser objUser.Put "userAccountControl", ADS_UF_NORMAL_ACCOUNT objUser.SetInfo objUser.SetPassword(strUser) objUser.AccountDisabled=FALSE objUser.SetInfo WScript.Echo "Created " & strUser next WScript.Echo "" WScript.Echo "Created " & intNumUsers & " users" 6.2.3 Discussion Using ADSI and even the new DS command line utilities on Windows Server 2003, you can create hundreds and even thousands of users easily and quickly. I ran both the CLI and VBScript solutions in a test domain, which create 1,000 user objects, on a single processor machine. The VBScript solution took less than 1.5 minutes and the CLI solution took less than 5 minutes. 177 Admittedly, they are not populating very many attributes, but it shows that you can quickly populate Active Directory with user accounts very easily. You can also modify the examples to pull from a data source, such as an employee database, and use real data. 6.2.4 See Also Recipe 6.1 for creating a user Recipe 6.3 Creating an inetOrgPerson User 6.3.1 Problem You want to create an inetOrgPerson object, which is the standard LDAP object class to represent users. 6.3.2 Solution 6.3.2.1 Using a graphical user interface 1. Open the Active Directory Users and Computers snap-in. 2. If you need to change domains, right-click on "Active Directory Users and Computers" in the left pane, select Connect to Domain, enter the domain name, and click OK. 3. In the left pane, browse to the parent container of the new user, right-click on it, and select New InetOrgPerson. 4. Enter first name, last name, and user logon name fields as appropriate and click Next. 5. Enter and confirm the password, set any of the password flags, and click Next. 6. Click Finish. 6.3.2.2 Using a command-line interface The dsadd command does not support creating inetOrgPerson objects so we'll use ldifde instead. First, we need to create an LDIF file called create_inetorgperson.ldf with the following contents: dn: <UserDN> changetype: add objectclass: inetorgperson sAMAccountName: <UserName> userAccountControl: 512 Be sure to replace <UserDN> with the distinguished name of the user you want to add and <UserName> with the user's username. Then run the following command: > ldifde -i -f create_inetorgperson.ldf 6.3.2.3 Using VBScript ' This code creates an inetOrgPerson object 178 set objParent = GetObject("LDAP://<ParentDN>") set objUser = objParent.Create("inetorgperson", "cn=<UserName>") ' Taken from ADS_USER_FLAG_ENUM Const ADS_UF_NORMAL_ACCOUNT = 512 objUser.Put "sAMAccountName", "<UserName>" objUser.Put "userPrincipalName", "<UserUPN>" objUser.Put "givenName", "<UserFirstName>" objUser.Put "sn", "<UserLastName>" objUser.Put "displayName", "<UserFirstName> <UserLastName>" objUser.Put "userAccountControl", ADS_UF_NORMAL_ACCOUNT objUser.SetInfo objUser.SetPassword("<Password>") objUser.AccountDisabled = FALSE objUser.SetInfo 6.3.3 Discussion The inetOrgPerson object class was defined in RFC 2798. It is the closest thing in the LDAP world to a standard representation of a user, and most LDAP vendors support the inetOrgPerson class. Unfortunately, Microsoft did not support inetOrgPerson with the initial release of Active Directory. Even though they provided an add-on later to extend the schema to support it, the damage had been done. Most Active Directory implementations were already using the user object class and were unlikely to convert. This required vendors to build in support for the user class. You can download the InetOrgPerson Kit for Windows 2000 from the following web site: http://msdn.microsoft.com/library/en- us/dnactdir/html/inetopkit.asp. This requires that you extend the schema to support an additional object class and new attributes. It also creates a schema conflict with Windows Server 2003. See MS KB 314649 for more information. In Windows Server 2003 Active Directory, inetOrgPerson is supported natively. You can create inetOrgPerson objects for your users, who can use them to authenticate just as they would accounts of the user object class. If you haven't deployed Active Directory yet and you plan on integrating a lot of third-party LDAP-based applications that rely on inetOrgPerson, you may want to consider using it over user. You won't be losing any information or functionality because the inetOrgPerson class inherits directly from the user class. For this reason, the inetOrgPerson class has even more attributes than the Microsoft user class. The one potential downside is that some of the Microsoft tools, such as the DS utilities, do not support modifying inetOrgPerson objects. 179 6.3.4 See Also Recipe 6.1 for creating a user and RFC 2798 (Definition of the inetOrgPerson LDAP Object Class) Recipe 6.4 Modifying an Attribute for Several Users at Once 6.4.1 Problem You want to modify an attribute for several users at once. 6.4.2 Solution 6.4.2.1 Using a graphical user interface This requires the Windows Server 2003 version of the Active Directory Users and Computers snap-in. 1. Open the Active Directory Users and Computers (ADUC) snap-in. 2. If you need to change domains, right-click on "Active Directory Users and Computers" in the left pane, select Connect to Domain, enter the domain name, and click OK. 3. In the left pane, browse to the parent container of the objects you want to modify. 4. In the right pane, highlight each object you want to modify, right-click and select Properties. 5. Check the box beside the attribute(s) you want to modify and edit the fields for the attributes. 6. Click OK. 6.4.2.2 Using a command-line interface The following command sets the home directory of all users under a parent container ( <ParentDN>) to be on a particular file server (<FileServer>). The user (i.e., $username$) is automatically replaced with the sAMAccountName for the user. > for /F "usebackq delims=""" %i in (`dsquery user "<ParentDN>" -limit 0 - scope[RETURN] onelevel`) do dsmod user -hmdir "\\<FileServerName>\$username$" %i 6.4.2.3 Using VBScript ' This code sets the home drive of all users under a container ' to be on a file server where the share name is the same as the user's ' sAMAccountName. set objParent = GetObject("LDAP://<ParentDN>") objParent.Filter = Array("user") for each objUser in objParent 180 Wscript.Echo "Modifying " & objUser.Get("sAMAccountName") objUser.HomeDirectory = "\\<FileServerName>\" & _ objUser.Get("sAMAccountName") objUser.SetInfo next 6.4.3 Discussion It is often necessary to update several users at once due to an organizational, locational or file server change. In each solution, I showed how to modify all users within a parent container, but you may need to use different criteria for locating the users. With ADUC, you are limited to modifying multiple users that belong to the same container. You can, however, create a Saved Query with the Windows Server 2003 version of ADUC that returns users based on any criteria you specify. You can then highlight those users and modify them as described in the GUI solution. With the CLI solution, you can modify the dsquery user command to search on whatever criteria you want. The same applies in the VBScript solution, but you'll need to use an ADO query instead of the Filter method if you want to do anything more complex. See Recipe 4.5 for more information on searching with ADO. Recipe 6.5 Moving a User 6.5.1 Problem You want to move a user object to a different container or OU. 6.5.2 Solution 6.5.2.1 Using a graphical user interface 1. Open the Active Directory Users and Computers snap-in. 2. If you need to change domains, right-click on "Active Directory Users and Computers" in the left pane, select Connect to Domain, enter the domain name, and click OK. 3. In the left pane, right-click on the domain and select Find. 4. Type the name of the user and click Find Now. 5. In the Search Results, right-click on the user and select Move. 6. Browse to the new parent container or OU and click on it. 7. Click OK. 6.5.2.2 Using a command-line interface > dsmove "<UserDN>" -newparent "<NewParentDN>" 6.5.2.3 Using VBScript ' This code moves a user from one container to another. ' SCRIPT CONFIGURATION . with Windows Server 2003. See MS KB 314649 for more information. In Windows Server 2003 Active Directory, inetOrgPerson is supported natively. You can create inetOrgPerson objects for your. Suffix for a Forest Introduction User accounts are one of the most frequently used types of objects in Active Directory. Because Windows 2000 and Windows 2003 systems manage users through Active. primaryGroupID ID of the primary group for the user. See Recipe 6.15 for more information. profilePath UNC path to profile directory. See Recipe 6.29 for more information. pwdLastSet Large integer