Tag Archives: Active Directory

Some SID Filtering Notes

  • SID Filtering is also known as Quarantine, Domain Quarantine, or SID Filtering Quarantine.
  • SID Filtering only applies to trusts, it cannot be enabled within a domain.
  • SID Filtering, by default, is not active on automatically created trusts within a forest. You can enable it, but not if the forest functional level is below Windows Server 2003. Doing so on any trust within a forest breaks replication. Additionally, if the forest functional level is Windows Server 2003 or higher; users with universal group memberships from other domains in the forest may loose access to resources if you enable SID Filtering on any of your trusts.
  • You can check the status of SID Filtering with the netdom.exe (Windows Domain Manager) command:
    • To verify the status of SID Filtering between two domains:
      netdom trust <TrustingDomainName> /domain: <TrustedDomainName> /quarantine
      Example output:
      SID filtering is not enabled for this trust. All SIDs presented in an authentication request from this domain will be honored.
      This is the default setting between domains in the same forest.
    • To verify the status of SID Filtering between two forests:
      netdom trust <TrustingDomainName> /domain: <TrustedDomainName> /enablesidhistory
      Example output:
      SID history is disabled for this trust.
      This is the default setting between trusting forests.
    • As you can see the two commands are nearly identical, but /quarantine applies only to domain trusts and /enablesidhistory is only valid for an outbound forest trust. They also output totally different messages making it hard to see that they actually apply to the same thing.
  • More info:

AdminSDHolder, Protected Groups, SDProp and moving mailboxes in Exchange

When you move a mailbox in Exchange 2000 or newer, you sometimes encounter an error saying that you have insufficient permissions to move the mailbox. Although that may be the case, usually this error is caused by the user object associated with the mailbox you are trying to move not having inheritable permissions enabled in Active Directory. This is also known as that the DACL is protected, i.e. it is special and should not be changed. But why is it protected?

Usually it is protected because the user was once a member of one of the protected administrative groups in Active Directory. (Notice the word ‘once’, it will be important later!) These groups are (per Windows Server 2008 R2):

  • Enterprise Admins
  • Schema Admins
  • Domain Admins
  • Administrators
  • Account Operators
  • Server Operators
  • Print Operators
  • Backup Operators
  • Cert Publishers

Any user who is a direct or indirect member of any of these groups will get a protected DACL (inheritable permissions turned off) and the attribute adminCount set to 1. SDProp, or the Security Descriptor Propagator, thread within the LSASS.EXE process is responsible for checking and applying these settings once an hour. Any change you make to a protected object will be reset within the hour.

So back to moving mailboxes.

If the user is a member of any of the protected groups, the move mailbox process completes successfully since Exchange is aware of how to handle that scenario. But if the user has been removed from all protected groups the move process fails (remember I said “once a member of”).

The reason is that the user still has a protected DACL and the adminCount attribute set to 1. SDProp does not reverse its changes when you remove a user from a protected group. This is a scenario that Exchange does not know how to handle and so throws the insufficient permissions error. The easiest way to resolve the problem is to go into the Security tab of the user object, select Advanced and hit the Restore Defaults button. That will enable inheritance of permissions and remove any ACEs that SDProp (or any other process) has set explicitly. One important thing to know is that the Restore Defaults button does not reset the adminCount attribute back to 0, so you still have a user object in a non-consistent state (it is inheriting permissions, but still flagged as a special object). The best practice would be to manually clear adminCount with you favorite DS tool when you also enable permission inheritance.

Now that we know this it would be a good idea to find all the users that would fail when we tried to move them. To do this we would need to construct a query with the following criteria:

  • Not a member of any of the protected groups
  • Has a mailbox
  • Has a protected DACL

My choice would be PowerShell. Here is an example using the Quest Active Directory cmdlets:

  1. Put all the known protected groups in an array:
    $ADProtectedGroups = @(“Enterprise Admins”,”Schema Admins”,”Domain Admins”,”Administrators”,”Account Operators”,”Server Operators”,”Print Operators”,”Backup Operators”,”Cert Publishers”)
  2. Find all the users and put them in an array:
    $mismatchedUsers = Get-qaduser -sizelimit 0 -securitymask DACL –NotIndirectMemberOf $ADProtectedGroups -IncludedProperties homeMDB | Where-Object {(($_.DirectoryEntry.PSBase.ObjectSecurity.AreAccessRulesProtected) –
    and ($_.homeMDB -ne $null))}
  3. View the users if you like:
    $mismatchedUsers | ft
  4. Fix the users:
    $mismatchedUsers | ForEach { Set-QADObjectSecurity $_ –UnLockInheritance | Set-QADObject -ObjectAttributes @{adminCount=$null} }

