Jorge's Quest For Knowledge!

All About Identity And Security On-Premises And In The Cloud – It's Just Like An Addiction, The More You Have, The More You Want To Have!

Archive for the ‘VB Script’ Category

(2011-07-10) Transferring And Seizing FSMO Roles Through GUI, Command Line Or PowerShell

Posted by Jorge on 2011-07-10


AD uses a multi-master replication mechanism, meaning that updates can originate on any RWDC. For all kinds of services AD is highly redundant assuming you have more than one RWDC. Within AD some operations cannot operate using the multi-master principle, but rather use the single-master principle to ensure consistency. The roles for those operations are the so called Flexible Single Masters of Operations (FSMO). From a forest perspective two forest wide FSMO roles exist and from a domain perspective three domain wide FSMO roles exist. Below you will find which one is which.

When FSMOs become unavailable, depending on the scenario you may need to transfer or seize the corresponding FSMO role(s). With regards to FSMO role transfer or seizure, please see "Moving FSMO Roles From One DC To Another DC". After a seizure the old FSMO role owner should never be brought online again. It should at least be force demoted while not connected to the network and its metadata in the AD should be cleaned.

To transfer/seize FSMOs through a GUI you can use:

  • AD Schema Management MMC (For Schema FSMO)
  • AD Domain And Trusts MMC (For Domain Naming Master FSMO)
  • AD Users And Computers MMC (For PDC FSMO, RID FSMO and IM FSMO)

