ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


Cooking with Active Directory

by Robbie Allen
09/22/2003

Related Reading

Active Directory Cookbook
By Robbie Allen

Editor's note: Active Directory Cookbook contains hundreds of step-by-step solutions for common and uncommon problems system administrators encounter with Active Directory. To provide a sense of the kind of examples you'll find in the book, we present two sample recipes: the first from Chapter 3, "Domain Controllers, Global Catalogs, and FSMOs" and the second from Chapter 6, "Users."

Recipe 3.25: Finding the FSMO Role Holders

Problem

You want to find the domain controllers that are acting as one of the FSMO roles.

Solution

Using a graphical user interface

For the Schema Master:

  1. Open the Active Directory Schema snap-in.
  2. Right-click on Active Directory Schema in the left pane and select Operations Master.

For the Domain Naming Master:

  1. Open the Active Directory Domains and Trusts snap-in.
  2. Right-click on Active Directory Domains and Trusts in the left pane and select Operations Master.

For the PDC Emulator, RID Master, and Infrastructure Master:

  1. Open the Active Directory Users and Computers snap-in.
  2. Make sure you've targeted the correct domain.
  3. Right-click on Active Directory Users and Computers in the left pane and select Operations Master.
  4. There are individual tabs for the PDC, RID, and Infrastructure roles.

Using a command-line interface

In the following command, you can leave out the /Domain <DomainDNSName> option to query the domain you are currently logged on.

> netdom query fsmo /Domain:<DomainDNSName>

For some reason, this command returns a "The parameter is incorrect" error on Windows Server 2003. Until that is resolved, you can use the dsquery server command shown here, where <Role> can be schema, name, infr, pdc, or rid:

> dsquery server -hasfsmo <Role>

Using VBScript

' This code prints the FSMO role owners for the specified domain.
' ------ SCRIPT CONFIGURATION ------
strDomain = "<DomainDNSName>"  ' e.g. emea.rallencorp.com
' ------ END CONFIGURATION ---------
 
set objRootDSE = GetObject("LDAP://" & strDomain & "/RootDSE")
strDomainDN  = objRootDSE.Get("defaultNamingContext")
strSchemaDN = objRootDSE.Get("schemaNamingContext")
strConfigDN = objRootDSE.Get("configurationNamingContext")
 
' PDC Emulator
set objPDCFsmo = GetObject("LDAP://" & strDomainDN)
Wscript.Echo "PDC Emulator: " & objPDCFsmo.fsmoroleowner
 
' RID Master
set objRIDFsmo = GetObject("LDAP://cn=RID Manager$,cn=system," _
                           & strDomainDN)
Wscript.Echo "RID Master: " & objRIDFsmo.fsmoroleowner
 
' Schema Master
set objSchemaFsmo = GetObject("LDAP://" & strSchemaDN)
Wscript.Echo "Schema Master: " & objSchemaFsmo.fsmoroleowner
 
' Infrastructure Master
set objInfraFsmo = GetObject("LDAP://cn=Infrastructure," _ 
                             & strDomainDN)
Wscript.Echo "Infrastructure Master: " & objInfraFsmo.fsmoroleowner
 
' Domain Naming Master
set objDNFsmo = GetObject("LDAP://cn=Partitions," & strConfigDN)
Wscript.Echo "Domain Naming Master: " & objDNFsmo.fsmoroleowner 

Discussion

Several Active Directory operations are sensitive, such as updating the schema, and therefore, need to be done on a single domain controller. Active Directory cannot guarantee the proper evaluation of these functions in a situation where they may be invoked from more than one DC. The FSMO mechanism is used to limit these functions to a single DC.

There are five designated FSMO roles that correspond to these sensitive functions. A FSMO role can apply either to an entire forest or to a specific domain. Each role is stored in the fSMORoleOwner attribute on various objects in Active Directory depending on the role. Table 3-4 contains a list of FSMO roles.

Table 3-4: FSMO roles
Role Description fSMORoleOwner Location Domain or Forest-wide?
Schema Processes schema updates CN=Schema,CN=Configuration,<ForestDN> Forest
Domain Naming Processes the addition, removal, and renaming of domains CN=Partitions,CN=Configuration,<ForestDN> Forest
Infrastructure Maintains references to objects in other domains CN=Infrastructure,<ForestDN> Domain
RID Handles RID pool allocation for the domain controllers in a domain CN=Rid Manager$, CN=System,<DomainDN> Domain
PDC Emulator Acts as the Windows NT master browser and also as the PDC for downlevel clients and Backup Domain Controllers (BDCs) <DomainDN> Domain

