In this article we will be having a look at how the Log On To list is populated. This is the list in windows XP/2003 where users can select which domain they are logging into from a drop down list.
I decided to blog this as I spent a morning working out how this worked, and there is little documentation on the Internet.
So where does this list come from?
The logon list is stored from a DomainCache registry key located under:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DomainCache
How does this list populate?
Windows populates the DomainCache registry key from a file called C:\WINDOWS\system32\config\netlogon.ftl.
The DomainCache registry key gets updated from netlogon.ftl as part of the computer boot process and whenever a remote desktop connection is established based on my testing.
Here I added a string record to the DomainCache called CLINTY pointing at a fake domain called clint.local. I then locked my PC, you can see it appear in the list.
If I remote desktop my machine or reboot the PC, it repopulates the DomainCache from netlogon.ftl. Here I remote desktoped my PC, you can see in process monitor it did the repopulation.
When it repopulated the DomainCache from netlogon.ftl, it deleted my CLINTY record.
What populates netlogon.ftl?
The netlogon.ftl file is populated from Active Directory by the netlogon service - I think this occurs when the system boots... but I'm not sure.
Where in Active Directory does netlogon.ftl populate from?
It the defaultNamingContext partition under the System container. It populates from the TrustedDomain object types.
You can also query this information using nltest or a VBScript:
nltest /domain_trusts
Here is a copy of the VB Script used in the above screenshot.
' This code prints the trusts for the specified domain.
' ------ SCRIPT CONFIGURATION ------
strDomain = "wfi.wan"
' ------ END CONFIGURATION ---------
' Trust Direction Constants taken from NTSecAPI.h
set objTrustDirectionHash = CreateObject("Scripting.Dictionary")
objTrustDirectionHash.Add "DIRECTION_DISABLED", 0
objTrustDirectionHash.Add "DIRECTION_INBOUND", 1
objTrustDirectionHash.Add "DIRECTION_OUTBOUND", 2
objTrustDirectionHash.Add "DIRECTION_BIDIRECTIONAL", 3
' Trust Type Constants - taken from NTSecAPI.h
set objTrustTypeHash = CreateObject("Scripting.Dictionary")
objTrustTypeHash.Add "TYPE_DOWNLEVEL", 1
objTrustTypeHash.Add "TYPE_UPLEVEL", 2
objTrustTypeHash.Add "TYPE_MIT", 3
objTrustTypeHash.Add "TYPE_DCE", 4
' Trust Attribute Constants - taken from NTSecAPI.h
set objTrustAttrHash = CreateObject("Scripting.Dictionary")
objTrustAttrHash.Add "ATTRIBUTES_NON_TRANSITIVE", 1
objTrustAttrHash.Add "ATTRIBUTES_UPLEVEL_ONLY", 2
objTrustAttrHash.Add "ATTRIBUTES_QUARANTINED_DOMAIN", 4
objTrustAttrHash.Add "ATTRIBUTES_FOREST_TRANSITIVE", 8
objTrustAttrHash.Add "ATTRIBUTES_CROSS_ORGANIZATION", 16
objTrustAttrHash.Add "ATTRIBUTES_WITHIN_FOREST", 32
objTrustAttrHash.Add "ATTRIBUTES_TREAT_AS_EXTERNAL", 64
set objRootDSE = GetObject("LDAP://" & strDomain & "/RootDSE")
set objTrusts = GetObject("LDAP://cn=System," & _
objRootDSE.Get("defaultNamingContext") )
objTrusts.Filter = Array("trustedDomain")
Wscript.Echo "Trusts for " & strDomain & ":"
for each objTrust in objTrusts
for each strFlag In objTrustDirectionHash.Keys
if objTrustDirectionHash(strFlag) = objTrust.Get("trustDirection") then
strTrustInfo = strTrustInfo & strFlag & " "
end If
next
for each strFlag In objTrustTypeHash.Keys
if objTrustTypeHash(strFlag) = objTrust.Get("trustType") then
strTrustInfo = strTrustInfo & strFlag & " "
end If
next
for each strFlag In objTrustAttrHash.Keys
if objTrustAttrHash(strFlag) = objTrust.Get("trustAttributes") then
strTrustInfo = strTrustInfo & strFlag & " "
end If
next
WScript.Echo " " & objTrust.Get("trustPartner") & " : " & strTrustInfo
strTrustInfo = ""
next
Subscribe to:
Post Comments (Atom)
Interesting topic, very well written and documented, thank you
ReplyDeleteThanks for this article clint it has assisted my knowledge of what this file does and how it is updated. Much appreciated for your post.
ReplyDelete