If you want to do this through the command line or PowerShell you can also use:

  • NTDSUTIL
    • NTDSUTIL
    • Roles
    • Connections
    • Connect to server <FQDN NEW DC>
    • Quit
    • To Transfer FSMOs
      • Schema FSMO –> Transfer schema master
      • Domain Naming FSMO –> Transfer naming master
      • PDC FSMO –> Transfer PDC
      • RID FSMO –> Transfer RID master
      • Infrastructure FSMO –> Transfer infrastructure master
    • To Seize FSMOs
      • Schema FSMO –> Seize schema master
      • Domain Naming FSMO –> Seize naming master
      • PDC FSMO –> Seize PDC
      • RID FSMO –> Seize RID master
      • Infrastructure FSMO –> Seize infrastructure master
    • Quit
    • Quit
  • ADMOD
    • To Transfer FSMOs
      • Schema FSMO (leverages "becomeSchemaMaster" operational attribute) –> ADMOD [-h <FQDN NEW DC>] -sc xferschema
      • Domain Naming FSMO (leverages "becomeDomainMaster" operational attribute) –> ADMOD [-h <FQDN NEW DC>] -sc xferdm
      • PDC FSMO (leverages "becomePdc" operational attribute) –> ADMOD [-h <FQDN NEW DC>] -sc xferpdc:<domain SID> (<domain SID> can be found on the rooDSE of any DC in the objectSid attribute)
      • RID FSMO (leverages "becomeRidMaster" operational attribute) –> ADMOD [-h <FQDN NEW DC>] -sc xferrid
      • IM FSMO (leverages "becomeInfrastructureMaster" operational attribute) –> ADMOD [-h <FQDN NEW DC>] -sc xferim
    • To Seize FSMOs
      • Schema FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> ADMOD [-h <FQDN NEW DC>] -b "CN=Schema,CN=Configuration,DC=<forest root domain>,DC=<tld>" "fSMORoleOwner::CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>"
      • Domain Naming FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> ADMOD [-h <FQDN NEW DC>] -b "CN=Partitions,CN=Configuration,DC=<forest root domain>,DC=<tld>" "fSMORoleOwner::CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>"
      • PDC FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> ADMOD [-h <FQDN NEW DC>] -b "DC=<domain>,DC=<tld>" "fSMORoleOwner::CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>"
      • RID FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> ADMOD [-h <FQDN NEW DC>] -b "CN=RID Manager$,CN=System,DC=<domain>,DC=<tld>" "fSMORoleOwner::CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>"
      • IM FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> ADMOD [-h <FQDN NEW DC>] -b "CN=Infrastructure,DC=<domain>,DC=<tld>" "fSMORoleOwner::CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>"
  • Regular PowerShell CMDlets (leveraging ADSI)
    • To Transfer FSMOs
      • $objRootDSE = [ADSI]"LDAP://<FQDN NEW DC>/rootDSE"
      • Schema FSMO (leverages "becomeSchemaMaster" operational attribute) –> $objRootDSE.Put("becomeSchemaMaster", "1")
      • Domain Naming FSMO (leverages "becomeDomainMaster" operational attribute) –> $objRootDSE.Put("becomeDomainMaster", "1")
      • PDC FSMO (leverages "becomePdc" operational attribute) –> $objRootDSE.Put("becomePdc", (([adsi]"").objectsid)[0])
      • RID FSMO (leverages "becomeRidMaster" operational attribute) –> $objRootDSE.Put("becomeRidMaster", "1")
      • Infrastructure FSMO (leverages "becomeInfrastructureMaster" operational attribute) –> $objRootDSE.Put("becomeInfrastructureMaster", "1")
      • $objRootDSE.SetInfo()
    • To Seize FSMOs
      • Schema FSMO (just hijacks the attribute by writing new attribute value, no checks performed)
        • $objDN = [ADSI]"LDAP://<FQDN NEW DC>/CN=Schema,CN=Configuration,DC=<forest root domain>,DC=<tld>"
        • $objDN.Put("fSMORoleOwner", "CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>")
        • $objDN.SetInfo()
      • Domain Naming FSMO (just hijacks the attribute by writing new attribute value, no checks performed)
        • $objDN = [ADSI]"LDAP://<FQDN NEW DC>/CN=Partitions,CN=Configuration,DC=<forest root domain>,DC=<tld>"
        • $objDN.Put("fSMORoleOwner", "CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>")
        • $objDN.SetInfo()
      • PDC FSMO (just hijacks the attribute by writing new attribute value, no checks performed)
        • $objDN = [ADSI]"LDAP://<FQDN NEW DC>/DC=<domain>,DC=<tld>"
        • $objDN.Put("fSMORoleOwner", "CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>")
        • $objDN.SetInfo()
      • RID FSMO (just hijacks the attribute by writing new attribute value, no checks performed)
        • $objDN = [ADSI]"LDAP://<FQDN NEW DC>/CN=RID Manager$,CN=System,DC=<domain>,DC=<tld>"
        • $objDN.Put("fSMORoleOwner", "CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>")
        • $objDN.SetInfo()
      • IM FSMO (just hijacks the attribute by writing new attribute value, no checks performed)
        • $objDN = [ADSI]"LDAP://<FQDN NEW DC>/CN=Infrastructure,DC=<domain>,DC=<tld>"
        • $objDN.Put("fSMORoleOwner", "CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<forest root domain>,DC=<tld>")
        • $objDN.SetInfo()
  • W2K8R2 AD PowerShell CMDlets
    • Import-Module ActiveDirectory
    • To Transfer FSMOs
      • Schema FSMO –> Move-ADDirectoryServerOperationMasterRole -Identity <FQDN NEW DC> -OperationMasterRole SchemaMaster
      • Domain Naming FSMO –> Move-ADDirectoryServerOperationMasterRole -Identity <FQDN NEW DC> -OperationMasterRole DomainNamingMaster
      • PDC FSMO –> Move-ADDirectoryServerOperationMasterRole -Identity <FQDN NEW DC> -OperationMasterRole PDCEmulator
      • RID FSMO –> Move-ADDirectoryServerOperationMasterRole -Identity <FQDN NEW DC> -OperationMasterRole RIDMaster
      • Infrastructure FSMO –> Move-ADDirectoryServerOperationMasterRole -Identity <FQDN NEW DC> -OperationMasterRole InfrastructureMaster
    • To Seize FSMOs
      • Schema FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-ADObject [-Server <FQDN NEW DC>] -Identity "CN=Schema,CN=Configuration,DC=<forest root domain>,DC=<tld>" -Replace @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}
      • Domain Naming FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-ADObject [-Server <FQDN NEW DC>] -Identity "CN=Partitions,CN=Configuration,DC=<forest root domain>,DC=<tld>" -Replace @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}
      • PDC FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-ADObject [-Server <FQDN NEW DC>] -Identity "DC=<domain>,DC=<tld>" -Replace @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}
      • RID FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-ADObject [-Server <FQDN NEW DC>] -Identity "CN=RID Manager$,CN=System,DC=<domain>,DC=<tld>" -Replace @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}
      • IM FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-ADObject [-Server <FQDN NEW DC>] -Identity "CN=Infrastructure,DC=<domain>,DC=<tld>" -Replace @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}
  • Quest AD PowerShell CMDlets
    • Add-PSSnapin Quest.ActiveRoles.ADManagement
    • To Transfer FSMOs
      • I have not been able to achieve this with the Quest PowerShell CMDlets. Use the regular PowerShell CMDlets instead which leverage ADSI (see above)
    • To Seize FSMOs
      • Schema FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-QADObject -Identity "CN=Schema,CN=Configuration,DC=<forest root domain>,DC=<tld>" -ObjectAttributes @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}
      • Domain Naming FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-QADObject -Identity "CN=Partitions,CN=Configuration,DC=<forest root domain>,DC=<tld>" -ObjectAttributes @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}
      • PDC FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-ADObject -Identity "DC=<domain>,DC=<tld>" -ObjectAttributes @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}
      • RID FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-ADObject -Identity "CN=RID Manager$,CN=System,DC=<domain>,DC=<tld>" -ObjectAttributes @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}
      • IM FSMO (just hijacks the attribute by writing new attribute value, no checks performed) –> Set-ADObject -Identity "CN=Infrastructure,DC=<domain>,DC=<tld>" -ObjectAttributes @{fSMORoleOwner=’CN=NTDS Settings,CN=<New DC Name>,CN=Servers,CN=<Site Name>,CN=Sites,CN=Configuration,DC=<domain>,DC=<tld>’}

