6.11.4 See Also MS KB 221930 Domain Security Policy in Windows 2000, MS KB 255550 Configuring Account Policies in Active Directory, MSDN: IADsLargeInteger, and MSDN: DOMAIN_PASSWORD_INF
Trang 16.11.3.3 Using VBScript
The VBScript solution required quite a bit of code to perform a simple task; printing out the account lockout and password policy settings First, I created a Dictionary object with each of the six attributes as the keys and the unit's designation for each key (e.g., minutes) as the value I then iterated over each key, printing it along with the value retrieved from the domain object
Some additional code was necessary to distinguish between the values returned from some of the attributes In the case of the time-based attributes, such as lockoutDuration, a
IADsLargeInteger object was returned from the Get method instead of a pure integer or string value IADsLargeInteger objects represent 64-bit, also known as Integer8, numbers 32-bit systems, which make up the majority of systems today, have to break 64-bit numbers into two parts (a high and low part) in order to store them Unfortunately, VBScript cannot natively handle a 64-bit number and stores it as a double precision To convert a 64-bit number into something VBScript can handle, we have to first multiply the high part by 4,294,967,296 (2^32) and then add the low part to the result
value = Abs(objLargeInt.HighPart * 2^32 + objLargeInt.LowPart)
Then I divided by 10,000,000 or 10^7, which represents the number of 100 nanosecond intervals per second
value = int ( value / 10000000 )
I then used the int function to discard any remainder and finally divided the result by 60
(number of seconds)
value = int ( value / 60 )
Note that the result is only an approximation in minutes and can be off by several minutes, hours,
or even days depending on the original value
The last part of the code iterates over another Dictionary object that contains constants
representing various flags that can be set as part of the pwdProperties attribute
6.11.4 See Also
MS KB 221930 (Domain Security Policy in Windows 2000), MS KB 255550 (Configuring Account Policies in Active Directory), MSDN: IADsLargeInteger, and MSDN:
DOMAIN_PASSWORD_INFORMATION
Recipe 6.12 Enabling and Disabling a User
6.12.1 Problem
You want to enable or disable a user
Trang 26.12.2 Solution
6.12.2.1 Using a graphical user interface
1 Open the Active Directory Users and Computers snap-in
2 In the left pane, right-click on the domain and select Find
3 Select the appropriate domain beside In
4 Type the name of the user beside Name and click Find Now
5 In the Search Results, right-click on the user and select Enable Account to enable or Disable Account to disable
6 Click OK
6.12.2.2 Using a command-line interface
To enable a user, use the following command:
> dsmod user <UserDN> -disabled no
To disable a user, use the following command:
> dsmod user <UserDN> -disabled yes
6.12.2.3 Using VBScript
' This code will enable or disable a user
' - SCRIPT CONFIGURATION -
' Set to FALSE to disable account or TRUE to enable account
strDisableAccount = FALSE
strUserDN = "<UserDN>" ' e.g cn=jsmith,cn=Users,dc=rallencorp,dc=com
' - END CONFIGURATION -
set objUser = GetObject("LDAP://" & strUserDN)
if objUser.AccountDisabled = TRUE then
WScript.Echo "Account for " & objUser.Get("cn") & " currently disabled"
if strDisableAccount = FALSE then
objUser.AccountDisabled = strDisableAccount
objUser.SetInfo
WScript.Echo "Account enabled"
end if
else
WScript.Echo "Account currently enabled"
if strDisableAccount = TRUE then
objUser.AccountDisabled = strDisableAccount
objUser.SetInfo
WScript.Echo "Account disabled"
end if
end if
6.12.3 Discussion
Account status is used to control if a user is allowed to log on or not When an account is
disabled, the user is not allowed to log on to her workstation with the account or access AD
Trang 3controlled resources Much like the lockout status, the account status is stored as a flag in the userAccountControl attribute (see Recipe 6.24)
There is an IADsUser::AccountDisabled property that allows you to determine and change the status Set the method FALSE to enable the account or TRUE to disable
6.12.4 See Also
Recipe 6.13 for finding disabled users, and Recipe 6.24 for more on the userAccountControl attribute
Recipe 6.13 Finding Disabled Users
6.13.1 Problem
You want to find disabled users in a domain
6.13.2 Solution
6.13.2.1 Using a graphical user interface
1 Open the Active Directory Users and Computers snap-in
2 In the left pane, connect to the domain you want to query
3 Right-click on the domain and select Find
4 Beside Find, select Common Queries
5 Check the box beside "disabled accounts."
6 Click the Find Now button
6.13.2.2 Using a command-line interface
> dsquery user <DomainDN> -disabled
6.13.2.3 Using VBScript
' This code finds all disabled user accounts in a domain
' - SCRIPT CONFIGURATION -
strDomainDN = "<DomainDN>" ' e.g dc=rallencorp,dc=com
' - END CONFIGURATION -
strBase = "<LDAP://" & strDomainDN & ">;"
strFilter = "(&(objectclass=user)(objectcategory=person)" & _
"(useraccountcontrol:1.2.840.113556.1.4.803:=2));"
strAttrs = "name;"
strScope = "subtree"
set objConn = CreateObject("ADODB.Connection")
objConn.Provider = "ADsDSOObject"
objConn.Open "Active Directory Provider"
set objRS = objConn.Execute(strBase & strFilter & strAttrs & strScope)
objRS.MoveFirst
while Not objRS.EOF
Trang 4Wscript.Echo objRS.Fields(0).Value
objRS.MoveNext
wend
6.13.3 Discussion
Users in Active Directory can either be enabled or disabled A disabled user cannot log in to the domain Unlike account lockout, which is an automatic process that is based on the number of times a user incorrectly enters a password, an account has to be manually enabled or disabled
All disabled user accounts have the bit that represents 2 (0010) set in their userAccountControl attribute This doesn't mean that the attribute will be equal to 2, it just means that the bit that equals 2 will be enabled—other bits may also be set See Recipe 4.9 and Recipe 4.12 for a more detailed explanation of bit flags
6.13.4 See Also
Recipe 6.12 for enabling and disabling users
Recipe 6.14 Viewing a User's Group Membership
6.14.1 Problem
You want to view the group membership of a user
6.14.2 Solution
6.14.2.1 Using a graphical user interface
1 Open the Active Directory Users and Computers snap-in
2 In the left pane, right-click on the domain and select Find
3 Select the appropriate domain beside In
4 Type the name of the user beside Name and click Find Now
5 In the Search Results, double-click on the user
6 Click the Member Of tab
7 To view all indirect group membership (from nested groups), you'll need to double-click
on each group
6.14.2.2 Using a command-line interface
The following command displays the groups <UserDN> is a member of Use the -expand switch
to list nested group membership as well:
> dsget user <UserDN> -memberof [-expand]
6.14.2.3 Using VBScript
Trang 5' This code displays the group membership of a user
' It avoids infinite loops due to circular group nesting by
' keeping track of the groups that have already been seen
' - SCRIPT CONFIGURATION -
strUserDN = "<UserDN>" ' e.g cn=jsmith,cn=Users,dc=rallencorp,dc=com
' - END CONFIGURATION -
set objUser = GetObject("LDAP://" & strUserDN)
Wscript.Echo "Group membership for " & objUser.Get("cn") & ":"
strSpaces = ""
set dicSeenGroup = CreateObject("Scripting.Dictionary")
DisplayGroups "LDAP://" & strUserDN, strSpaces, dicSeenGroup
Function DisplayGroups ( strObjectADsPath, strSpaces, dicSeenGroup)
set objObject = GetObject(strObjectADsPath)
WScript.Echo strSpaces & objObject.Name
on error resume next ' Doing this to avoid an error when memberOf is empty
if IsArray( objObject.Get("memberOf") ) then
colGroups = objObject.Get("memberOf")
else
colGroups = Array( objObject.Get("memberOf") )
end if
for each strGroupDN In colGroups
if Not dicSeenGroup.Exists(strGroupDN) then
dicSeenGroup.Add strGroupDN, 1
DisplayGroups "LDAP://" & strGroupDN, strSpaces & " ", dicSeenGroup end if
next
End Function
6.14.3 Discussion
The memberOf attribute on user objects is multivalued and contains the list of distinguished names for the groups the user is a member memberOf is actually linked with the member attribute
on group objects, which holds the distinguished names of its members For this reason, you cannot directly modify the memberOf attribute; you must instead modify the member attribute on the group
The primary group of a user, which the user is technically a member of, will not be shown in either the CLI or VBScript solutions This is due to the fact that the primary group is not stored
in the memberOf attribute like the rest of the groups See Recipe 6.15 and Recipe 7.8 for more on finding the primary group of a user
6.14.4 See Also
Recipe 7.3 for more on viewing the nested members of a group and Recipe 10.16 for more information on linked attributes
Trang 6Recipe 6.15 Changing a User's Primary Group
6.15.1 Problem
You want to change the primary group of a user
6.15.2 Solution
6.15.2.1 Using a graphical user interface
1 Open the Active Directory Users and Computers snap-in
2 In the left pane, right-click on the domain and select Find
3 Select the appropriate domain beside In
4 Type the name of the user beside Name and click Find Now
5 In the Search Results, double-click on the user
6 Click the Member Of tab
7 Click on the name of the group you want to set as the primary group
8 Click the Set Primary Group button
9 Click OK
6.15.2.2 Using VBScript
' This code first checks to see if the user's primary group is already
' set to the specified group If not it will a) add the user to the group ' if not already a member and b) set the primary group id to the group
' - SCRIPT CONFIGURATION -
strUserDN = "<UserDN>" ' e.g cn=rallen,ou=Sales,dc=rallencorp,dc=com strGroupDN = "<GroupDN>" ' e.g cn=SalesGroup,ou=Sales,dc=rallencorp,dc=com
' - END CONFIGURATION -
Const ADS_PROPERTY_APPEND = 3
set objUser = GetObject("LDAP://" & strUserDN )
WScript.Echo
set objGroup = GetObject("LDAP://" & strGroupDN )
objGroup.GetInfoEx Array("primaryGroupToken"), 0
if objGroup.Get("primaryGroupToken") = objUser.Get("primaryGroupID") then WScript.Echo "Primary group for user already set to " & strGroupDN
WScript.Quit
end if
intAddMember = 1
for each strMemberDN in objUser.GetEx("memberOf")
if LCase(strMemberDN) = LCase(strGroupDN) then
intAddMember = 0
Exit for
end if
next
if intAddMember > 0 then
objGroup.PutEx ADS_PROPERTY_APPEND, "member", Array(strUserDN)
Trang 7objGroup.SetInfo
WScript.Echo "Added " & strUserDN & " as member of " & strGroupDN
end if
objUser.Put "primaryGroupID", objGroup.Get("primaryGroupToken")
objUser.SetInfo
WScript.Echo "Changed primary group id of " & strUserDN & _
" to " & objGroup.Get("primaryGroupToken")
6.15.3 Discussion
The primary group is a holdover from Windows NT that was used to support Macintosh and POSIX clients, but it is not used actively in Active Directory That said, you might have some legacy applications that depend on the primary group, and therefore, you may have to change some users' primary group
Changing the primary group is not difficult, but it is not straightforward either The primary group is stored on user objects in the primaryGroupID attribute, which contains the RID of the primary group You can obtain this value by querying the primaryGroupToken attribute on the target group object Before you can set the primaryGroupID on the user object, you have to first make sure the user is a member of the group If you try to set the primaryGroupID for a group in which the user is not a member, you will get an error
The default primaryGroupID is set to 513 (Domain Users) for all users
6.15.4 See Also
Recipe 7.8 for determining the group name given a group ID, MS KB 297951 (HOWTO: Use the PrimaryGroupID Attribute to Find the Primary Group for a User), MS KB 321360 (How to Use Native ADSI Components to Find the Primary Group), and MS KB 243330 (Well Known
Security Identifiers in Windows 2000)
Recipe 6.16 Transferring a User's Group Membership
to Another User
6.16.1 Problem
You want to transfer the group membership for one user to another
6.16.2 Solution
6.16.2.1 Using a graphical user interface
1 Open the Active Directory Users and Computers snap-in
2 In the left pane, right-click on the domain and select Find
3 Select the appropriate domain beside In
Trang 84 Beside Name, type the name of the user you want to transfer groups from and click Find Now
5 In the Search Results, double-click on the user
6 Click the Member Of tab
7 For each group you want to add another user in, do the following:
a Double-click on the group
b Click the Members tab
c Click the Add button
d Find the user you want to add in the object picker and click OK
e Click OK
6.16.2.2 Using a command-line interface
The following command line will add <NewUserDN> to all of the groups that <CurrentUserDN>
is a member of:
> for /F "usebackq delims=""" %i in (`dsget user "<CurrentUserDN>" -memberof`)
do[RETURN]
dsmod group %i -addmbr "<NewUserDN>"
If you want to get fancy and remove <CurrentUserDN> from each of the groups in the same
operation, simply add an -rmmbr option on the end:
> for /F "usebackq delims=""" %i in (`dsget user "<CurrentUserDN>" -memberof`)
do[RETURN]
dsmod group %i -addmbr "<NewUserDN>" -rmmbr "<CurrentUserDN>"
6.16.2.3 Using VBScript
' This code adds the "new" user to the groups the "current"
' user is a member of
' - SCRIPT CONFIGURATION -
strCurrentUserDN = "<CurrentUserDN>" ' e.g
cn=jsmith,ou=Sales,dc=rallencorp,dc=com
strNewUserDN = "<NewUserDN>" ' e.g
cn=rallen,ou=Sales,dc=rallencorp,dc=com"
' - SCRIPT CONFIGURATION -
Const ADS_PROPERTY_APPEND = 3
set objCurrentUser = GetObject("LDAP://" & strCurrentUserDN )
set objNewUser = GetObject("LDAP://" & strNewUserDN )
on error resume next
WScript.Echo "Transfering groups from " & strCurrentUserDN & " to " &
strNewUserDN
for each strGroupDN in objCurrentUser.GetEx("memberOf")
set objGroup = GetObject("LDAP://" & strGroupDN)
objGroup.PutEx ADS_PROPERTY_APPEND, "member", Array( strNewUserDN )
objGroup.SetInfo
if Err then
WScript.Echo "Error adding user to group: " & strGroupDN
else
Trang 9WScript.Echo "Added user to group: " & strGroupDN
end if
next
6.16.3 Discussion
Employees come and go; people take on new responsibilities and move on to new jobs It is common to have movement within an organization When this happens, typically someone is replacing the person that is moving on The new person needs to get up to speed as quickly as possible, including getting accounts set up and access to any necessary resources A big part of this includes getting added to the correct groups You can help facilitate this by using one of the processes outlined in the Solution section to help the user gain access to the exact same groups that the former employee was a member of
One important issue to point out is that the memberOf attribute, which was used in the Solution section to determine a user's group membership, contains only the groups in the same domain as the user Any groups the user is a member of outside of the user's domain, will not be transferred
To transfer group membership outside of a domain, you will need to perform a query against the global catalog for all group objects that have a member attribute that contains the DN of the user
6.16.4 See Also
Recipe 7.4 for adding and removing members of a group
Recipe 6.17 Setting a User's Password
6.17.1 Problem
You want to set the password for a user
6.17.2 Solution
6.17.2.1 Using a graphical user interface
1 Open the Active Directory Users and Computers snap-in
2 In the left pane, right-click on the domain and select Find
3 Select the appropriate domain beside In
4 Type the name of the user beside Name and click Find Now
5 In the Search Results, right-click on the user and select Reset Password
6 Enter and confirm the new password
7 Click OK
6.17.2.2 Using a command-line interface
This command changes the password for the user specified by <UserDN> Using * after the -pwd option prompts you for the new password You can replace * with the password you want to set,
Trang 10but it is not a good security practice since other users that are logged into the machine may be able to see it
> dsmod user <UserDN> -pwd *
6.17.2.3 Using VBScript
' This code sets the password for a user
' - SCRIPT CONFIGURATION -
strUserDN = "<UserDN>" ' e.g cn=jsmith,cn=Users,dc=rallencorp,dc=com
strNewPasswd = "NewPasword"
' - END CONFIGURATION -
set objUser = GetObject("LDAP://" & strUserDN)
objUser.SetPassword(strNewPasswd)
Wscript.Echo "Password set for " & objUser.Get("cn")
6.17.3 Discussion
The password for a user is stored in the unicodePwd attribute You cannot directly modify that attribute, but have to use one of the supported APIs See Recipe 6.18 to see how to set the
password using native LDAP and Recipe 6.19 for changing the password via Kerberos
With the VBScript solution, you can use the IADsUser::SetPassword method or
IADsUser::ChangePassword The latter requires the existing password to be known before setting it This is the method you'd want to use if you've created a web page that accepts the previous password before allowing a user to change it
6.17.4 See Also
Recipe 6.18 for setting the password via LDAP, Recipe 6.19 for setting the password via
Kerberos, MS KB 225511 (New Password Change and Conflict Resolution Functionality in Windows), MS KB 264480 (Description of Password-Change Protocols in Windows 2000), MSDN: IADsUser::SetPassword, and MSDN: IADsUser::ChangePassword
Recipe 6.18 Setting a User's Password via LDAP
6.18.1 Problem
You want to set the password for a user using LDAP
6.18.2 Solution
You have to first enable SSL/TLS support in your Active Directory domain See Recipe 14.1 for more on this
You can then set the unicodePwd attribute of a user object using LDAP operations over an SSL
or TLS connection