Note: You may also want to include adminCount=1 in your search to see which objects have it set, but you could then get back users that have been fixed before by pressing Restore Defaults or enabling inheritable permissions.

To search for users with adminCount=1:

$admincountUsers = Get-qaduser -sizelimit 0 -NotIndirectMemberOf $ADProtectedGroups -IncludedProperties homeMDB,adminCount | Where-Object {(($_.adminCount -eq 1) -and ($_.homeMDB -ne $null))}

Or to just find everything with adminCount=1:

Get-ADObject –LDAPFilter “(adminCount=1)”

“A certificate cloud not be found that can be used with this Extensible Authentication Protocol” error in IAS

After issuing a new certificate for a Windows Server 2003 running IAS this error presented itself in the IAS console when trying to configure EAP with the new certificate:

image

“A certificate could not be found that can be used with this Extensibel Authentication Protocol.”

This was accompanied by these two events in the System Log:

image

image

This was the new certificate, based on the default Computer template in Windows:

image

Notice the empty subject field, IAS/NPS does not accept certificates with empty subject names for use with EAP or Smart Cards. The certificate template that had been used for this certificate was a duplicate of the default Computer template. The template looked like this:

image

After creating a new template from the default Computer template, now with Subject name format set to Common name, and issuing a new certificate; IAS worked fine.

So don’t use certificate with blank subjects for your IAS/NPS servers…

An overview of groups used by Active Directory Certificate Services

This is a quick list of the groups associated with Active Directory Certificate Services.

CERTSVC_DCOM_ACCESS

Purpose: Grant DCOM access to Certificate Authority.

Default description: This group has no default description.

Group type: Local/Domain Local Security group.

Default members: Everyone/Domain Users and Domain Computers.

This group is created when Windows Server 2003 Service Pack 1 is installed on a Certificate Authority. If the CA is a member server (or in a workgroup); CERTSVC_DCOM_ACCESS is a computer local group, if the CA is a DC; CERTSVC_DCOM_ACCESS is a domain local group. Also when you install a Certificate Authority (CA) on a Windows Server 2003 machine that already has Service Pack 1 (or later); this group is created.

All security principals that need to enroll certificates from the CA must be a member, direct or indirect, of this group. If the CA is a member server; the Everyone security group is added to CERTSVC_DCOM_ACCESS. If the CA is a DC; the Domain Users and Domain Computers groups are added to CERTSVC_DCOM_ACCESS.

Only domains with a CA installed on a DC have this group, and only members servers with a CA have it as a computer local group. If you have several domains in your forest, only computers and users in the domain where the CA resides can request certificates. If other domains in the forest need to enroll certificates, security principals from those domains must be added to the group.

In Windows Server 2008 this group was replaced by the Certificate Service DCOM Access group (see own group into below).