For more information about FSMO roles see "Operations master roles" and "FSMO Roles".

Cheers,
Jorge
———————————————————————————————
* This posting is provided "AS IS" with no warranties and confers no rights!
* Always evaluate/test yourself before using/implementing this!
* DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
———————————————————————————————
############### Jorge’s Quest For Knowledge #############
#########
http://JorgeQuestForKnowledge.wordpress.com/ ########
———————————————————————————————

Advertisement

Posted in Active Directory Domain Services (ADDS), Batch Script, FSMO, PowerShell, Tooling/Scripting, VB Script | 1 Comment »

(2009-01-01) Domain Join through an RODC instead of an RWDC

Posted by Jorge on 2009-01-01


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
  • From a command line: ADMOD -replacedn XXX-DOMAIN-XXX:_default -add -b "CN=<NetBIOS Name Computer>,OU=<SOME OU>,XXX-DOMAIN-XXX" "objectClass::computer" "sAMAccountName:: <NetBIOS Name Computer>$" "userAccountControl::4096" -kerbenc "unicodePwd::<Password>" "dNSHostName::<NetBIOS Name Computer>.%USERDNSDOMAIN%" "servicePrincipalName:++:HOST/<NetBIOS Name Computer>;HOST/<NetBIOS Name Computer>.%USERDNSDOMAIN%"