Using VBScript

If you want to get the DNS name for each FSMO, you'll need to get the parent object of the nTDSDSA object and use the dNSHostName attribute, similar to "Finding the Domain Controllers for a Domain." The code for getting the Schema Master could be changed to the following to retrieve the DNS name of the DC:

set objSchemaFsmo = GetObject("LDAP://cn=Schema,cn=Configuration," _
                                         & strForestDN)
set objSchemaFsmoNTDS = GetObject("LDAP://" & objSchemaFsmo.fsmoroleowner)
set objSchemaFsmoServer = GetObject(objSchemaFsmoNTDS.Parent)
Wscript.Echo "Schema Master: " & objSchemaFsmoServer.Get("dNSHostName")

See Also

MS KB 197132 (Windows 2000 Active Directory FSMO Roles), MS KB 223346 (FSMO Placement and Optimization on Windows 2000 Domain Controllers), MS KB 234790 (HOW TO: Find Servers That Hold Flexible Single Master Operations Roles), and MS KB 324801 (HOW TO: View and Transfer FSMO Roles in Windows Server 2003)

Recipe 6.27: Determining a User's Last Logon Time

TIP:   This recipe requires the Windows Server 2003 forest functional level.

Problem

You want to determine the last time a user logged into a domain.

Solution

Using a graphical user interface

If you install the AcctInfo.dll extension to Active Directory Users and Computers, you can view the last logon timestamp.

TIP:   AcctInfo.dll can be downloaded from the Microsoft download site:

http://microsoft.com/downloads/
details.aspx?FamilyId=7AF2E69C-
91F3-4E63-8629-B999ADDE0B9E&
displaylang=en

  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. Beside Name, type the name of the user you want to modify and click Find Now.
  5. In the Search Results, double-click on the user.
  6. Click the Additional Account Info tab.
  7. View the value for Last-Logon-Timestamp.

Using VBScript

' This code prints the last logon timestamp for a user.
' ------ SCRIPT CONFIGURATION ------
strUserDN = "<UserDN>"  ' e.g. cn=rallen,ou=Sales,dc=rallencorp,dc=com
' ------ END CONFIGURATION ---------
 
set objUser =  GetObject("LDAP://" & strUserDN)
set objLogon = objUser.Get("lastLogonTimestamp")
intLogonTime = objLogon.HighPart * (2^32) + objLogon.LowPart 
intLogonTime = intLogonTime / (60 * 10000000)
intLogonTime = intLogonTime / 1440
WScript.Echo "Approx last logon timestamp: " & intLogonTime + #1/1/1601#

Discussion

Trying to determine when a user last logged on has always been a challenge in the Microsoft NOS environment. In Windows NT, you could retrieve a user's last logon timestamp from a PDC or BDC, but this timestamp was the last time the user logged on to the PDC or BDC. That means in order to determine the actual last logon, you'd have to query every domain controller in the domain. In large environments, this wasn't practical. With Windows 2000 Active Directory, things did not improve much. A lastLogon attribute is used to store the last logon timestamp, but unfortunately, this attribute isn't replicated. So again, to get an accurate picture, you'd have to query every domain controller in the domain for the user's last logon attribute and keep track of the most recent one.

Now with Windows Server 2003, we finally have a viable solution. A new attribute was added to the schema for user objects called lastLogonTimestamp. This attribute is similar to the lastLogon attribute that was available previously, with two distinct differences. First, and most importantly, this attribute is replicated. That means when a user logs in, the lastLogonTimestamp attribute will get populated and then replicate to all domain controllers in the domain.

The second difference is that since lastLogonTimestamp is replicated, special safeguards needed to be put in place so that users that logged in repeatedly over a short period of time did not cause unnecessary replication traffic. For this reason, the lastLogonTimestamp is updated only if the last update occurred a week or more ago. This means that the lastLogonTimestamp attribute could be up to a week off in terms of accuracy with a user's actual last logon. Ultimately, this shouldn't be a problem for most situations because lastLogonTimestamp is intended to address the common problem where administrators want to run a query and determine which users have not logged in over the past month or more.

See Also

"Finding Users Who Have Not Logged On Recently."

Be sure to check back to this space in two weeks for more recipes from Active Directory Cookbook on modifying an attribute for several users at once and viewing the nested members of a group.

Robbie Allen is the coauthor of Active Directory, 2nd Edition and the author of the Active Directory Cookbook.


Return to ONDotnet.com

Copyright © 2009 O'Reilly Media, Inc.