More info:

  • Description of the changes to DCOM security settings after you install Windows Server 2003 Service Pack 1
  • Error message when a client computer requests a certificate from a computer that is running Windows Server 2003 with Service Pack 1: “The wizard cannot be started because of one or more of the following conditions”Certificate Service DCOM Access

    Purpose: Grant DCOM access to Certificate Authority.

    Default description: Members of this group are allowed to connect to Certification Authorities in the enterprise.

    Group type: Builtin Local Security Group.

    Default members: Authenticated Users.

    This group serves the same purpose as CERTSVC_DCOM_ACCESS, but is created in Windows Server 2008 domains. It grants access to Certificate Authorities, but is a Builtin local group as opposed to CERTSVC_DCOM_ACCESS, which is a Local or Domain Local group.

    Sometimes you will se both CERTSVC_DCOM_ACCESS and Certificate Service DCOM Access in a domain.

    Cert Publishers

    Purpose: Publish certificates to Active Directory.

    Default description: Enterprise certification and renewal agents

    Group Type: Global Security Group (Windows 2000)/Domain Local Security Group (Windows Server 2003 or later)

    Default members: Certificate Authority computer account from same domain as group.

    This group is created when an Active Directory domain is created. In Windows 2000 it is created as a Global Security Group, but in Windows Server 2003 or later it is created as a Domain Local Security Group.

    If a Windows 2000 domain is upgraded to Windows Server 2003 or later, this group remains as a Global Security Group; it is not automatically updated to Domain Local scope. To change the group scope you can run this command:

  • dsmod group CN=Cert Publishers,CN=Users,<domain DN> -scope lSometimes you cannot change the group scope directly to Domain Local. In this case, you have to run 2 commands:
  • dsmod group CN=Cert Publishers,CN=Users,<domain DN> -scope u
    (This command changes the global group into a universal group.)
  • dsmod group CN=Cert Publishers,CN=Users,<domain DN> -scope l
    (This changes the group scope to Domain Local.)This group is granted Read userCertificate and Write userCertificate on all user and computer accounts in the domain where it resides. If the same domain contains a Certificate Authority the CA is added to this group, thus allowing it to publish certificates to the user or computer.

    The permissions granted to the Cert Publishers group in a domain are defined on the AdminSDHolder container located in <domain>/System. Changing the Cert Publishers group’s permissions on AdminSDHolder will change the permissions that Cert Publishers have on all objects in the domain.

    In a multi-domain forest, the CA computer account(s) must be added to this group in all the domains where you want the CA to be able to publish certificates.

    If you have a multi-domain forest the PowerShell script below will display the group scope and members of all the Cert Publishers groups in the forest:

    #
    # EnumerateAllCertPublishersMembers2.ps1
    # by Morgan Simonsen, Atea
    #
    # List the group type, scope and members of the Cert Publishers group
    # in every domain in a forest.
    #
    # More info:
    #
    http://morgansimonsen.wordpress.com/2012/01/24/an-overview-of-groups-used-by-active-directory-certificate-services/
    #

    $colCertPublishersGroups = @()

    $forest = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()

    Write-Host “Getting forest-wide membership of Cert Publishers groups…”

    # Get members of ‘Cert Publishers’ for forest-root domain
    $objTemp = New-Object System.Object
    $objTemp | Add-Member -type NoteProperty -name “Domain” -value $forest.name

    $group = Get-QADGroup -Identity ( $forest.name + “/users/Cert Publishers” ) -Service $forest.pdcroleowner #-ea silentlycontinue

    $objTemp | Add-Member -type NoteProperty -name “Group Name” -value $group.name
    $objTemp | Add-Member -type NoteProperty -name “Group Type” -value $group.grouptype
    $objTemp | Add-Member -type NoteProperty -name “Group Scope” -value $group.groupscope

    $members = Get-QADGroupMember -Identity ( $forest.name + “/users/Cert Publishers” ) -Service $forest.pdcroleowner #-ea silentlycontinue

    $objTemp | Add-Member -type NoteProperty -name “Members” -value $members

    If ( $members -ne $null )
    {
    ForEach ( $member in $members )
    {
    #Nothing
    }
    }
    $colCertPublishersGroups += $objTemp

    $domain = $null
    $group = $null
    $members = $null
    $objTemp = $null

    # Get members of ‘Cert Publishers’ for child domains
    $forest.children | ForEach `
    {
    $objTemp = New-Object System.Object
    $mydomain = Get-QADObject -Identity $_.name #-ea silentlycontinue

        $objTemp | Add-Member -type NoteProperty -name “Domain” -value $mydomain.name

        $group = Get-QADGroup -Identity ( $_.name + “/users/Cert Publishers” ) -Service $_.pdcroleowner #-ea silentlycontinue

        $objTemp | Add-Member -type NoteProperty -name “Group Name” -value $group.name
    $objTemp | Add-Member -type NoteProperty -name “Group Type” -value $group.grouptype
    $objTemp | Add-Member -type NoteProperty -name “Group Scope” -value $group.groupscope

        $members = Get-QADGroupMember -Identity ( $_.name + “/users/Cert Publishers” ) -Service $_.pdcroleowner #-ea silentlycontinue

        $objTemp | Add-Member -type NoteProperty -name “Members” -value $members

        If ( $members -ne $null )
    {
    ForEach ( $member in $members )
    {
    #Nothing
    }
    }
    $colCertPublishersGroups += $objTemp

        $domain = $null
    $group = $null
    $members = $null
    $objTemp = $null

    }

    $colCertPublishersGroups

    More info:

  • Certification Authority configuration to publish certificates in Active Directory of trusted domain
  • Cert Publishers scope changed from Global to Domain Local in Windows Server 2003
  • Enterprise CA May Not Publish Certificates from Child Domain or Trusted Domain

Error when trying to reset a password when Fine Grained Password Policies (FGPP) are in effect

I had created a Fine Grained Password Policy (FGPP) which, among other things, turned off the requirement for complex passwords. I had applied this policy to users through a group. When I tried to reset the password of one of the users for which this FGPP applied, Active Directory Users and Computers would give me this error:

—————————
Active Directory Domain Services
—————————
Windows cannot complete the password change for <user> because:

The password does not meet the password policy requirements. Check the minimum password length, password complexity and password history requirements.

—————————
OK
—————————

Originally I though that my password did in fact violate my FGPP, but after testing this further I concluded that it was something else. After a bit of looking I discovered that this domain was in Windows Server 2003 Functional Mode. A requirement for FGPP is at least Windows Server 2008 Functional Mode. After changing it to Windows Server 2008, the FGPP took effect and I could reset my passwords.

Perhaps the *-ADFineGrainedPasswordPolicy cmdlets should check the domain functional level. At least New-ADFineGrainedPasswordPolicy should display a warning if the domain is not at the required level. The requirement is listed in the Step-by-Step guide (thank you PTS), but I didn’t catch that this time.

References:

Viewing the contents of Group Policy Registry.pol files

While investigating some EFS settings I needed to look at the raw data in Group Policy settings files, usually called Registry.pol and located in the SYSVOL share for each GPO. First I tried to load it as any other hive in Registry Editor, but that did not work, indicating that .pol files do not use the same format as the Registry does.

After a bit of searching I found this excellent utility at the gpoguy.com website: Registry.pol Viewer Utility.

With it I could read (but not change) the information in my Registry.pol file.

The Registry.pol format is documented at MSDN.

Group Policy WMI filters

WMI filters are useful to further filter Group Policy Objects (GPOs), beyond what is possible/convenient with groups.

Distinguish between x86 and x64 computers:

x86

Select AddressWidth from Win32_Processor where (AddressWidth=”32″)

x64

Select AddressWidth from Win32_Processor where (AddressWidth=”64″)

Determine Windows version:

Use this filter to determine the Windows version and role:

select * from Win32_OperatingSystem where Version like “6.%” and ProductType = “1”

  • The Version property returns values that begin with the following characters (the % symbol is a wildcard character that represents other characters that can follow, but do not help distinguish the version number):
    Windows Server 2008 R2 or Windows 7 6.1%
    Windows Server 2008 or Windows Vista 6.0%
    Windows Server 2003 5.2%
    Windows XP 5.1%
    Windows 2000 5.0%
  • The ProductType property returns the following values:
    Client versions of Windows 1
    Server versions of Windows that are operating as a domain controller 2
    Server versions of Windows that are not operating as a domain controller (typically referred to as member servers) 3

Determine computer type (laptop, desktop etc.)

NOTE: The PCSystemType property in only available on Windows Vista and later OSs.

SELECT * FROM Win32_ComputerSystem WHERE PCSystemType = 1

These are the possible values for PCSystemType:

Value Meaning
0 Unspecified
1 Desktop
2 Mobile
3 Workstation
4 Enterprise Server
5 Small Office and Home Office (SOHO) Server
6 Appliance PC
7 Performance Server
8 Maximum

(I’d really like a computer with type 8, please!)

Configuring a Windows Domain Controller to synchronize its clock with an external time source

Kerberos authentication requires correct time on all clients participating in authentication. If the clocks on two machines trying to authenticate to each other are too far apart, Kerberos authentication will fail. Since Kerberos is used extensively in Windows a mechanism to ensure correct clocks throughout the forest was also implemented. This is the Windows Time Service (w32time), a service which runs on all Windows machines since Windows 2000. The protocol used for synchronizing clocks is the Network Time Protocol (NTP). Every member computer, be it server or workstation, synchronize their clocks with the Domain Controller holding the PDC emulator FSMO role for its domain. The PDC emulator for a domain, in turn, synchronizes with the PDC emulator DC in the forest root domain. The PDC emulator in the root domain, therefore, is authoritative for the time throughout the forest, since all machines will inherit its clock. For this reason the PDC emulator DC in the forest root domain should be configured to obtain exact time from a dependable time server on the Internet. Microsoft has published information about doing this in KB816042. I have created a VBScript which implements the registry changes specified in that article:

 1: ' Configures the PDC Emulator in the root of a forest to be an authoritative time server
 2: ' and sync time from several NTP time servers on the Internet
 3: ' Info gathered from KB816042 How to configure an authoritative time server in
 4: ' Windows Server 2003 (http://support.microsoft.com/kb/816042)
 5: '
 6: ' On a PDC Emulator the settings changed from the default settings are:
 7: ' Type (From NT5DS to NTP)
 8: ' AnnounceFlags (From 10 to 5)
 9: ' NTPServer (From time.windows.com,0x1 to contents of strTimeServers)
 10: ' SpecialPollInterval (From 3600 to 900)
 11: ' MaxPosPhaseCorrection (From 4294967295 to 1800)
 12: ' MaxNegPhaseCorrection (From 4294967295 to 1800)
 13: '
 14: ' A useful command line command is:
 15: ' w32tm /config /manualpeerlist:"time-a.nist.gov time-b.nist.gov time.nist.gov time-nw.nist.gov" /syncfromflags:manual /reliable:yes /update
 16: ' This command sets AnnounceFlags to 5, NTPServer to the server list and Type to NTP
 17: ' Command found here:
 18: ' http://technet2.microsoft.com/windowsserver/en/library/ce8890cf-ef46-4931-8e4a-2fc5b4ddb0471033.mspx?mfr=true
 19: '
 20: ' A list of the NIST time server can be found here:
 21: ' http://tf.nist.gov/service/time-servers.html
 22: '
 23: ' Microsoft's list of (S)NTP servers is here:
 24: ' http://support.microsoft.com/kb/262680/en-us 
 25:
 26: const HKEY_CURRENT_USER = &H80000001
 27: const HKEY_LOCAL_MACHINE = &H80000002
 28: strKeyPath = "SYSTEMCurrentControlSetServicesW32Time"
 29:
 30: strTimeServers = "time-a.nist.gov,0x1 time-b.nist.gov,0x1 time-a.timefreq.bldrdoc.gov,0x1 time-b.timefreq.bldrdoc.gov,0x1 time-c.timefreq.bldrdoc.gov,0x1 utcnist.colorado.edu,0x1 time.nist.gov,0x1 time-nw.nist.gov,0x1 nist1.dc.certifiedtime.com,0x1 nist1.datum.com,0x1 nist1.nyc.certifiedtime.com,0x1 nist1.sjc.certifiedtime.com,0x1"
 31: strComputer = "."
 32: Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\" & strComputer & "rootdefault:StdRegProv")
 33:
 34: 'Change the server type to NTP (KB Step 1)
 35: objReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath & "Parameters","Type","NTP"
 36: 'Set AnnounceFlags to 5 (KB Step 2)
 37: objReg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath & "Config","AnnounceFlags",5
 38: 'Enable NTPServer (KB Step 3)
 39: objReg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath & "TimeProvidersNtpServer","Enabled",1
 40: 'Specify the time sources (KB Step 4)
 41: objReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath & "Parameters","NtpServer",strTimeServers
 42: 'Select the poll interval (KB Step 5)
 43: objReg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath & "TimeProvidersNtpClient","SpecialPollInterval",900
 44: 'Configure the time correction settings (KB Step 6)
 45: objReg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath & "Config","MaxPosPhaseCorrection",1800
 46: objReg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath & "Config","MaxNegPhaseCorrection",1800
 47:
 48: Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\" & strComputer & "rootcimv2")
 49: Set colListOfServices = objWMIService.ExecQuery ("Select * from Win32_Service Where Name ='W32Time'")
 50: For Each objService in colListOfServices
 51:     retVal = objService.StopService()
 52:     If retVal = 0 Then
 53:         'WScript.Echo "Service stopped"
 54:     Else
 55:         WScript.Echo "Service stop failed (" & retVal & ")"
 56:     End If
 57:     WScript.Sleep 5000
 58:     retVal = objService.StartService()
 59:     If retVal = 0 Then
 60:         'WScript.Echo "Service started"
 61:     Else
 62:         WScript.Echo "Service start failed (" & retVal & ")"
 63:     End If
 64: Next
 65:
 66: WScript.Echo "Done!"

Below is a comparison of the changes in the registry before and after the changes:

Before

 1: PS C:Usersadministrator> w32tm /query /configuration
 2: [Configuration]
 3:
 4: EventLogFlags: 2 (Local)
 5: AnnounceFlags: 10 (Local)
 6: TimeJumpAuditOffset: 28800 (Local)
 7: MinPollInterval: 6 (Local)
 8: MaxPollInterval: 10 (Local)
 9: MaxNegPhaseCorrection: 172800 (Local)
 10: MaxPosPhaseCorrection: 172800 (Local)
 11: MaxAllowedPhaseOffset: 300 (Local)
 12:
 13: FrequencyCorrectRate: 4 (Local)
 14: PollAdjustFactor: 5 (Local)
 15: LargePhaseOffset: 50000000 (Local)
 16: SpikeWatchPeriod: 900 (Local)
 17: LocalClockDispersion: 10 (Local)
 18: HoldPeriod: 5 (Local)
 19: PhaseCorrectRate: 7 (Local)
 20: UpdateInterval: 100 (Local)
 21:
 22:
 23: [TimeProviders]
 24:
 25: NtpClient (Local)
 26: DllName: C:Windowssystem32w32time.dll (Local)
 27: Enabled: 1 (Local)
 28: InputProvider: 1 (Local)
 29: CrossSiteSyncFlags: 2 (Local)
 30: AllowNonstandardModeCombinations: 1 (Local)
 31: ResolvePeerBackoffMinutes: 15 (Local)
 32: ResolvePeerBackoffMaxTimes: 7 (Local)
 33: CompatibilityFlags: 2147483648 (Local)
 34: EventLogFlags: 1 (Local)
 35: LargeSampleSkew: 3 (Local)
 36: SpecialPollInterval: 3600 (Local)
 37:
 38:
 39:
 40:
 41: Type: NT5DS (Local)
 42:
 43: NtpServer (Local)
 44: DllName: C:Windowssystem32w32time.dll (Local)
 45: Enabled: 1 (Local)
 46: InputProvider: 0 (Local)
 47: AllowNonstandardModeCombinations: 1 (Local)
 48:
 49: VMICTimeProvider (Local)
 50: DllName: C:WindowsSystem32vmictimeprovider.dll (Local)
 51: Enabled: 1 (Local)
 52: InputProvider: 1 (Local)
 53:

After

 1: PS C:Usersadministrator> w32tm /query /configuration
 2: [Configuration]
 3:
 4: EventLogFlags: 2 (Local)
 5: AnnounceFlags: 5 (Local)
 6: TimeJumpAuditOffset: 28800 (Local)
 7: MinPollInterval: 6 (Local)
 8: MaxPollInterval: 10 (Local)
 9: MaxNegPhaseCorrection: 1800 (Local)
 10: MaxPosPhaseCorrection: 1800 (Local)
 11: MaxAllowedPhaseOffset: 300 (Local)
 12:
 13: FrequencyCorrectRate: 4 (Local)
 14: PollAdjustFactor: 5 (Local)
 15: LargePhaseOffset: 50000000 (Local)
 16: SpikeWatchPeriod: 900 (Local)
 17: LocalClockDispersion: 10 (Local)
 18: HoldPeriod: 5 (Local)
 19: PhaseCorrectRate: 7 (Local)
 20: UpdateInterval: 100 (Local)
 21:
 22:
 23: [TimeProviders]
 24:
 25: NtpClient (Local)
 26: DllName: C:Windowssystem32w32time.dll (Local)
 27: Enabled: 1 (Local)
 28: InputProvider: 1 (Local)
 29:
 30: AllowNonstandardModeCombinations: 1 (Local)
 31: ResolvePeerBackoffMinutes: 15 (Local)
 32: ResolvePeerBackoffMaxTimes: 7 (Local)
 33: CompatibilityFlags: 2147483648 (Local)
 34: EventLogFlags: 1 (Local)
 35: LargeSampleSkew: 3 (Local)
 36: SpecialPollInterval: 900 (Local)
 37: Type: NTP (Local)
 38: NtpServer: time-a.nist.gov,0x1 time-b.nist.gov,0x1 time-a.timefreq.bldrdoc.gov,0x1 time-b.timefreq.bldrdoc.gov,0x1 time-
 39: c.timefreq.bldrdoc.gov,0x1 utcnist.colorado.edu,0x1 time.nist.gov,0x1 time-nw.nist.gov,0x1 nist1.dc.certifiedtime.com,0x
 40: 1 nist1.datum.com,0x1 nist1.nyc.certifiedtime.com,0x1 nist1.sjc.certifiedtime.com,0x1 (Local)
 41:
 42:
 43: NtpServer (Local)
 44: DllName: C:Windowssystem32w32time.dll (Local)
 45: Enabled: 1 (Local)
 46: InputProvider: 0 (Local)
 47: AllowNonstandardModeCombinations: 1 (Local)
 48:
 49: VMICTimeProvider (Local)
 50: DllName: C:WindowsSystem32vmictimeprovider.dll (Local)
 51: Enabled: 1 (Local)
 52: InputProvider: 1 (Local)

The most notable change is the Type value for the NTP client, which changes from NT5DS to NTP. The Type value is documented here.

Using w32tm.exe

The Windows Time Service can be configured using a complimentary utility called w32tm.exe. The following sets AnnounceFlags to 5, NTPServer to the server list and Type to NTP:

w32tm.exe /config /manualpeerlist:”time-a.nist.gov time-b.nist.gov time.nist.gov time-nw.nist.gov” /syncfromflags:manual /reliable:yes /update

Note that the settings for poll interval (SpecialPollInterval) and time correction (MaxPosPhaseCorrection/MaxNegPhaseCorrection) must be set in the registry.

Although the script uses the NIST time servers, I would recommend looking at the NTP Pool Project as well.

Also, to clear up a common misunderstanding, Windows does not need any third party software to synchronize its clock with an external time source, as long as the protocol used is NTP. This, of course, does not apply if you are using a special piece of hardware, such as a hardware clock, to keep correct time on your forest root PDC emulator DC. Furthermore, it is absolutely not necessary to include net time /sync or the like in logon scripts for clients to ensure they have the correct time, the Windows Time Service handles this.

If the DC holding the PDC Emulator FSMO role in the forest root domain is not set to sync its time from a reliable or external time source, the Windows Time service will log a warning in the System log with event ID 12:

Time Provider NtpClient: This machine is configured to use the domain hierarchy to determine its time source, but it is the AD PDC emulator for the domain at the root of the forest, so there is no machine above it in the domain hierarchy to use as a time source. It is recommended that you either configure a reliable time service in the root domain, or manually configure the AD PDC to synchronize with an external time source. Otherwise, this machine will function as the authoritative time source in the domain hierarchy. If an external time source is not configured or used for this computer, you may choose to disable the NtpClient.

Resetting configuration

In some cases you need to reset the configuration of the Windows Time Service. The easiest way I have found is to unregister and the register the service. Do this:

  1. Stop the Windows Time Service
    net stop w32time
  2. Unregister the service:
    w32tm /unregister
  3. Register the service:
    w32tm /register
  4. Start the Windows Time Service
    net start w32time

These steps will reset the service back to the defaults, usually to sync from the Domain Hierachy for a domain joined machine.

Configuring time synchornication on a non-domain computer

Some machines are not part of a domain hierarchy and therefore do not automatically use it to set their clocks. For Windows Vista and later there is a schedules task (Task Scheduler LibraryMicrosoftWindowsTime SynchronizationSynchronizeTime) that is set to run every Sunday at 01:00 by default. The Windows Time serivce is set to manual startup on workgroup computers by default and is started by the scheduled task. The command in the schedule task is %windir%system32sc.exe start w32time task_started. The start of the service, in turn, triggers a synchronizations agains the configured time server; time.windows.com, by default. Which server that is used to syncronize time is specified on the Internet Time tab of the Date and Time Control Panel applet (timedate.cpl). The Internet Time tab is missing on domian joined computers.

When you press Update now it seems to perform a regular synchronization with the Windows Time service, starting the service first if it is not running. This is evident by the events in the System log:

EntryType          : Information
Message            : The time service is now synchronizing the system time with the time source no.pool.ntp.org,0x9 (ntp.m|0x9|0.0.0.0:123->139.117.2.21:123).
Source             : Microsoft-Windows-Time-Service
UserName           : NT AUTHORITYLOCAL SERVICE

EntryType          : Information
Message            : The time provider NtpClient is currently receiving valid time data from no.pool.ntp.org,0x9 (ntp.m|0x9|0.0.0.0:123->139.117.2.21:123).
Source             : Microsoft-Windows-Time-Service
UserName           : NT AUTHORITYLOCAL SERVICE

EntryType          : Information
Message            : The system time has changed to ‎2011‎-‎10‎-‎12T10:05:28.640000000Z from ‎2011‎-‎10‎-‎12T10:05:28.640606800Z.
Source             : Microsoft-Windows-Kernel-General
UserName           : NT AUTHORITYLOCAL SERVICE

If you want to dump the SynchronizeTime task you can use this command:

schtasks.exe /query /TN “MicrosoftWindowsTime SynchronizationSynchronizeTime” /v /FO List

If you try to issue any w32tm.exe command before the Windows Time service is started you will receive an error:

The following error occurred: The service has not been started. (0x80070426)

After either starting the service yourself, or by pressing the Update now button in the Date and Time applet (which starts the service), you can issue commands with w32tm.exe normally. To configure which server(s) the computer syncs with you can either use the applet and enter a server FQDN (only one), or use w32tm.exe (multiple servers). With w32tm.exe you would use a sligtly different version of the command used on a forest root PDC Emulator domain controller:

w32tm.exe /config /manualpeerlist:”0.no.pool.ntp.org 1.no.pool.ntp.org 2.no.pool.ntp.org 3.no.pool.ntp.org” /syncfromflags:manual /update

As you can see, the reliable flag is missing from this command since it is only applicable on Domain Controllers.

Some thoughts on Active Directory OU structure design

Over the years I have been involved in quite a few Active Directory deployments and restructures. On these projects much time is always spent, or should be spent, on designing the OU structure.
The main thing about OU structure desing is to keep thing simple. Some organizations like to take the organizational chars and copy that in AD. Chances are that that structure will not be very useful for the people whose job it is to manage the network. They need an OU structure that reflects groupings of users, computers, groups and servers which have the same management and configuration needs.
There are many approaches to the design process. Eg. geographical where your OUs reflect the geographical locations of your company or users and computers. Functional; which organizes users by the function they have in the company, for example Sales users etc. A much used variant is one where some or all of the regular approaches are combined, for example geographical and functional.
Now, let’s consider an example. You have been charged with designing the OU structure for a large school or university. You decide that you want to use the functional approach and decided to create two main OUs to hold all your user accounts. The OUs will be called Students and Teachers. Upon first inspection this would seem to work well. You would be able to manage all your student users easily, same for teachers. But what if you have a user who works at the school as a teacher but would also like to attend courses or classes? (I assume here that we want to honour the principle of one user, one account.) That user should be treated as a student at one point, but as a teacher the next. Clearly our OU structure is not cut out for this. You could try to classify the user further and determine that he or she is mostly a teacher or mostly a student, but you probably do a lot of stuff based on which OU the user resides in, so you will eventually run into trouble. Not all your users will fit neatly into your two categories.
The problem here is that OUs are exclusive. You can only be located in one at any give time. So our desing here does not fit users that have dual identities. We have to come up with something that caters to this need. Back to the drawing board.
On our next try we start out with just one OU called Users. (Yes, I know there is already an object in Active Directory called Users, but that object is a container and we are creating an OU so that is not a problem.) In this OU we put all users regardless of their role or function. We now create groups to identify the needed roles. One group for students and one for teachers for example. We add all students to the Students group, all teachers to the Teachers group and users who are both to both groups. We now use Group Policy filtering to apply our GPOs to the correct group. A GPO that configures settings for students is filtered on the Students group, likewise for teachers. The GPO links that give the most access or have the least restrictive settings, should have a higher priority than more restrictive GPOs. That way if a user is a member of two or more groups with different access levels he or she will get the least restrictive settings.
Contrary to OUs, groups are inclusive, you can be a member of more than one. This lets your users assume several identities and get access to information and settings available to both.
I realize this approach is contrary to many accepted “truths” about Active Directory design, such that your should try to never filter your GPOs, but with the tools like GPMC it is very easy to see where your GPOs are linked and how they are filtered.

What does the Protect object from accidental deletion setting in Windows Server 2008 Active Directory actually do?

Windows Server 2008 Active Directory introduced a setting called Protect object from accidental deletion on all directory objects:

040309_1011_Whatdoesthe1

This was implemented to avoid accidentally deleting objects from the directory. OUs have this setting set by default. But what does it actually do?

When this setting is set a Deny access control entry (ACE) is added to the security descriptor of the object (“DELETE” & “DELETE TREE”) and a Deny access control entry (ACE) is added to the security descriptor of the PARENT of the object (“DELETE CHILD”). The security principal associated with these ACEs is Everyone, and they apply to This object only.

So if we select to protect the OU company.com/Unit/Usersfrom deletion the following will happen in the directory:

  • The UsersOU itself will get the “DELETE” and “DELETE TREE” DENY ACE set.
  • The parent of Users, in this case the OU Unit, will get the “DELETE CHILD” DENY ACE set.

Quried with DSACLS.EXE this will look like this:

For the Users OU:

dsacls.exe “OU=Users,OU=Unit,DC=company,DC=com”
Owner: COMPANYDomain Admins
Group: COMPANYDomain Admins

Access list:
Deny  Everyone                        SPECIAL ACCESS
DELETE
DELETE TREE

For the Unit OU (the parent of Users):

dsacls.exe “OU=Unit,DC=company,DC=com”
Owner: COMPANYDomain Admins
Group: COMPANYDomain Admins

Access list:
Deny  Everyone                        SPECIAL ACCESS
DELETE
DELETE CHILD
DELETE TREE

If you want to set these ACEs yourself you can use DSACLS.EXE:

For the Users OU:

DSACLS “OU=Users,OU=Unit,DC=Company,DC=Com” /D “Everyone:SDDT”

For the Unit OU (the parent of Users):

DSACLS “OU=Unit,DC=Company,DC=Com” /D “Everyone:DC”

If your are still running Windows 2000 or Windows Server 2003, I highly recommend making this part of your standard steps for creating new OUs. You can also change the Active Directory Schema so that the ACEs are set by default when creating new objects. When I figure out how that is done I will update this post.