(2) Allow the password of the computer account to be cached on the RODC

  • Use the AD domain wide ALLOW group: "Allowed RODC Password Replication Group" (for ALL RODCs)
    • Using ADUC: By selecting the computer account of the RODC and selecting the tab "Password Replication Policy" and choosing AD domain wide ALLOW group to add the computer account to
      OR
    • From a command line: net localgroup "Allowed RODC Password Replication Group" <NetBIOS Name Computer>$ /add
      OR
    • From a command line: ADMOD -replacedn XXX-DOMAIN-XXX:_default -b "CN=Allowed RODC Password Replication Group,CN=Users,XXX-DOMAIN-XXX" "member::CN=<NetBIOS Name Computer>,OU=<SOME OU>,XXX-DOMAIN-XXX"

    OR

  • Use the ALLOW group which is specific to the single RODC only
    • Using ADUC: By selecting the computer account of the RODC and selecting the tab "Password Replication Policy" and choosing the RODC specific ALLOW group to add the computer account to
      OR
    • From a command line: net (local)group "<ALLOW group specific to RODC>" <NetBIOS Name Computer>$ /add
      OR
    • From a command line: ADMOD -replacedn XXX-DOMAIN-XXX:_default -b "CN=<ALLOW group specific to RODC>,OU=<SOME OU>,XXX-DOMAIN-XXX" "member::CN=<NetBIOS Name Computer>,OU=<SOME OU>,XXX-DOMAIN-XXX"

(3) Force the computer account to be cached at the RODC

  • 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
  • From a command line: REPADMIN /RODCPWDREPL <RODC> <RWDC> "CN=<NetBIOS Name Computer>,OU=<SOME OU>,DC=<DOMAIN>,DC=<TLD>"

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 workgroup Const ACCT_CREATE = 2 ' Creates an account on a domain Const ACCT_DELETE = 4 ' Deletes an account when a domain exists Const WIN9X_UPGRADE = 16 ' The join operation is part of an upgrade from Windows 98 or Windows 95 to Windows 2000 or Windows NT Const DOMAIN_JOIN_IF_JOINED = 32 ' Allows a join to a new domain, even if the computer is already joined to a domain Const JOIN_UNSECURE = 64 ' Performs an unsecured join Const MACHINE_PASSWORD_PASSED = 128 ' The machine, not the user, password passed. This option is only valid for unsecure joins Const DEFERRED_SPN_SET = 256 ' Writing SPN and DnsHostName attributes on the computer object should be deferred until the rename that follows the join Const NETSETUP_JOIN_READONLY = 2048 ' Use an RODC to perform the domain join against Const INSTALL_INVOCATION = 262144 ' The APIs were invoked during install strDomain = "ADCORP.LAB" ' The FQDN of the AD domain strRODC = "RFSRODC1.ADCORP.LAB" ' The FQDN of the RODC to use strPassword = "Pa$$w0rd" ' The custom password for the computer account Set objNetwork = CreateObject("WScript.Network") strComputer = objNetwork.ComputerName ' The NetBIOS name of the local computer Set 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) Select Case ReturnValue Case 0 strErrDescr = "The operation completed successfully" Case 5 strErrDescr = "Access is denied" Case 87 strErrDescr = "The parameter is incorrect" Case 1326 strErrDescr = "Logon failure: unknown username or bad password" Case 1355 strErrDescr = "The specified domain either does not exist or could not be contacted" Case 2691 strErrDescr = "The machine is already joined to the domain" End Select 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.

image

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

The procedure above works for: Windows Vista (and later), Windows Server 2008 (and later), Windows XP Professional SP2 (and later), Windows Server 2003 SP1 (and later). For both Windows XP Professional and Windows Server 2003 the hotfix specified in MS-KBQ944043_Description of the Windows Server 2008 read-only domain controller compatibility pack for Windows Server 2003 clients and for Windows XP clients *MUST* be installed! You will get a "Domain Join Result Code" of 87 (The parameter is incorrect) when the hotfix is NOT installed! Make sure it is installed!

More information:

Windows 7 (Windows Server 2008 R2) will provide an even cooler way of joining clients/servers to an AD domain. More of that later, so stay tuned!

Cheers,

Jorge

———————————————————————————————

