Archive for the ‘Read-Only Domain Controller’ Category

In the blog post (2009-01-01) Domain Join through an RODC instead of an RWDC I explained the so called read-only domain join against an RODC. In that blog post you will find a VBS script that helps you achieve that goal. Prior to the VBS script you see multiple ways of pre-creating the computer and having the password of the computer account replicate to the RODC.

–

In this blog post I provide an updated PowerShell script (don’t forget the execution policy on the server!) that performs the read-only domain join. You can get the PowerShell script through this link, or you can copy it from below.

The statement in figure 5 is incorrect. Because I selected "Retain Metadata" (see figure 3), the statement should be: "When the process is complete, this server will be a stand-alone server (non-domain joined)". When you retain the metadata of an RODC, it becomes "unoccupied" which allows you to attach to when promoting a new RODC with the same name.

If you did not select "Retain Metadata", the statement in figure 5 is correct.

My TEST environment, corporate forest with 2 AD domains and DMZ forest with 1 AD domain with 2 RWDCs and 2 RODCs, was running W2K12 and I still needed to update it to W2K12R2. Part of the test environment was already updated weeks ago. The only part left to upgrade were the RODCs. All RWDCs were already upgraded. So I demoted the RODCs, while keeping their metadata in place in the directory to use it later on during a new staged RODC promotion.

–

I started both RODC staged promotions at the same time and I did not expect any errors. Well, think again!

During the promotions I got the error: "While promoting Read-only Domain Controller, the expected state objects could not be found".

I saw the error in the PowerShell window as you can see below, and also in the debug log files.

You will not find ANY clue from anywhere what the problem is. So, after a long time searching and googling, I found some information about a TAPI3 partition. The problem is related to a directory partition, but not related to the partition being named TAPI3. Based upon that I decided to check the cross-references in my directory as you can see below.

Figure 3: ADSIEDIT – Cross-References For All Partitions In The Directory

–

And that’s when I noticed the partition "DC=RegionDnsZones,DC=ADDMZ,DC=LAN". I had totally forgotten about it! It was a partition I had created in the past to test replication of DNS zones.

See the difference? The cross-reference for the partition "DC=RegionDnsZones,DC=ADDMZ,DC=LAN", DOES NOT list any replica hosting the partition, and THAT is what is wrong here.

During my upgrade from W2K12 to W2K12R2 DCs (no in place upgrade, but rather replace) I had forgotten about this partition and unintentionally removed all hosting replicas without assigning new replicas. OOPS!

So, WHY does this go wrong with the RODC promotion? I reviewed the scripted PowerShell command I used, and I noticed the option "-ApplicationPartitionsToReplicate *". "*" basically means "go and look for all configured cross-references, enlist to host the partition and find a replica to inbound replicate the directory partition data". Everything goes right, up to the moment the RODC promotion is checking the cross-reference of the partition "DC=RegionDnsZones,DC=ADDMZ,DC=LAN" to find a replica. And as you can see, there are NO replicas specified. Although the definition of the partition is there, the so called cross-reference, the actual partition hosted on some replica is nowhere to be found! And that’s why the RODC promotion fails. It would be interesting and more helpful if the error was more intuitive/informative.

–

So, now the question: "how to solve this problem?". As always, that’s easy!

The solution is to delete the cross-reference, and for that I’m going to use NTDSUTIL. See below! You can either use the commands in the sub-menu "METADATA CLEANUP" or the commands in the sub-menu "PARTTION MANAGEMENT"

UPDATE 2017-03-16: There is an updated version which you can find here

–

In the blog post (2009-01-01) Domain Join through an RODC instead of an RWDC I explained the so called read-only domain join against an RODC. In that blog post you will find a VBS script that helps you achieve that goal. Prior to the VBS script you see multiple ways of pre-creating the computer and having the password of the computer account replicate to the RODC.

–

In this blog post I provide a PowerShell script (don’t forget the execution policy on the server!) that performs the read-only domain join. You can get the PowerShell script through this link, or you can copy it from below.

With this blog post I want to explain the difference in replication of regular data in AD and the replication of password, also when RODCs are included in the mix. The focus will be on replication of passwords.

–

One thing you can be sure of is that passwords do not replicate the same way and other data in the directory, especially between an RWDC and an RODC. Between RWDCs, passwords replicate like any other piece of data in the directory. In addition to that, the following ALSO applies:

When a password is changed/reset on some RWDC (the initial RWDC), that RWDC will automatically forward the password to the RWDC that hosts the PDC FSMO role. This occurs over the NetLogon secure channel the initial RWDC has with the RWDC hosting the PDC FSMO role. This is default behavior of RWDCs. The exception to this behavior (in other words, the password will not be forwarded) is when the “AvoidPdcOnWan” registry option has been configured on the initial RWDC (see: New Password Change and Conflict Resolution Functionality in Windows

When a user tries to authenticate against a specific RWDC (the initial RWDC) and the password provided does not match the password on that initial RWDC, then that RWDC will automatically retry authentication of that same user against the RWDC hosting the PDC FSMO role. If authentication against the RWDC hosting the PDC FSMO role succeeds, then the user can log on and the forwarding RWDC (the initial RWDC against which authentication was tried) will instantly inbound replicate the (new) password. This the default behavior. The exception to this behavior (in other words, authentication will not be forwarded) is when the “AvoidPdcOnWan” registry option has been configured on the initial RWDC (see: New Password Change and Conflict Resolution Functionality in Windows. If authentication against the RWDC with the PDC FSMO role fails, the user is presented with an error stating the username or password is incorrect.

The new password on both the initial RWDC and RWDC with the PDC FSMO role will replicate that new password in the normal way using AD replication to other RWDCs in the same AD domain, with or without change notification depending on the location of the RWDC (from an AD site perspective) and whether or not change notification has been enabled on one or more AD site links.

–

Between an RWDC and an RODC, the replication of passwords is a different story. A password NEVER replicates automatically from an RWDC to any RODC, no matter what happens! Remember though that this does not apply to password related metadata, such as for example the “pwdLastSet” attribute. The password related metadata does replicate automatically from an RWDC to an RODC. So, how does a password replicate from an RWDC to an RODC? One thing is for sure and that is that it will always occur on demand/request. Two on demand/request scenarios exist, being:

[1] the user authenticates against the RODC while the (new) password is not cached yet. In this case the RODC forwards authentication, because it does not have the password, to the RWDC with which the RODC has setup a secure channel with. After authentication the RODC uses the “replicate single object” method to get the latest password of that user account. The RWDC will only allow on demand/request replication of a password to the RODC when that account is explicitly listed in the “Allowed To Cache List” of that RODC and also not explicitly listed in the “Denied To Cache List” of that RODC. This of course will only work when the RODC can reach any RWDC. If the RODC cannot reach the RWDC, the authentication forwarding will not work and the inbound replication of the (new) password will also not work.

[2] the admin pre-populates the password of the user/computer account in question on the RODC using ADUC, scripting (e.g. PowerShell) or REPADMIN. Remember that, whatever the case, an RODC will ALWAYS try to inbound replicate the password using the “Replicate Single Object” method, whether or not the user/computer is listed in the “Allowed To Cache List”. It is the responsibility of the RWDC to enforce the password replication policy configuration such as the “Allowed To Cache List” and the “Denied To Cache List”. That’s WHY an RODC can only replicate the default domain NC from a W2K8 or higher RWDC and not from a W2K/W2K3 RWDC. The W2K/W2K3 RWDCs do not understand the password replication policy configuration of an RODC and will therefore not enforce it. When a password is changed/reset on an RWDC, the password related metadata (e.g. “pwdLastSet” attribute) is replicated to the RODC. Based upon that information the RODC knows the locally stored password (if any) is not valid anymore in the AD domain and will therefore invalidate it. After that it will try to inbound replicate the (new) password using the “replicate single object” method.

Windows Server 2008 introduces one of the coolest features in AD, being IMHO the Read-Only Domain Controller (RODC). The main goal of the RODC is to improve the AD security and to mitigate risks. It is therefore also preferably deployed at the perimeter of the network. Based upon that, three different scenarios/deployments exist:

RODC in a Branch Office (= primary focus!)

RODC in the DMZ (under investigation by MS)

RODC on the internet (under investigation by MS)

With regards to the RODC, Microsoft created a planning and deployment guide. This guide can be found here. Additionally Microsoft also released a RODC Compatibility Pack which can be found here.

The RODC needs to be able to "talk" to a writable W2K8 DC (W2K8 RWDC) for replication, authentication forwarding, etc. In all three scenarios it is very feasible to place a firewall between RWDCs and RODCs, whereas only one or more RODCs can talk to one or more RWDCs. Clients and servers can make LDAP writes, which refer a client to a RWDC, or special writes which are forwarded by the RODC to an RWDC. For more info about this see the presentations HERE and HERE.

Joining clients to an AD domain is such an operation for which you normally require to contact an RWDC. However, in those scenarios where the Branch Office has been separated from the Datacenter by a firewall so that only the RODC can contact an RWDC, you cannot join clients in the normal way against an RODC. The reason? Well, only the RODC can contact an RWDC and the clients/servers cannot. Another way is to join the computer in the datacenter first and then ship it to the Branch Office. However, that may not be feasible. Another way is to join the computer against the RODC with a workaround. The steps for that are explained below.

On some RWDC perform the following steps:

(1) Pre-create a computer account and set a custom password on that same computer account:

From a command line: net computer \<NetBIOS Name Computer> /add & net user <NetBIOS Name Computer>$ <Password> (additional attributes must be set afterwards such as "dNSHostName", "servicePrincipalName"!) (Be aware that this way the "userAccountControl" attribute contains an incorrect value. I’m saying "incorrect" because the bit "Password Not Required is also set" and that’s something I do not like!) OR

Using ADUC: By selecting the computer account of the RODC and selecting the tab "Password Replication Policy" and clicking the Advanced button and clicking the Prepopulate Passwords button to pre-cache the password on the RODC OR

On the client or server to be joined to the AD domain using an RODC implement the following script (DomainJoinAgainstRODC.vbs) and execute it:

Const JOIN_DOMAIN =1' Joins a computer to a domain. If this value is not specified, the join is a computer to a workgroupConst ACCT_CREATE =2' Creates an account on a domainConst ACCT_DELETE =4' Deletes an account when a domain existsConst WIN9X_UPGRADE =16' The join operation is part of an upgrade from Windows 98 or Windows 95 to Windows 2000 or Windows NTConst DOMAIN_JOIN_IF_JOINED =32' Allows a join to a new domain, even if the computer is already joined to a domainConst JOIN_UNSECURE =64' Performs an unsecured joinConst MACHINE_PASSWORD_PASSED =128' The machine, not the user, password passed. This option is only valid for unsecure joinsConst DEFERRED_SPN_SET =256' Writing SPN and DnsHostName attributes on the computer object should be deferred until the rename that follows the joinConst NETSETUP_JOIN_READONLY =2048' Use an RODC to perform the domain join againstConst INSTALL_INVOCATION =262144' The APIs were invoked during install
strDomain ="ADCORP.LAB"' The FQDN of the AD domainstrRODC ="RFSRODC1.ADCORP.LAB"' The FQDN of the RODC to usestrPassword ="Pa$$w0rd"' The custom password for the computer accountSet objNetwork =CreateObject("WScript.Network")
strComputer = objNetwork.ComputerName ' The NetBIOS name of the local computerSet objComputer =GetObject("winmgmts:{impersonationLevel=Impersonate}!\"& strComputer &"rootcimv2:Win32_ComputerSystem.Name='"& strComputer &"'")
Wscript.echo("### STARTING ###")
Wscript.echo("Trying to join the local computer to the AD domain using an RODC...")
Wscript.echo("")
ReturnValue = objComputer.JoinDomainOrWorkGroup(strDomain &""& strRODC, strPassword, NULL, NULL, JOIN_DOMAIN+MACHINE_PASSWORD_PASSED+NETSETUP_JOIN_READONLY)
' List of 'system error codes' (http://msdn.microsoft.com/en-us/library/ms681381.aspx) and
' List of 'network management error codes' (http://msdn.microsoft.com/en-us/library/aa370674(VS.85).aspx)SelectCase ReturnValue
Case0 strErrDescr ="The operation completed successfully"Case5 strErrDescr ="Access is denied"Case87 strErrDescr ="The parameter is incorrect"Case1326 strErrDescr ="Logon failure: unknown username or bad password"Case1355 strErrDescr ="The specified domain either does not exist or could not be contacted"Case2691 strErrDescr ="The machine is already joined to the domain"EndSelect
Wscript.echo("FQDN AD Domain : '"& strDomain &"'")
Wscript.echo("FQDN RODC : '"& strRODC &"'")
Wscript.echo("Local Computer Name : '"& strComputer &"."& strDomain &"'")
Wscript.echo("Domain Join Result Code : '"& ReturnValue &"'")
Wscript.echo("Domain Join Result Text : '"& strErrDescr &"'")
Wscript.echo("")
Wscript.echo("### FINISHED ###")

Execute the VBS script: CSCRIPT DomainJoinAgainstRODC.vbs

Depending in the current condition of the client you may receive an output similar to the picture below.

When:

Domain Join Result Code : ‘0’

Domain Join Result Text : ‘The operation completed successfully’

Then the client is successfully joined to the AD domain!

Let’s analyze a few parts of the script….

(1) The name of the RODC is specified. Why is this required? When a client/server joins an AD domain it queries DNS for DCs that have registered the domain-wide SRV resource records. RODCs by default DO NOT register domain-wide SRV resource records, only site-wide SRV resource records! Because of that, you must specify in the script WHICH DC the client/server must contact for the domain join

(2) You must specify the custom password that has been configured on the computer account in AD

(3) You need to specify the option ‘JOIN_DOMAIN’ to make sure it joins a DOMAIN and not a WORKGROUP

(4) You need to specify the option ‘MACHINE_PASSWORD_PASSED’ to make sure you pass the password that has been configured on the AD account and NOT credentials that are allowed to make the join. The authentication/authorization of the domain join occurs by just knowing the password that has been configured on the AD computer account!

(5) You need to specify the option ‘NETSETUP_JOIN_READONLY’ to make the join is made in READ-ONLY mode

A DC (for both RODCs/RWDCs) can be (un)assigned the GC role by just configuring a checkbox in Active Directory Sites And Services or using REPADMIN or some other tool that configures the feature. To switch between a RWDC and a RODC (or the other way around), you must always first demote, reboot and promote to whatever you want.

However, the RODC is untrusted. The RWDC is very trusted. From a security perspective I do not recommend to promote any server to a RWDC that was an RODC or a member server when:

it was previously managed by a non-domain admin

the server did not have any physical security

the server was from a network perspective located in an unsecure network segment

everything else that is non-trusted or insecure

Why? Because if the member server or the RODC has been compromised before the promotion, the person/thing (probably a hacker or a non-Domain Admins or malicious software) causing the compromise can become a domain/enterprise admin by using the power of the RWDC after the promotion to a RWDC.

So, if you do not trust the member server and/or the RODC that should become a RWDC, rebuild it from scratch! And after doing all this, don’t allow physical access or interactive logon access to ANY non-Domain Admin for ANY RWDC. The same is true for backups, snapshots and IFM sets from ANY RWDC!

I would not have any problems when the switch goes from a RWDC to a RODC. But, what is the world without having good friends watching over your shoulder? Thanks Dean!

I was made aware of a scenario that could occur when you want to switch from a RWDC to an RODC. "Now what" you may thing? Well, during the demotion of the RWDC to a member server or a stand alone server the writable NTDS.DIT file is removed/delete. So? Let’s say it becomes a stand alone server and the Domain Admin wants to replace the RWDC with an RODC using a staged (delegated) demotion [1]. The Domain Admin performs the first stage by pre-creating the RODC objects in AD and delegated the second stage to a NON-Domain Admin. The NON-Domain Admin logs to the stand alone server for the second stage. The NON-Domain Admin hates the other Domain Admins because he is not a Domain Admin or for whatever reason he would do anything to become one or just do some damage to the environment. Because the Domain Admin knows the stand alone server WAS an RWDC, the NTDS.DIT is still on the hard disk of the server and could be recovered using whatever UNDELETE/RECOVERY software that recovers deleted/lost files. From the recovered NTDS.DIT he could hack his way into the NTDS.DIT and extract the password hashes. Having the password hashes he could crack the password hashes to real passwords and misuse them. But why all the trouble and work? Why not just use the password hash with a "RUNAS-like" tool? That kinda software is also available on the internet!!! In the end he is able to misuse the password hash of the Domain Admin accounts and do all kinds of stuff that can turn into one heck of a nightmare!

So what can you do? After the demotion of the RWDC, do not hand-over the server to the NON-Domain Admin right away. Use the CIPHER tool (by default in the OS) to really remove data from unused disk space. The command for that is: CIPHER /W:<(Top)Folder that contained the NTDS.DIT>

[1] Regarding staged/delegated promotions for RODC see my slides from DEC 2008 and TechDays 2008 which you will find on my blog in different posts