* This posting is provided "AS IS" with no warranties and confers no rights!

* Always evaluate/test yourself before using/implementing this!

* DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/

———————————————————————————————

############### Jorge’s Quest For Knowledge #############

#########

http://JorgeQuestForKnowledge.wordpress.com/ ########

———————————————————————————————

Posted in Active Directory Domain Services (ADDS), Domain Join, Read-Only Domain Controller, Tooling/Scripting, VB Script | 22 Comments »

(2007-09-11) Determining The Effective PSO For A User

Posted by Jorge on 2007-09-11


In "Windows Server 2008 – Fine-Grained Password Policies" I explain the new password and account lockout feature/concept in Windows Server 2008. When using ADUC it is interesting to know what PSO is effective from some user, and better yet, what the settings are from that effective PSO. Of course you could use the new "Attribute Editor", and look at the value of the "msDS-ResultantPSO" attribute. After knowing that you to go into to "Password Settings Container". As explained in the previous post about FGPP you need to have at least ALLOW:read permissions on a PSO to be able to retrieve its settings. By default only "Enterprise Admins" and "Domain Admins" have that permission. Also as explained in the post, you can configure a certain group to be able to read PSO settings.

Assuming the permissions are in place, you could also write your own tool/script to retrieve the effective PSO and its settings. Stop! Don’t do that. Somebody else already created a kick a$$ tool to manage/read/create/delete PSOs. Well have a look at PSOMGR from joeware.net.

What I did was to adjust the admin contextmenu for user objects and add a new option. That option performs retrieves the effective PSO and reads the that PSO’s settings. When choosing that action a script is executed which runs the tool and shows you the info. Have a look at the picture below.

image

To create the new context option for user objects, execute the following:

  • ADMOD -replacedn XXX-CONFIG-XXX:_config -b "CN=user-Display,CN=409,CN=DisplaySpecifiers,XXX-CONFIG-XXX" "adminContextMenu:+:99,Effective PSO Settings,D:\TOOLS\CONFIG\COMMON\Effective-PSO-On-User-Object.vbs"
    • Change "409" into the locale of the OS you are using. 409 is US English
    • Change "Effective PSO Settings" into whatever name the contextmenu option should have
    • Change "D:\TOOLS\CONFIG\COMMON\Effective-PSO-On-User-Object.vbs" into a central network location where you can find the script "Effective-PSO-On-User-Object.vbs" (that location must be available from whatever computer doing this)

 

 

The contents of "Effective-PSO-On-User-Object.vbs" is:

Option Explicit Dim WshShell Dim wshArguments, objRootDSE Dim strDomainControllerFLnum, strDomainFLnum Dim strUser, Return On Error Resume Next Const cPSOMGR = "D:\TOOLS\MISC\PSOMgr.exe" ' CHANGE THIS TO A CENTRAL LOCATION WHERE YOU CAN FIND PSOMGR Set WshShell = Wscript.CreateObject("Wscript.Shell") Set objFSO = CreateObject("Scripting.FileSystemObject") Set wshArguments = WScript.Arguments Set objRootDSE = GetObject("LDAP://RootDSE") strDomainControllerFLnum=objRootDSE.Get("domainControllerFunctionality") strDomainFLnum=objRootDSE.Get("domainFunctionality") If Int(strDomainControllerFLnum) < "3" Then Wscript.Echo("This feature can only be used on W2K8 DCs! The script will now stop.") Call srClearDimVars() Wscript.Quit(1) End If If Int(strDomainFLnum) < "3" Then Wscript.Echo("This feature can only be used on W2K8 DCs when the domain functional level is at least 'Windows Server 2008'! The script will now stop.") Call srClearDimVars() Wscript.Quit(1) End If If objFSO.FileExists(cPSOMGR) Then Else Wscript.Echo("The file location '" & cPSOMGR & "' does not exist! The script will now stop.") Call srClearDimVars() Wscript.Quit(1) End If strUser = Right(wshArguments(0), Len(wshArguments(0))-Instr(wshArguments(0),"CN=")+1) Return = WshShell.Run("CMD /C" & cPSOMGR & " /EFFECTIVE " & Chr(34) & strUser & Chr(34) & " " & Chr(38) & " PAUSE", 1, true) Sub srClearDimVars() On Error Resume Next Set WshShell = Nothing Set wshArguments = Nothing Set objRootDSE = Nothing Set strDomainControllerFLnum = Nothing Set strDomainFLnum = Nothing Set strUser = Nothing Set Return = Nothing End Sub

UPDATE:

Interesting to know is that you can also use DSGET to retrieve the effective PSO on a user object

  • dsget user <User-DN> -effectivepso

Also see: Step-by-Step Guide for Fine-Grained Password and Account Lockout Policy Configuration

 

Cheers,

Jorge

———————————————————————————————

* This posting is provided "AS IS" with no warranties and confers no rights!

* Always evaluate/test yourself before using/implementing this!

* DISCLAIMER:

https://jorgequestforknowledge.wordpress.com/disclaimer/

———————————————————————————————

############### Jorge’s Quest For Knowledge #############

#########

http://JorgeQuestForKnowledge.wordpress.com/ ########

———————————————————————————————

Posted in Active Directory Domain Services (ADDS), Fine Grained Password Policies, VB Script | 8 Comments »

(2006-11-15) Finding Unused GPOs

Posted by Jorge on 2006-11-15


In time you may have gone crazy and created and used a lot of GPOs. Some may be disabled, not be linked, be orphaned in the SYSVOL or not have any setting configured. So how can you check which GPO does meets the criteria mentioned above without going into some GUI and check each and every GPO?

The answer is easy! GPMC is your friend! 😉

To find disabled GPOs in the AD domain (FindDisabledGPOs.wsf)

  • This will output all GPOs in the AD domain that are completely disabled, only computer is disabled or only user part is disabled
    • cscript FindDisabledGPOs.wsf /domain:<FQDN AD domain>

To find unlinked GPOs in the AD domain (FindUnlinkedGPOs.wsf)

  • This will output all GPOs in the AD domain that are not linked to any OU within the AD domain or the AD domain itself. It will not check sites or other AD domains in the forest.
    • cscript FindUnlinkedGPOs.wsf /domain:<FQDN AD domain>

To find unlinked GPOs in the AD domain (FindOrphanedGPOsInSYSVOL.wsf)

  • This will output all GPOs that exist in the SYSVOL but not in the AD domain anymore.
    • cscript FindOrphanedGPOsInSYSVOL.wsf /domain:<FQDN AD domain>

To find GPOs with NO settings defined in both the computer part and user part (GetReportsForAllGPOs.wsf)

  • This will create a report for EACH GPO in the AD domain (HTML and XML files).
    • cscript GetReportsForAllGPOs.wsf <location for reports> /domain:<FQDN AD domain>
  • The following wil check each HTML file for the string "No Settings Defined" and when found it will output the name of the GPO into the TXT file. Put the script in the same location as the GPO reports. Each GPO that lists "No Settings Defined" TWICE has no GPO settings configured.
    • GPOsWithSettingsOrNot.CMD (see contents of script below)
      • @ECHO OFF
      • CLS
      • IF EXIST "GPOsWithSettingsOrNot.txt" (DEL GPOsWithSettingsOrNot.txt)
      • FOR /F "tokens=*" %%A IN (‘DIR /B "*.HTML"’) DO (
      • FIND /i "No settings defined" "%%A" >> GPOsWithSettingsOrNot.txt
      • )
      • NOTEPAD GPOsWithSettingsOrNot.txt

The output of "GPOsWithSettingsOrNot.txt" looks like (red colored GPOs have no GPO Settings defined in both computer and user part):

———- CLIENTS POLICY.HTML

———- CUSTOM DOMAIN CONTROLLERS POLICY.HTML

———- DEFAULT DOMAIN CONTROLLERS POLICY.HTML
<div class="container"><div class="he4i">No settings defined.</div></div>

———- DEFAULT DOMAIN POLICY.HTML

———- DEFRAG SETTINGS.HTML
<div class="container"><div class="he4i">No settings defined.</div></div>

———- MEMBER SERVERS POLICY.HTML

———- NEW GROUP POLICY OBJECT.HTML
<div class="container"><div class="he4i">No settings defined.</div></div>
<div class="container"><div class="he4i">No settings defined.</div></div>

———- TEST.HTML
<div class="container"><div class="he4i">No settings defined.</div></div>
<div class="container"><div class="he4i">No settings defined.</div></div>

Cheers,
Jorge
———————————————————————————————
* This posting is provided "AS IS" with no warranties and confers no rights!
* Always evaluate/test yourself before using/implementing this!
* DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
———————————————————————————————
############### Jorge’s Quest For Knowledge #############
#########
http://JorgeQuestForKnowledge.wordpress.com/ ########
———————————————————————————————

Posted in Active Directory Domain Services (ADDS), Batch Script, VB Script | Leave a Comment »

(2006-05-17) Large Integers And VBS Or BATCH

Posted by Jorge on 2006-05-17


For a script I was writing, I needed to work with large integers.

 

Example code in VBS was to compare very large numeric numbers:

Dim LargestValue LargestValue=0 AR = Array("134234","22342399999999999994","9","555555555577698","6","5") For l = 0 to UBound(AR) If LargestValue < Int(AR(l)) then LargestValue = Int(AR(l)) End If Next wscript.echo LargestValue

As you can see 22342399999999999994 is the largest value and it should be returned as such. Well it does, almost…

However, it does not say (and that is what I would like!):

22342399999999999994

but it says:

2.23424E+19

As soon as a numeric value gets a certain size it converts it to x.xxxxE+y

Example code in VBS was to compare very large numeric numbers:

@ECHO OFF CLS SETLOCAL ENABLEDELAYEDEXPANSION SET LargestValue=0 FOR /F %%I IN (NUMBERS.TXT) DO ( IF /I !LargestValue! LSS %%I ( SET LargestValue=%%I ) ) ECHO !LargestValue!

In this case it does return the largest value as I want…

So I thought, lets do it in batch. So before continuing I thought "let’s do another test of creating an addition of very large numbers". The code would look like:

@ECHO OFF CLS SETLOCAL ENABLEDELAYEDEXPANSION SET NUMBER1=4611689999999999999 SET NUMBER2=500000 SET /A NUMBERTOTAL=%NUMBER1% ++ %NUMBER2% ECHO %NUMBERTOTAL%

now guess what the output was!….

it was:

Invalid number.  Numbers are limited to 32-bits of precision.

 

Cheers,

Jorge

———————————————————————————————

* This posting is provided "AS IS" with no warranties and confers no rights!

* Always evaluate/test yourself before using/implementing this!

* DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/

———————————————————————————————

############### Jorge’s Quest For Knowledge #############

######### http://JorgeQuestForKnowledge.wordpress.com/ ########

———————————————————————————————

Posted in Batch Script, Field Experiences, VB Script | 2 Comments »

(2005-11-16) Script To Set Or Clear The Inheritance Flag On AD Objects

Posted by Jorge on 2005-11-16


I have seen several questions regarding setting the inheritance flag on AD objects. Possible reasons were:

* Inheritance was disabled on sub OUs for some reason

* Inheritance was disabled on CUSTOM users or groups that previously were members of default AD protected groups

I found the script below on the internet after googling for some time. I found it at: http://www.codecomments.com/archive299-2004-10-298672.html

A copy of the script can be found below. That script can be modified to use an input file with all the objects that need inheritance enabled again.

In the second case (the adminSDholder case) first query AD for all groups and users that have adminCount = 1.

For that you can use Joe’s ADFIND tool (http://www.joeware.net/win/free/tools/adfind.htm)

ADFIND -default -f "(&(|(&(objectCategory=person)(objectClass=user))(objectCategory=group))(adminCount=1))" -dn

From the result you get filter out all default protected users and groups AND custom groups that are still members of the protected groups.

Review what is left and put that into the input file and use the script below (first read the QUOTE!) to enable inheritance again.

You can use the same input file to reset the adminCount attribute to 0 or to <not set>. You could just use ADMOD (also from Joeware – http://www.joeware.net/win/free/tools/admod.htm) in conjunction with ADFIND and modify all objects that have adminCount=1 to adminCount=0. However you DON’T wanna do that as some objects have that attribute because they are protected by the adminSDHolder object. Although if you change it, it will be reset back. So you would be changing what should NOT be changed. Because you have a custom list objects to change you should use a script (e.g. VBS).

Maybe if we all ask real hard, Joe will modify ADMOD to accept an input file with DNs of objects to modify… ;-))

 

<QUOTE>

The VBScript program below will toggle this setting. That is, if "allow inheritable permissions" is enabled (as it is by default), this program will disable it. If it is disabled, the program will enable it. I have hard coded the Distinguished Name of the object in the program. It should work for any object in Active Directory. If you need to modify the program, remember you would use the "And" operator to test a bit in ‘intNtSecurityDescriptorControl’, the "Or" operator to set a bit, and the "Xor" operator (as below) to toggle the bit. The constant SE_DACL_PROTECTED represents just one bit of intNtSecurityDescriptorControl.

</QUOTE>

' VBScript program to toggle "allow inheritable permissions from ' parent to propagate to this object" on the Security tab of the object. Option Explicit Const SE_DACL_PROTECTED = &H1000 Dim objADObject, objNtSecurityDescriptor, intNtSecurityDescriptorControl ' Distinguished Name of user object hard coded. Set objADObject = GetObject("LDAP://cn=TestUser,ou=Sales,dc=MyDomain,dc=com") ' Retreive security descriptor object for this object. Set objNtSecurityDescriptor = objADObject.Get("ntSecurityDescriptor") ' Retrieve control settings. intNtSecurityDescriptorControl = objNtSecurityDescriptor.Control ' Toggle the bit for "allow inheritable permissions". intNtSecurityDescriptorControl = intNtSecurityDescriptorControl Xor SE_DACL_PROTECTED ' Save control settings in the security descriptor object. objNtSecurityDescriptor.Control = intNtSecurityDescriptorControl ' Save the security descriptor object. objADObject.Put "ntSecurityDescriptor", objNtSecurityDescriptor ' Update the user object. objADObject.SetInfo Wscript.Echo "Done"

Use this script at your own risk!

NOTE: as inheritance was disabled the ACLs on the parent object are copied onto the child object. If you enable inheritance on the target object that object can/will have the following "types" of permissions (depending on how inheritance was disabled – manually or through adminSDHolder object):

* Permissions defined in the schema for that type of target object

* Explicit permissions on the target object that were copied from the parent when inheritance was disabled

* Implicit permissions on the target object that are inherited from the parent object after re-enabling inheritance

* Explicit permissions set by the adminSDHolder object

 

To reset everything to normal you can use DSACLS with the option to reset the ACLs of the target object as defined in the schema. BE CAREFUL! -> if you have custom ACLs defined (e.g. because of delegations which is possible for OUs) those ACLs will be removed

Cheers,

Jorge

———————————————————————————————

* This posting is provided "AS IS" with no warranties and confers no rights!

* Always evaluate/test yourself before using/implementing this!

* DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/

———————————————————————————————

############### Jorge’s Quest For Knowledge #############

######### http://JorgeQuestForKnowledge.wordpress.com/ ########

———————————————————————————————

 

Posted in Active Directory Domain Services (ADDS), VB Script | 9 Comments »

 
%d bloggers like this: