<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Ask the Directory Services Team</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/askds/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/askds/feed.xml</link>
    <description>Microsoft&amp;#039;s official enterprise support blog for AD DS and more</description>
    <lastBuildDate>Fri, 08 Nov 2019 01:35:39 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>AskDS Is Moving!</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/askds-is-moving</link>
      <pubDate>Tue, 26 Mar 2019 15:08:05 GMT</pubDate>
      <dc:creator><![CDATA[Ryan Ries [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=17775</guid>
      <description><![CDATA[Hello readers.

The AskDS blog, as with all the other TechNet and MSDN blogs, will be moving to a...]]></description>
      <content:encoded><![CDATA[Hello readers.

The AskDS blog, as with all the other TechNet and MSDN blogs, will be moving to a new home on <a href="https://techcommunity.microsoft.com/t5/custom/page/page-id/Blogs">TechCommunity</a>.

The new URL is: <a href="https://techcommunity.microsoft.com/t5/Ask-the-Directory-Services-Team/bg-p/AskDS">https://techcommunity.microsoft.com/t5/Ask-the-Directory-Services-Team/bg-p/AskDS</a>

And as always, the short URL, <a href="http://aka.ms/AskDS">aka.ms/AskDS</a> will take you there as well.

Thanks!]]></content:encoded>
    </item>
    <item>
      <title>Deep Dive: Active Directory ESE Version Store Changes in Server 2019</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/deep-dive-active-directory-ese-version-store-changes-in-server-2019</link>
      <pubDate>Tue, 02 Oct 2018 23:39:36 GMT</pubDate>
      <dc:creator><![CDATA[Ryan Ries [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=17655</guid>
      <description><![CDATA[Hey everybody. Ryan Ries here to help you fellow AD ninjas celebrate the launch of Server...]]></description>
      <content:encoded><![CDATA[Hey everybody. <a href="https://blogs.technet.microsoft.com/askds/tag/ryan-ries/">Ryan Ries</a> here to help you fellow AD ninjas celebrate the launch of Server 2019.

Warning: As is my wont, this is a <span style="color: #ff0000">deep dive</span> post. Make sure you've had your coffee before proceeding.

Last month at Microsoft Ignite, many exciting new features rolling out in Server 2019 were talked about. (Watch MS Ignite sessions <a href="https://channel9.msdn.com/Events/Ignite/2018">here</a> and <a href="https://myignite.techcommunity.microsoft.com/videos">here</a>.)

But now I want to talk about an enhancement to on-premises Active Directory in Server 2019 that you won't read or hear anywhere else. This specific topic is near and dear to my heart personally.

The intent of the first section of this article is to discuss how Active Directory’s sizing of the ESE version store has changed in Server 2019 going forward. The second section of this article will discuss some basic debugging techniques related to the ESE version store.

Active Directory, also known as NT Directory Services (NTDS,) uses Extensible Storage Engine (ESE) technology as its underlying database.

One component of all ESE database instances is known as the version store. The version store is an in-memory temporary storage location where ESE stores snapshots of the database during open transactions. This allows the database to roll back transactions and return to a previous state in case the transactions cannot be committed. When the version store is full, no more database transactions can be committed, which effectively brings NTDS to a halt.

In 2016, the CSS Directory Services support team blog, (also known as AskDS,) published some previously undocumented (and some lightly-documented) internals regarding the ESE version store. Those new to the concept of the ESE version store should read <a href="https://blogs.technet.microsoft.com/askds/2016/06/14/the-version-store-called-and-theyre-all-out-of-buckets/">that blog post</a> first.

In the blog post linked to previously, it was demonstrated how Active Directory had calculated the size of the ESE version store since AD’s introduction in Windows 2000. When the NTDS service first started, a complex algorithm was used to calculate version store size. This algorithm included the machine’s native pointer size, number of CPUs, version store page size (based on an assumption which was incorrect on 64-bit operating systems,) maximum number of simultaneous RPC calls allowed, maximum number of ESE sessions allowed per thread, and more.

Since the version store is a memory resource, it follows that the most important factor in determining the optimal ESE version store size is the amount of physical memory in the machine, and that - ironically - seems to have been the only variable <em>not</em> considered in the equation!

The way that Active Directory calculated the version store size did not age well. The original algorithm was written during a time when all machines running Windows were 32-bit, and even high-end server machines had maybe one or two gigabytes of RAM.

As a result, many customers have contacted Microsoft Support over the years for issues arising on their domain controllers that could be attributed to or at least exacerbated by an undersized ESE version store. Furthermore, even though the default ESE version store size can be augmented by the "<a href="https://support.microsoft.com/en-us/help/974803/the-domain-controller-runs-slower-or-stops-responding-when-the-garbage">EDB max ver pages (increment over the minimum)</a>" registry setting, customers are often hesitant to use the setting because it is a complex topic that warrants heavier and more generous amounts of documentation than what has traditionally been available.

The algorithm is now greatly simplified in Server 2019:

- <strong>When NTDS first starts, the ESE version store size is now calculated as 10% of physical RAM, with a minimum of 400MB and a maximum of 4GB. </strong>

The same calculation applies to physical machines and virtual machines. In the case of virtual machines with dynamic memory, the calculation will be based off of the amount of "starting RAM" assigned to the VM. The "EDB max ver pages (increment over the minimum)" registry setting can still be used, as before, to add additional buckets over the default calculation. (Even beyond 4GB if desired.) The registry setting is in terms of "buckets," not bytes. Version store buckets are 32KB each on 64-bit systems. (They are 16KB on 32-bit systems, but Microsoft no longer supports any 32-bit server OSes.) Therefore, if one adds 5000 "buckets" by setting the registry entry to 5000 (decimal,) then 156MB will be added to the default version store size. A minimum of 400MB was chosen for backwards compatibility because when using the old algorithm, the default version store size for a DC with a single 64-bit CPU was ~410MB, regardless of how much memory it had. (There is no way to configure less than the minimum of 400MB, similar to previous Windows versions.) The advantage of the new algorithm is that now the version store size scales linearly with the amount of memory the domain controller has, when previously it did not.

Defaults:
<table>
<tbody>
<tr>
<td width="269">Physical Memory in the Domain Controller</td>
<td width="198">Default ESE Version Store Size</td>
</tr>
<tr>
<td width="269">1GB</td>
<td width="198">400MB</td>
</tr>
<tr>
<td width="269">2GB</td>
<td width="198">400MB</td>
</tr>
<tr>
<td width="269">3GB</td>
<td width="198">400MB</td>
</tr>
<tr>
<td width="269">4GB</td>
<td width="198">400MB</td>
</tr>
<tr>
<td width="269">5GB</td>
<td width="198">500MB</td>
</tr>
<tr>
<td width="269">6GB</td>
<td width="198">600MB</td>
</tr>
<tr>
<td width="269">8GB</td>
<td width="198">800MB</td>
</tr>
<tr>
<td width="269">12GB</td>
<td width="198">1.2GB</td>
</tr>
<tr>
<td width="269">24GB</td>
<td width="198">2.4GB</td>
</tr>
<tr>
<td width="269">48GB</td>
<td width="198">4GB</td>
</tr>
<tr>
<td width="269">128GB</td>
<td width="198">4GB</td>
</tr>
</tbody>
</table>
&nbsp;

This new calculation will result in larger default ESE version store sizes for domain controllers with greater than 4GB of physical memory when compared to the old algorithm. This means more version store space to process database transactions, and fewer cases of version store exhaustion. (Which means fewer customers needing to call us!)
<p style="padding-left: 30px"><em>Note: This enhancement currently only exists in Server 2019 and there are not yet any plans to backport it to older Windows versions.</em></p>
<p style="padding-left: 30px"><em>Note: This enhancement applies only to Active Directory and not to any other application that uses an ESE database such as Exchange, etc.</em></p>
&nbsp;

<strong><u>ESE Version Store Advanced Debugging and Troubleshooting</u></strong>

&nbsp;

This section will cover some basic ESE version store triage, debugging and troubleshooting techniques.

As covered in the AskDS blog post linked to previously, the performance counter used to see how many ESE version store buckets are currently in use is:

\\.\Database ==&gt; Instances(lsass/NTDSA)\Version buckets allocated

&nbsp;

Once that counter has reached its limit, (~12,000 buckets or ~400MB by default,) events will be logged to the Directory Services event log, indicating the exhaustion:

[caption id="attachment_17665" align="alignnone" width="594"]<img width="594" height="403" class="size-full wp-image-17665" alt="Figure 1: NTDS version store exhaustion." src="https://msdnshared.blob.core.windows.net/media/2018/10/verstore2019_1.png" /> <em>Figure 1: NTDS version store exhaustion.</em>[/caption]

&nbsp;

The event can also be viewed graphically in Performance Monitor:

[caption id="attachment_17675" align="alignnone" width="982"]<img width="982" height="602" class="size-full wp-image-17675" alt="Figure 2: The plateau at 12,314 means that the performance counter &quot;Version Buckets Allocated&quot; cannot go any higher. The flat line represents a dead patient." src="https://msdnshared.blob.core.windows.net/media/2018/10/verstore2019_2.png" /> <em>Figure 2: The plateau at 12,314 means that the performance counter "Version Buckets Allocated" cannot go any higher. The flat line represents a dead patient.</em>[/caption]

&nbsp;

As long as the domain controller still has available RAM, try increasing the version store size using the previously mentioned registry setting. Increase it in gradual increments until the domain controller is no longer exhausting the ESE version store, or the server has no more free RAM, whichever comes first. Keep in mind that the more memory that is used for version store, the less memory will be available for other resources such as the database cache, so a sensible balance must be struck to maintain optimal performance for <em>your</em> workload. (i.e. no one size fits all.)

If the "Version Buckets Allocated" performance counter is still pegged at the maximum amount, then there is some further investigation that can be done using the debugger.

The eventual goal will be to determine the nature of the activity within NTDS that is primarily responsible for exhausting the domain controller of all its version store, but first, some setup is required.

First, generate a process memory dump of lsass on the domain controller while the machine is "in state" – that is, while the domain controller is at or near version store exhaustion. To do this, the "Create dump file" option can be used in Task Manager by right-clicking on the lsass process on the Details tab. Optionally, another tool such as Sysinternals’ procdump.exe can be used (with the -ma switch .)

In case the issue is transient and only occurs when no one is watching, data collection can be configured on a trigger, using procdump with the -p switch.
<p style="padding-left: 30px"><em>Note: Do not share lsass memory dump files with unauthorized persons, as these memory dumps can contain passwords and other sensitive data.</em></p>
&nbsp;

It is a good idea to generate the dump after the Version Buckets Allocated performance counter has risen to an abnormally elevated level but before version store has plateaued completely. The reason why is because the database transaction responsible may be terminated once the exhaustion occurs, therefore the thread would no longer be present in the memory dump. If the guilty thread is no longer alive once the memory dump is taken, troubleshooting will be much more difficult.

Next, gather a copy of %windir%\System32\esent.dll from the same Server 2019 domain controller. The esent.dll file contains a debugger extension, but it is highly dependent upon the correct Windows version, or else it could output incorrect results. It should match the same version of Windows as the memory dump file.

Next, download WinDbg from the Microsoft Store, or from <a href="https://www.microsoft.com/en-us/p/windbg-preview/9pgjgd53tn86?activetab=pivot%3aoverviewtab">this link</a>.

Once WinDbg is installed, configure the symbol path for Microsoft’s public symbol server:

[caption id="attachment_17685" align="alignnone" width="922"]<img width="922" height="509" class="size-full wp-image-17685" alt="Figure 3: srv*c:\symbols*http://msdl.microsoft.com/download/symbol" src="https://msdnshared.blob.core.windows.net/media/2018/10/verstore2019_3.png" /> <em>Figure 3: srv*c:\symbols*http://msdl.microsoft.com/download/symbol</em>[/caption]

&nbsp;

Now load the lsass.dmp memory dump file, and load the esent.dll module that you had previously collected from the same domain controller:

[caption id="attachment_17695" align="alignnone" width="916"]<img width="916" height="290" class="size-full wp-image-17695" alt="Figure 4: .load esent.dll" src="https://msdnshared.blob.core.windows.net/media/2018/10/verstore2019_4.png" /> <em>Figure 4: .load esent.dll</em>[/caption]

&nbsp;

Now the ESE database instances present in this memory dump can be viewed with the command !ese dumpinsts:

[caption id="attachment_17705" align="alignnone" width="995"]<img width="995" height="360" class="size-full wp-image-17705" alt="Figure 5: !ese dumpinsts - The only ESE instance present in an lsass dump on a DC should be NTDSA." src="https://msdnshared.blob.core.windows.net/media/2018/10/verstore2019_5.png" /> <em>Figure 5: !ese dumpinsts - The only ESE instance present in an lsass dump on a DC should be NTDSA.</em>[/caption]

&nbsp;

Notice that the current version bucket usage is 11,189 out of 12,802 buckets total. The version store in this memory dump is very nearly exhausted. The database is not in a particularly healthy state at this moment.

The command !ese param &lt;instance&gt; can also be used, specifying the same database instance gotten from the previous command, to see global configuration parameters for that ESE database instance. Notice that <a href="https://msdn.microsoft.com/en-us/library/gg269201(v=exchg.10).aspx">JET_paramMaxVerPages</a> is set to 12800 buckets, which is 400MB worth of 32KB buckets:

[caption id="attachment_17715" align="alignnone" width="1031"]<img width="1031" height="336" class="size-full wp-image-17715" alt="Figure 6: !ese param &lt;instance&gt;" src="https://msdnshared.blob.core.windows.net/media/2018/10/verstore2019_6.png" /> <em>Figure 6: !ese param </em>[/caption]

&nbsp;

To see much more detail regarding the ESE version store, use the !ese verstore &lt;instance&gt; command, specifying the same database instance:

&nbsp;

[caption id="attachment_17725" align="alignnone" width="711"]<img width="711" height="719" class="size-full wp-image-17725" alt="Figure 7: !ese verstore &lt;instance&gt;" src="https://msdnshared.blob.core.windows.net/media/2018/10/verstore2019_7.png" /> <em>Figure 7: !ese verstore </em>[/caption]

&nbsp;

The output of the command above shows us that there is an open, long-running database transaction, how long it’s been running, and which thread started it. This also matches the same information displayed in the Directory Services event log event pictured previously.

Neither the event log event nor the esent debugger extension were always quite so helpful; they have both been enhanced in recent versions of Windows.

In older versions of the esent debugger extension, the thread ID could be found in the dwTrxContext field of the PIB, (command: !ese dump PIB 0x000001AD71621320) and the start time of the transaction could be found in m_trxidstack as a 64-bit file time. But now the debugger extension extracts that data automatically for convenience.

Switch to the thread that was identified earlier and look at its call stack:

[caption id="attachment_17735" align="alignnone" width="651"]<img width="651" height="728" class="size-full wp-image-17735" alt="Figure 8: The guilty-looking thread responsible for the long-running database transaction." src="https://msdnshared.blob.core.windows.net/media/2018/10/verstore2019_8.png" /> <em>Figure 8: The guilty-looking thread responsible for the long-running database transaction.</em>[/caption]

&nbsp;

The four functions that are highlighted by a red rectangle in the picture above are interesting, and here’s why:

When an object is deleted on a domain controller, and that object has <a href="https://docs.microsoft.com/en-us/windows/desktop/AD/linked-attributes">links</a> to other objects, those links must also be deleted/cleaned by the domain controller. For example, when an Active Directory user becomes a member of a security group, a database link between the user and the group is created that represents that relationship. The same principle applies to all linked attributes in Active Directory. If the Active Directory Recycle Bin is enabled, then the link-cleaning process will be deferred until the deleted object surpasses its Deleted Object Lifetime – typically 60 or 180 days after being deleted. This is why, when the AD Recycle Bin is enabled, a deleted user can be easily restored with all of its group memberships still intact – because the user account object’s links are not cleaned until after its time in the Recycle Bin has expired.

The trouble begins when an object with <em>many</em> backlinks is deleted. Some security groups, distribution lists, RODC password replication policies, etc., may contain hundreds of thousands or even millions of members. Deleting such an object will give the domain controller a lot of work to do. As you can see in the thread call stack shown above, the domain controller had been busily processing links on a deleted object for 47 seconds and still wasn’t done. All the while, more and more ESE version store space was being consumed.

When the AD Recycle Bin is enabled, this can cause even more confusion, because no one remembers that they deleted that gigantic security group 6 months ago. A time bomb has been sitting in the AD Recycle Bin for months. But suddenly, AD replication grinds to a standstill throughout the domain and the admins are scrambling to figure out why.

The performance counter "\\.\DirectoryServices ==&gt; Instances(NTDS)\Link Values Cleaned/sec" would also show increased activity during this time.

There are two main ways to fight this: either by increasing version store size with the "<a href="https://support.microsoft.com/en-us/help/974803/the-domain-controller-runs-slower-or-stops-responding-when-the-garbage">EDB max ver pages (increment over the minimum)</a>" registry setting, or by decreasing the batch size with the "<a href="https://support.microsoft.com/en-us/help/3149779/deleting-active-directory-objects-that-have-many-links-causes-replicat">Links process batch size</a>" registry setting, or a combination of both. Domain controllers process the deletion of these links in batches. The smaller the batch size, the shorter the individual database transactions will be, thus relieving pressure on the ESE version store.

Though the default values are properly-sized for almost all Active Directory deployments and most administrators should never have to worry about them, the two previously-mentioned registry settings are supported and well-informed enterprise administrators are encouraged to tweak the values – within reason – to avoid ESE version store depletion. Contact Microsoft customer support before making any modifications if there is any uncertainty.

At this point, one could continue diving deeper, using various approaches (e.g. consider not only debugging process memory, but also consulting DS Object Access audit logs, object metadata from repadmin.exe, etc.) to find out which exact object with many thousands of links was just deleted, but in the end that’s a moot point. There’s nothing else that can be done with that information. The domain controller simply must complete the work of link processing.

In other situations however, it will be apparent using the same techniques shown previously, that it’s an incoming LDAP query from some network client that’s performing inefficient queries, leading to version store exhaustion. Other times it will be DirSync clients. Other times it may be something else. In those instances, there may be more you can do besides just tweaking the version store variables, such as tracking down and silencing the offending network client(s), optimizing LDAP queries, creating database indices, etc..

&nbsp;

Thanks for reading,
- Ryan "Where's My Ship-It Award" Ries]]></content:encoded>
    </item>
    <item>
      <title>TLS Handshake errors and connection timeouts? Maybe it’s the CTL engine….</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/tls-handshake-errors-and-connection-timeouts-maybe-its-the-ctl-engine</link>
      <pubDate>Tue, 10 Apr 2018 21:19:59 GMT</pubDate>
      <dc:creator><![CDATA[Ryan Ries [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=17605</guid>
      <description><![CDATA[Hi There! 

Marius and Tolu from the Directory Services Escalation Team. 

Today, we’re going to...]]></description>
      <content:encoded><![CDATA[<span>Hi There!</span><span> </span>

<span>Marius and Tolu from the Directory Services Escalation Team.</span><span> </span>

<span>Today, we’re going to talk about a little twist on some scenarios you may have come across at some point, where TLS connections fail or timeout for a variety of reasons. </span><span> </span><span> </span>

<span>You’re probably already familiar with some of the usual suspects like cipher suite mismatches, certificate validation errors and TLS version incompatibility, to name a few. </span><span> </span><span> </span>

<span>Here are just some examples for illustration (but there is a wealth of information out there)</span><span> </span><span> </span>
<ul>
 	<li><a href="https://blogs.technet.microsoft.com/askpfeplat/2014/07/06/troubleshooting-tls1-2-and-certificate-issue-with-microsoft-message-analyzer-a-real-world-example/"><strong>Troubleshooting TLS 1.2 and Certificate Issue with Microsoft Message Analyzer: A Real World Example</strong></a></li>
 	<li><a href="https://blogs.msdn.microsoft.com/friis/2012/08/29/tls-1-2-handshake-failure/"><strong>TLS 1.2 handshake failure</strong></a></li>
 	<li><strong> </strong><a href="https://docs.microsoft.com/en-us/iis/troubleshoot/security-issues/troubleshooting-ssl-related-issues-server-certificate"><strong>Troubleshooting SSL related issues (Server Certificate)</strong></a></li>
</ul>
<span>Recently we’ve seen a number of cases with a variety of symptoms affecting different customers which all turned out to have a common root cause. </span><span> </span>

<span>We’ve managed to narrow it down to an unlikely source; a built-in OS feature working in its default configuration.</span><span> </span><span> </span>

<span>We’re talking about the <strong>automatic root update and automatic disallowed roots update mechanisms</strong> based on CTLs.</span>

<span>Starting with Windows Vista, root certificates are updated on Windows automatically. </span>

<span>When a user on a Windows client visits a secure Web site (by using HTTPS/TLS), reads a secure email (S/MIME), or downloads an ActiveX control that is signed (code signing) and encounters a certificate which chains to a root certificate not present in the root store, Windows will automatically check the appropriate Microsoft Update location for the root certificate. </span><span> </span>

<span>If it finds it, it downloads it to the system. To the user, the experience is seamless; they don’t see any security dialog boxes or warnings and the download occurs automatically, behind the scenes.</span><span> </span><span> </span>

<span>Additional information in: </span><span> </span><span> </span>
<p style="padding-left: 30px"><a href="https://technet.microsoft.com/en-us/library/cc751157.aspx"><span><strong>How Root Certificate Distribution Works</strong></span></a><span> </span></p>
During TLS handshakes, any certificate chains involved in the connection will need to be validated, and, from Windows Vista/2008 onwards, the automatic <em>disallowed</em> root update mechanism is also invoked to verify if there are any changes to the untrusted CTL (Certificate Trust List).

A certificate trust list (CTL) is a predefined list of items that are authenticated and signed by a trusted entity.

The mechanism is described in more detail in the following article:
<p style="padding-left: 30px"><a href="https://support.microsoft.com/en-us/help/2677070"><strong>An automatic updater of untrusted certificates is available for Windows Vista, Windows Server 2008, Windows 7, and Windows Server 2008 R2</strong></a></p>
It expands on the automatic root update mechanism technology (for trusted root certificates) mentioned earlier to let certificates that are compromised or are untrusted in some way be specifically flagged as untrusted.

Customers therefore benefit from periodic automatic updates to <strong>both </strong>trusted and untrusted CTLs.

So, after the preamble, what scenarios are we talking about today?

Here are some examples of issues we’ve come across recently.

&nbsp;

1)
<ul>
 	<li>Your users may experience browser errors after several seconds when trying to browse to secure (https) websites behind a load balancer.</li>
 	<li>      They might receive an error like "The page cannot be displayed. Turn on TLS 1.0, TLS 1.1, and TLS 1.2 in the Advanced settings and try connecting to <u>https://contoso.com</u> again.  If this error persists, contact your site administrator."</li>
 	<li>      If they try to connect to the website via the IP address of the server hosting the site, the https connection works after showing a certificate name mismatch error.</li>
 	<li>      All TLS versions ARE enabled when checking in the browser settings:</li>
</ul>
[caption id="attachment_17615" align="alignnone" width="396"]<img src="https://msdnshared.blob.core.windows.net/media/2018/04/ctl1.png" alt="Internet Options" width="396" height="260" class="size-full wp-image-17615" /> Internet Options[/caption]

&nbsp;

<strong> </strong>2)
<ul>
 	<li>      You have a 3rd party appliance making TLS connections to a Domain Controller via LDAPs (Secure LDAP over SSL) which may experience delays of up to 15 seconds during the TLS handshake</li>
 	<li>      The issue occurs randomly when connecting to any eligible DC in the environment targeted for authentication.</li>
 	<li>      There are no intervening devices that filter or modify traffic between the appliance and the DCs</li>
</ul>
2a)
<ul>
 	<li>A very similar scenario* to the above is in fact described in the following article by our esteemed colleague, Herbert:</li>
</ul>
<p style="padding-left: 30px"><a href="https://blogs.technet.microsoft.com/askds/2014/10/24/understanding-atq-performance-counters-yet-another-twist-in-the-world-of-tlas/">Understanding ATQ performance counters, yet another twist in the world of TLAs </a></p>
<p style="padding-left: 30px">Where he details:</p>
<p style="padding-left: 30px"><strong><em>Scenario 2 </em></strong></p>
<p style="padding-left: 30px"><em>DC supports LDAP over SSL/TLS </em></p>
<p style="padding-left: 30px"><em>A user sends a certificate on a session. The server need to check for certificate revocation which may take some time.*</em></p>
<p style="padding-left: 30px"><em>This becomes problematic if network communication is restricted and the DC cannot reach the Certificate Distribution Point (CDP) for a certificate.</em></p>
<p style="padding-left: 30px"><em>To determine if your clients are using secure LDAP (LDAPs), check the counter “LDAP New SSL Connections/sec”. </em></p>
<p style="padding-left: 30px"><em>If there are a significant number of sessions, you might want to look at CAPI-Logging.</em></p>
&nbsp;

3)
<ul>
 	<li>A 3<sup>rd</sup> party meeting server performing LDAPs queries against a Domain Controller may fail the TLS handshake on the first attempt after surpassing a pre-configured timeout (e.g 5 seconds) on the application side</li>
 	<li>Subsequent connection attempts are successful</li>
</ul>
&nbsp;

So, what’s the story? Are these issues related in anyway?

Well, as it turns out, they do have something in common.

As we mentioned earlier, certificate chain validation occurs during TLS handshakes.

Again, there is plenty of documentation on this subject, such as
<ul>
 	<li><a href="https://docs.microsoft.com/en-us/windows-server/security/tls/tls-ssl-schannel-ssp-overview"><strong>TLS - SSL (Schannel SSP) Overview</strong><strong> </strong> </a></li>
 	<li><a href="https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/dn786425(v%3dws.11)"><strong>Schannel Security Support Provider Technical Reference</strong> </a></li>
 	<li><a href="https://technet.microsoft.com/en-us/library/cc783349(v=ws.10).aspx"><strong>How TLS/SSL Works: Logon and Authentication</strong> </a></li>
 	<li><a href="https://blogs.msdn.microsoft.com/kaushal/2015/05/27/client-certificate-authentication-part-1/"><strong>Client Certificate Authentication (Part 1)</strong> </a></li>
</ul>
<span>During certificate validation operations, the CTL engine gets periodically invoked to verify if there are any changes to the untrusted CTLs.</span>

In the example scenarios we described earlier, if the default public URLs for the CTLs are unreachable, and there is no alternative internal CTL distribution point configured (more on this in a minute), the TLS handshake will be delayed until the <em>WinHttp</em> call to access the default CTL URL times out.

By default, this timeout is usually around 15 seconds, which can cause problems when load balancers or 3<sup>rd</sup> party applications are involved and have their own (more aggressive) timeouts configured.

If we enable CAPI2 Diagnostic logging, we should be able to see evidence of when and why the timeouts are occurring.

<span>We will see events like the following:</span><span> </span>

<span><strong>Event ID 20 – Retrieve Third-Party Root Certificate from Network</strong></span><span><strong>:</strong></span>

<span> </span><span> </span>
<ul>
 	<li><span><strong>Trusted CTL attempt</strong></span><span><strong></strong></span></li>
</ul>
[caption id="attachment_17625" align="alignnone" width="548"]<img src="https://msdnshared.blob.core.windows.net/media/2018/04/ctl2.png" alt="Trusted CTL Attempt" width="548" height="299" class="size-full wp-image-17625" /> Trusted CTL Attempt[/caption]

<span><strong> </strong></span>
<ul>
 	<li><span> </span><span><strong>Disallowed CTL attempt</strong></span><span><strong></strong></span></li>
</ul>
<strong> </strong>

[caption id="attachment_17635" align="alignnone" width="540"]<img src="https://msdnshared.blob.core.windows.net/media/2018/04/ctl3.png" alt="Disallowed CTL Attempt" width="540" height="279" class="size-full wp-image-17635" /> Disallowed CTL Attempt[/caption]

&nbsp;

&nbsp;

<strong>Event ID 53 error message details showing that we have failed to access the disallowed CTL</strong>:

&nbsp;

[caption id="attachment_17645" align="alignnone" width="602"]<img src="https://msdnshared.blob.core.windows.net/media/2018/04/ctl4.png" alt="Event ID 53" width="602" height="635" class="size-full wp-image-17645" /> Event ID 53[/caption]

<span> </span>

<span> </span><span>The following article gives a more detailed overview of the <strong>CAPI2</strong> diagnostics feature available on Windows systems, which is very useful when looking at any certificate validation operations occurring on the system:</span><span> </span><span> </span>
<p style="padding-left: 30px"><a href="https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc749296(v%3dws.10)"><span><strong>Troubleshooting PKI Problems on Windows Vista</strong></span><span> </span></a></p>
To help us confirm that the CTL updater engine is indeed affecting the TLS delays and timeouts we’ve described, we can temporarily disable it for both the trusted and untrusted CTLs and then attempt our TLS connections again.

&nbsp;

To disable it:
<ul>
 	<li> <em>Create a backup of this registry key (export and save a copy)</em></li>
</ul>
<p style="padding-left: 60px"><strong><em>HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\AuthRoot</em></strong></p>

<ul>
 	<li><em>Then create the following DWORD registry <strong>values</strong> under the key</em></li>
</ul>
<p style="padding-left: 60px"><strong><em>"EnableDisallowedCertAutoUpdate"=dword:00000000</em></strong></p>
<p style="padding-left: 60px"><strong><em>"DisableRootAutoUpdate"=dword:00000001</em></strong></p>
&nbsp;

<span>After applying these steps, you should find that your previously failing TLS connections will no longer timeout. Your symptoms may vary slightly, but you should see speedier connection times, because we have eliminated the delay in trying and failing to reach the CTL URLs.</span><span> </span>

<span>So, what now?</span><span> </span>

<span>We should now <strong>REVERT</strong> the above registry changes by restoring the backup we created, and <strong>evaluate the following, </strong></span><span><strong>more permanent solutions</strong></span><span>.</span>

<span>We previously stated that disabling the updater engine should only be a temporary measure to confirm the root cause of the timeouts in the above scenarios. </span><span> </span>

&nbsp;
<ul>
 	<li><strong>For the untrusted CTL:   </strong><strong>         </strong><strong> </strong></li>
</ul>
<ul>
 	<li>The automatic disallowed root update mechanism is a built-in OS feature, so we can consider allowing access to the public Microsoft disallowed CTL URL from users’ machines; <a href="http://ctldl.windowsupdate.com/msdownload/update/v3/static/trustedr/en/disallowedcertstl.cab">http://ctldl.windowsupdate.com/msdownload/update/v3/static/trustedr/en/disallowedcertstl.cab</a></li>
</ul>
<ul>
 	<li>OR, we can configure and maintain an internal untrusted CTL distribution point as outlined in <a href="https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/dn265983(v=ws.11)#BKMK_PrepServer">Configure Trusted Roots and Disallowed Certificates </a></li>
</ul>
&nbsp;
<ul>
 	<li><strong>For the trusted CTL:       </strong><strong>         </strong><strong> </strong></li>
</ul>
<ul>
 	<li>For server systems you might consider deploying the trusted 3rd party CA certificates via GPO on an as needed basis</li>
</ul>
<p style="padding-left: 60px"><a href="https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc754841(v%3dws.11)">Manage Trusted Root Certificates   </a></p>
<p style="padding-left: 30px">(particularly to avoid hitting the TLS protocol limitation described here:</p>
<p style="padding-left: 30px"><a href="https://support.microsoft.com/en-us/help/2801679/ssl-tls-communication-problems-after-you-install-kb-931125">SSL/TLS communication problems after you install KB 931125</a> )</p>
&nbsp;
<ul>
 	<li>For client systems, you should consider</li>
</ul>
<p style="padding-left: 30px">Allowing access to the public allowed Microsoft CTL URL <a href="http://ctldl.windowsupdate.com/msdownload/update/v3/static/trustedr/en/authrootstl.cab">http://ctldl.windowsupdate.com/msdownload/update/v3/static/trustedr/en/authrootstl.cab</a></p>
<p style="padding-left: 30px">OR</p>
<p style="padding-left: 30px">Defining and maintaining an internal trusted CTL distribution point as outlined in <a href="https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/dn265983(v=ws.11)#BKMK_PrepServer">Configure Trusted Roots and Disallowed Certificates </a></p>
<p style="padding-left: 30px">OR</p>
<p style="padding-left: 30px">If you require a more granular control of which CAs are trusted by client machines, you can deploy the 3<sup>rd</sup> Party CA certificates as needed via GPO</p>
<p style="padding-left: 30px"><a href="https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc754841(v%3dws.11)">Manage Trusted Root Certificates </a></p>
So there you have it. We hope you found this interesting, and now have an additional factor to take into account when troubleshooting TLS/SSL communication failures.]]></content:encoded>
    </item>
    <item>
      <title>ESE Deep Dive: Part 1: The Anatomy of an ESE database</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/ese-deep-dive-part-1-the-anatomy-of-an-ese-database</link>
      <pubDate>Mon, 04 Dec 2017 18:33:18 GMT</pubDate>
      <dc:creator><![CDATA[Linda Taylor (Microsoft GBS UK)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=17125</guid>
      <description><![CDATA[hi!Get your crash helmets on and strap into your seatbelts for a JET engine / ESE database...]]></description>
      <content:encoded><![CDATA[<p>hi!</p><p>Get your crash helmets on and strap into your seatbelts for a JET engine / ESE database special...<p>This is Linda Taylor, Senior AD Escalation Engineer from the UK here again. And WAIT...... I also somehow managed to persuade Brett Shirley to join me in this post. Brett is a Principal Software Engineer in the ESE Development team so you can be sure the information in this post is going to be deep and confusing but really interesting and useful and the kind you cannot find anywhere else :- )<br>BTW, Brett used to write blogs before he grew up and got very busy. And just for fun, you might find this old&nbsp; <a href="https://blogs.msdn.microsoft.com/brettsh/2006/06/12/i-decided-to-check-out-the-size-of-erics-dit/%20">“Brett” classic</a> entertaining. I have never forgotten it. :- )<br>Back to today's post...this will be a rather more grown up post, although we will talk about DITs but in a very scientific fashion. <br><br>In this post, we will start from the ground up and dive deep into the overall file format of an ESE database file including practical skills with <strong>esentutl </strong>such as how to look at raw database pages. And as the title suggests this is Part1 so there will be more!</p><h2>What is an ESE database?</h2><p>Let’s start basic. The Extensible Storage Engine (ESE), also known as JET Blue, is a database engine from Microsoft that does not speak SQL. And Brett also says … For those with a historical bent, or from academia, and remember ‘before SQL’ instead of ‘NoSQL’ ESE is modelled after the <a href="https://en.wikipedia.org/wiki/ISAM">ISAMs (indexed sequential access method)</a> that were vogue in the mid-70s. ;-p <br>If you work with Active Directory (which you must do if you are reading this post :-) then you will (I hope!) know that it uses an ESE database. The respective binary being, <strong>esent.dll</strong> (or Brett loves exchange, it's <strong><strong>ese.dll</strong></strong> for the Exchange Server install). Applications like active directory are all ESE clients and use the <a href="https://msdn.microsoft.com/en-us/library/gg269259(v=exchg.10).aspx">JET APIs</a> to access the ESE database. <p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/114.png"><img width="789" height="454" title="1" alt="1" src="https://msdnshared.blob.core.windows.net/media/2017/12/1_thumb3.png"></a><p>This post will dive deep into the Blue parts above. The ESE side of things. AD is one huge client of ESE, but there are many other Windows components which use an ESE database (and non-Microsoft software too), so your knowledge in this area is actually very applicable for those other areas. Some examples are below:<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/210.png"><img width="798" height="445" title="2" alt="2" src="https://msdnshared.blob.core.windows.net/media/2017/12/2_thumb2.png"></a><h3>Tools</h3><p>There are several built-in command line tools for looking into an ESE database and related files.&nbsp; <ol><li><p><a href="https://technet.microsoft.com/en-us/library/hh875546(v=ws.11).aspx">esentutl</a>. This is a tool that ships in Windows Server by default for use with Active Directory, Certificate Authority and any other built in ESE databases.&nbsp; This is what we will be using in this post and can be used to look at any ESE database. </p></li></ol><ol start="2"><li><p><a href="https://technet.microsoft.com/en-us/library/aa996953(v=exchg.65).aspx">eseutil</a>. This is the Exchange version of the same and gets installed typically in the Microsoft\Exchange\V15\Bin sub-directory of the Program Files directory.</p></li></ol><ol start="3"><li><p><a href="https://technet.microsoft.com/en-us/library/cc753343(v=ws.11).aspx">ntdsutil</a>. Is a tool specifically for managing an AD or ADLDS databases and cannot be used with generic ESE databases (such as the one produced by Certificate Authority service).&nbsp; This is installed by default when you add the AD DS or ADLDS role.</p></li></ol><p>For read operations such as dumping file or log headers it doesn’t matter which tool you use. But for operations which write to the database you MUST use the matching tool for the application and version (for instance it is not safe to run <strong>esentutl /r</strong> from Windows Server 2016 on a Windows Server 2008 DB). Further throughout this article if you are looking at an Exchange database instead, you should use eseutil.exe instead of esentutl.exe. For AD and ADLDS always use ntdsutil or esentutl. They have different capabilities, so I use a mixture of both. And Brett says that If you think you can NOT keep the read operations straight from the write operations, play it safe and match the versions and application.<p>During this post, we will use an AD database as our victim example. We may use other ones, like ADLDS for variety in later posts. <h2>Database logical format - Tables</h2><p>Let’s start with the logical format. From a logical perspective, an ESE database is a set of tables which have rows and columns and indices.<p>Below is a visual of the list of tables from an AD database in Windows Server 2016. Different ESE databases will have different table names and use those tables in their own ways.<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/33.png"><img width="306" height="295" title="3" alt="3" src="https://msdnshared.blob.core.windows.net/media/2017/12/3_thumb2.png"></a><p>In this post, we won’t go into the detail about the DNTs, PDNTs and how to analyze an AD database dump taken with LDP because this is AD specific and here we are going to look at ESE specific level. Also, there are other blogs and sources where this has already been explained. for example, here on <a href="https://blogs.technet.microsoft.com/askpfeplat/2012/07/22/mcm-core-active-directory-internals/">AskPFEPlat.</a> However, if such post is wanted, tell me and I will endeavor to write one!! <p>It is also worth noting that all ESE databases have a table called <strong>MSysObjects</strong> and <strong>MSysObjectsShadow</strong> which is a backup of <strong>MSysObjects.</strong> These are also known as “the catalog” of the database and they store metadata about client’s schema of the database – i.e.<ol><li><p>All the tables and their table names and where their associated <a href="https://en.wikipedia.org/wiki/B%2B_tree">B+ trees</a> start in the database and other miscellaneous metadata. </p></li></ol><ol start="2"><li><p>All the columns for each table and their names (of course), the <a href="https://msdn.microsoft.com/en-us/library/gg269213(v=exchg.10).aspx">type of data</a> stored in them, and various schema constraints.</p></li></ol><ol start="3"><li><p>All the indexes on the tables and their names, and where their associated B+ trees start in the database.</p></li></ol><p>This is the boot-strap information for ESE to be able to service client requests for opening tables to eventually retrieve rows of data.<h2>Database physical format</h2><p>From a physical perspective, an ESE database is just a file on disk. It is a collection of fixed size pages arranged into B+ tree structures. Every database has its page size stamped in the <strong>header</strong> (and it can vary between different clients, AD uses 8 KB). At a high level it looks like this:<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/44.png"><img width="640" height="330" title="4" alt="4" src="https://msdnshared.blob.core.windows.net/media/2017/12/4_thumb1.png"></a><p>The first <strong><strong>“page”</strong></strong> is the Header (H). <p>The second “page” is a Shadow Header (SH) which is a copy of the header. <p>However, in ESE “page number” (also frequently abbreviated “pgno”) has a very specific meaning (and often shows up in ESE events) and the first NUMBERED page of the actual database is page number / pgno 1 but is actually the third “page” (if you are counting from the beginning :-).<p>From here on out though, we will not consider the header and shadow header proper pages, and page number 1 will be third page, at byte offset = &lt;page size&gt; * 2 = 8192 * 2 (for AD databases).<p>If you don’t know the page size, you can dump the database header with <strong>esentutl /mh.</strong><p>Here is a dump of the header for an NTDS.DIT file – the AD database: <p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/12.jpg"><img width="553" height="493" title="1" alt="1" src="https://msdnshared.blob.core.windows.net/media/2017/12/1_thumb1.jpg"></a><p>The page size is the <strong><font>cbDbPage.</font></strong> AD and ADLDS uses a page size of <strong>8k</strong>. Other databases use different page sizes.<p>A caveat is that to be able to do this, the database must not be in use. So, you’d have to stop the NTDS service on the DC or run esentutl on an offline copy of the database.<p>But the good news is that in WS2016 and above we can now dump a LIVE DB header with the /vss switch! The command you need would be <strong>"esentutl /mh ntds.dit /vss”</strong> (note: must be run as administrator).<p>All these numbered database pages logically are “owned” by various B+ trees where the actual data for the client is contained … and all these B+ trees have a “type of tree” and all of a tree’s pages have a “placement in the tree” flag (Root, or Leaf or implicitly Internal – if not root or leaf). <p>Ok, Brett, that was “proper” tree and page talk -&nbsp; I think we need some pictures to show them... <p>Logically the ownership / containing relationship looks like this:<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/53.png"><img width="663" height="369" title="5" alt="5" src="https://msdnshared.blob.core.windows.net/media/2017/12/5_thumb1.png"></a><h3>More about B+ Trees</h3><p>The pages are in turn arranged into <a href="https://en.wikipedia.org/wiki/B%2B_tree">B+ Trees.</a> Where top page is known as the ‘Root’ page and then the bottom pages are ‘Leaf’ pages where all the data is kept.&nbsp; Something like this (note this particular example does not show ‘Internal’ B+ tree pages): <p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/62.png"><img width="781" height="250" title="6" alt="6" src="https://msdnshared.blob.core.windows.net/media/2017/12/6_thumb1.png"></a><ul><li><p>The upper / parent page has partial keys indicating that all entries with 4245 + A* can be found in pgno 13, and all entries with 4245 + E* can be found in pgno 14, etc.</p><li><p>Note this is a highly simplified representation of what ESE does … it’s a bit more complicated.</p></li></ul><ul><li><p>This is not specific to ESE; many database engines have either B trees or B+ trees as a fundamental arrangement of data in their database files.</p></li></ul><h4>The Different trees</h4><p>You should know that there are different types of B+ trees inside the ESE database that are needed for different purposes. These are:<ol><li><p><strong><strong>Data / Primary Trees</strong></strong> – hold the table’s primary records which are used to store data for regular (and small) column data.</p></li></ol><ol start="2"><li><p><strong>Long Value (LV) Trees</strong> – used to store <a href="https://en.wikipedia.org/wiki/Extensible_Storage_Engine">long values</a>. In other words, large chunks of data which don't fit into the primary record.</p></li></ol><ol start="3"><li><p><strong>Index trees</strong> – these are B+Trees used to store indexes.</p></li></ol><ol start="4"><li><p><strong>Space Trees</strong> – these are used to track what pages are owned and free / available as new pages for a given B+ tree.&nbsp; Each of the previous three types of B+ Tree (Data, LV, and index), may (if the tree is large) have a set of two space trees associated with them.</p></li></ol><h4>Storing large records</h4><p>Each Row of a table is limited to 8k (or whatever the page size is) in Active Directory and AD LDS. I.e. so each record has to fit into a single database page of 8k..but you are probably aware that you can fit a LOT more than 8k into an AD object or an exchange e-mail! So how do we store large records? <p>Well, we have different types of columns as illustrated below: <p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/71.png"><img width="665" height="370" title="7" alt="7" src="https://msdnshared.blob.core.windows.net/media/2017/12/7_thumb1.png"></a><p>Tagged columns can be split out into what we call the Long Value Tree. So in the tagged column we store a simple 4 byte number that’s called a LID (Long Value ID) which then points to an entry in the LV tree. So we take the large piece of data, break it up into small chunks and prefix those with the key for the LID and the offset. <p>So, if every part of the record was a LID / pointer to a LV, then essentially we can fit 1300 LV pointers onto the 8k page. btw, this is what creates the <a href="https://blogs.technet.microsoft.com/askds/2015/10/29/administrative-limit-for-this-request-was-exceeded-error-from-active-directory/">1300 attribute limit in AD</a>. It’s all down to the ESE page size. <p>Now you can also start to see that when you are looking at a whole AD object you may read pages from various trees to get all the information about your object. For example, for a user with many attributes and group memberships you may have to get data from a page in the ”datatable” \ Primary tree + “datatable” \ LV tree + sd_table \ Primary tree + link_table \ Primary tree. <h4>Index Trees</h4><p>An index is used for a couple of purposes. Firstly, to make a list of the records in an intelligent order, such as by surname in an alphabetical order. And then secondly to also cut down the number of records which sometimes greatly helps speed up searches (especially when the ‘selectivity is high’ – meaning few entries match).<p>Below is a visual illustration (with the B+ trees turned on their side to make the diagram easier) of a primary index which is the DNT index in the AD Database – the Data Tree.&nbsp; And a secondary index of dNSHostName. You can see that the secondary index only contains the records which has a dNSHostName populated. It is smaller. <p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/81.png"><img width="634" height="334" title="8" alt="8" src="https://msdnshared.blob.core.windows.net/media/2017/12/8_thumb1.png"></a><p>You can also see that in the secondary index, the primary key is the data portion (the name) and then the data is the actual Key that links us back to the REAL record itself. <h3>Inside a Database page</h3><p>Each database page has a fixed <strong>header</strong>. And the header has a<strong> checksum</strong> as well as other information like how much free space is on that page and which B-tree it belongs to. <p>Then we have these things called <strong>TAGS (or nodes),</strong> which store the data. <p><strong>A node can be many things, such as a record in a database table or an entry in an index.</strong><p>The TAGS are actually out of order on the page, but order is established by the tag array at end.<ul><li><p>TAG 0 = Page External Header</p></li></ul><p>This contains variable sized special information on the page, depending upon the type of B-tree and type of page in B tree (space vs. regular tree, and root vs. leaf).<ul><li><p>TAG 1,2,3, etc are all “nodes” or lines, and the order is tracked.</p></li></ul><p>The key &amp; data is specific to the B Tree type.<p>And TAG 1 is actually node 0!!! <strong>So here is a visual picture of what an ESE database page looks like:</strong><p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/91.png"><img width="602" height="335" title="9" alt="9" src="https://msdnshared.blob.core.windows.net/media/2017/12/9_thumb1.png"></a><p>It is possible to calculate this key if you have an object's primary key. In AD this is a DNT.<p>The formulae for that (if you are ever crazy enough to need it) would be:<ul><li><p>Start with 0x7F, and if it is a signed INT append a 0x80000000 and then OR in the number</p></li></ul><ul><li><p>For example 4248 –&gt; in hex 1098 –&gt; as key 7F80001098 (note 5 bytes).</p><li><p>Note: Key buffer uses big endian, not little endian (like x86/amd64 arch).</p><li><p>If it was a 64-bit int, just insert zeros in the middle (9 byte key).</p></li></ul><ul><li><p>If it is an unsigned INT, start with 0x7F and just append the number.</p><li><p>Note: Long Value (LID) trees and ESE’s Space Trees (pgno) are special, no 0x7F (4 byte keys).</p><li><p>And finally other non-integers column types, such as String and Binary types, have a different more complicated formatting for keys.</p></li></ul><p>Why is this useful? Because, for example you can take a DNT of an object and then calculate its key and then seek to its page using esentutl.exe dump page /m functionality and /k option.<p>The Nodes also look different (containing different data) depending on the ESE B+tree type. Below is an illustration of the different nodes in a Space tree, a Data Tree, a LV tree and an Index tree. <p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/103.png"><img width="634" height="354" title="10" alt="10" src="https://msdnshared.blob.core.windows.net/media/2017/12/10_thumb1.png"></a><p>The green are the keys. The dark blue is data. <h4>What does a REAL page look like? </h4><p>You can use <strong>esentutl</strong> to dump pages of the database if you are investigating some corruption for example. <p>Before we can dump a page, we want to find a page of interest (picking a random page could give you just a blank page) … so first we need some info about the table schema, so to start you can dump all the tables and their associated root page numbers like this :<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/1_21.jpg"><img width="666" height="375" title="1_2" alt="1_2" src="https://msdnshared.blob.core.windows.net/media/2017/12/1_2_thumb1.jpg"></a><p>Note, we have findstring’d the output again to get a nice view of just all the tables and their pgnoFDP and objidFDP. <strong>Findstr.exe</strong> is case sensitive so use the exact format or use /i switch. <p><strong>objidFDP</strong> identifies this table in the catalog metadata. When looking at a database page we can use its objidFDP to tell which table this page belongs to. <p><strong>pgnoFDP</strong> is the page number of the <strong>Father Data Page</strong> – the very top page of that <a href="https://en.wikipedia.org/wiki/B%2B_tree">B+ tree</a>, also known as the root page.&nbsp; If you run esentutl /mm &lt;dbname&gt; on its own you will see a huge list of every table and B-tree (except internal “space” trees) including all the indexes. <p>So, in this example page 31 is the root page of the datatable here.<h4>Dumping a page</h4><p>You can dump a page with esentutl using /m and /p. Below is an example of dumping page 31 from the database - the root page of the “datatable” table as above. <p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/23.jpg"><img width="605" height="610" title="2" alt="2" src="https://msdnshared.blob.core.windows.net/media/2017/12/2_thumb1.jpg"></a><p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/32.jpg"><img width="606" height="450" title="3" alt="3" src="https://msdnshared.blob.core.windows.net/media/2017/12/3_thumb1.jpg"></a><p>The objidFDP is the number indicating which B-tree the page belongs to. And the cbFree tells us how much of this page is free. (cb = count of bytes). Each database page has a double header checksum – one ECC (Error Correcting Code) checksum for single bit data correction, and a higher fidelity XOR checksum to catch all other errors, including 3 or more bit errors that the ECC may not catch.&nbsp; In addition, we compute a logged data checksum from the page data, but this is not stored in the header, and only utilized by the Exchange 2016 Database Divergence Detection feature.<p>You can see this is a root page and it has 3 nodes (4 TAGS – remember TAG1 is node 0 also known as line 0! :-) and it is nearly empty! (cbFree = 8092 bytes, so only 100 bytes used for these 3 nodes + page header + external header). <p>The objidFDP tells us which B-Tree this page belongs to.<p>And notice the PageFlushType, which is related to the JET Flush Map file we could talk about in another post later. <p>The nodes here point to pages lower down in the tree. And we could dump a next level page (pgno: 1438)....and we can see them getting deeper and more spread out with more nodes.<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/42.jpg"><img width="630" height="693" title="4" alt="4" src="https://msdnshared.blob.core.windows.net/media/2017/12/4_thumb1.jpg"></a><p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/52.jpg"><img width="633" height="393" title="5" alt="5" src="https://msdnshared.blob.core.windows.net/media/2017/12/5_thumb1.jpg"></a><p>So you can see this page has 294 nodes! Which again all point to other pages. It is also a <strong><font>ParentOfLeaf</font></strong> meaning these pgno / page numbers actually point to leaf pages (with the final data on them). <p>Are you bored yet? <img class="wlEmoticon wlEmoticon-openmouthedsmile" alt="Open-mouthed smile" src="https://msdnshared.blob.core.windows.net/media/2017/12/wlEmoticon-openmouthedsmile.png"><p>Or are you enjoying this like a geek? either way, we are nearly done with the page internals and the tree climbing here.&nbsp; <p>If you navigate more down, eventually you will get a page with some data on it like this for example, let's dump <strong><font>page 69</font></strong> which TAG 6 is pointing to:<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/62.jpg"><img width="637" height="704" title="6" alt="6" src="https://msdnshared.blob.core.windows.net/media/2017/12/6_thumb1.jpg"></a><p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/72.jpg"><img width="630" height="266" title="7" alt="7" src="https://msdnshared.blob.core.windows.net/media/2017/12/7_thumb1.jpg"></a><p>So this one has some data on it (as indicated by the “Leaf page” indicator under the fFlags).&nbsp; <p>Finally, you can also dump the data - the contents of a node (ie TAG) with the /n switch like this:<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/81.jpg"><img width="635" height="270" title="8" alt="8" src="https://msdnshared.blob.core.windows.net/media/2017/12/8_thumb1.jpg"></a></p><p><strong>Remember:</strong> The<strong> <strong>/n</strong></strong> specifier takes a <strong>pgno : line</strong> or node specifier … this means that the :3 here, dumped TAG 4 from the previous screen.&nbsp; And note that trying to dump “/n69:4” would actually fail.</p><p>This /n will dump all the raw data on the page along with the information of columns and their contents and types. The output also needs some translation because it gives us the columnID (711 in the above example) and not the attribute name in AD (or whatever your database may be). The application developer would then be able to translate those column IDs to some meaningful information. For AD and ADLDS, we can translate those to attribute names using the source code. <p>Finally, there really should be no need to do this in real life, other than in a situation where you are debugging a database problem. However, we hope this provided a good and ‘realistic’ demo to help understand and visualize the structure of an ESE database and how the data is stored inside it! <p>Stay tuned for more parts .... which Brett says will be significantly more useful to everyday administrators! ;-)<h2>The End!</h2><p>Linda &amp; Brett]]></content:encoded>
    </item>
    <item>
      <title>Introducing Lingering Object Liquidator v2</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/introducing-lingering-object-liquidator-v2</link>
      <pubDate>Mon, 09 Oct 2017 18:04:49 GMT</pubDate>
      <dc:creator><![CDATA[Ryan Ries [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=16925</guid>
      <description><![CDATA[Greetings again AskDS!

Ryan Ries here. Got something exciting to talk about.

You might be...]]></description>
      <content:encoded><![CDATA[Greetings again AskDS!

<a href="https://blogs.technet.microsoft.com/askds/tag/ryan-ries/">Ryan Ries</a> here. Got something exciting to talk about.

You might be familiar with the original <a href="https://blogs.technet.microsoft.com/askds/2014/09/15/remove-lingering-objects-that-cause-ad-replication-error-8606-and-friends/">Lingering Object Liquidator</a> tool that was released a few years ago.

Today, we're proud to announce version 2 of <a href="http://aka.ms/msftlol">Lingering Object Liquidator</a>!

Because Justin's blog post from 2014 covers the fundamentals of what lingering objects are so well, I don't think I need to go over it again here. If you need to know what lingering objects in Active Directory are, and why you want to get rid of them, then please go read <a href="https://blogs.technet.microsoft.com/askds/2014/09/15/remove-lingering-objects-that-cause-ad-replication-error-8606-and-friends/">that post</a> first.

The new version of the Lingering Object Liquidator tool began its life as an attempt to address some of the long-standing limitations of the old version. For example, the old version would just stop the entire scan when it encountered a single domain controller that was unreachable. The new version will just skip the unreachable DC and continue scanning the other DCs that are reachable. There are multiple other improvements in the tool as well, such as multithreading and more exhaustive logging.

Before we take a look at the new tool, there are some things you should know:

1) Lingering Object Liquidator - neither the old version nor the new version - are covered by CSS Support Engineers. A small group of us (including yours truly) have provided this tool as a convenience to you, but it comes with no guarantees. If you find a problem with the tool, or have a feature request, drop a line to the public <a href="mailto:askdspub@microsoft.com">AskDS public email address</a>, or submit feedback to the <a href="https://windowsserver.uservoice.com/forums/304621-active-directory?category_id=320170">Windows Server UserVoice forum</a>, but please don't bother Support Engineers with it on a support case.

2) Don't immediately go into your production Active Directory forest and start wildly deleting things just because they show up as lingering objects in the tool. Please carefully review and consider any AD objects that are reported to be lingering objects before deleting.

3) The tool may report some false positives for deleted objects that are very close to the garbage collection age. To mitigate this issue, you can <a href="https://msdn.microsoft.com/en-us/library/cc223317.aspx">manually initiate garbage collection</a> on your domain controllers before using this tool. (We may add this so the tool does it automatically in the future.)

4) The tool will continue to evolve and improve based on <b>your</b> feedback! Contact the AskDS alias or the Uservoice forum linked to in #1 above with any questions, concerns, bug reports or feature requests.
<h2>Graphical User Interface Elements</h2>
Let's begin by looking at the graphical user interface. Below is a legend that explains each UI element:

[caption id="attachment_16956" align="alignnone" width="1044"]<img src="https://msdnshared.blob.core.windows.net/media/2017/10/lol2021.png" alt="Lingering Object Liquidator v2" width="1044" height="604" class="size-full wp-image-16956" /> Lingering Object Liquidator v2[/caption]

A) "Help/About" label. Click this and a page should open up in your default web browser with extra information and detail regarding Lingering Object Liquidator.

B) "Check for Updates" label. Click this and the tool will check for a newer version than the one you're currently running.

C) "Detect AD Topology" button. This is the first button that should be clicked in most scenarios. The AD Topology must be generated first, before proceeding on to the later phases of lingering object detection and removal.

D) "Naming Context" drop-down menu. (Naming Contexts are sometimes referred to as partitions.) Note that this drop-down menu is only available after AD Topology has been successfully discovered. It contains each Active Directory naming context in the forest. If you know precisely which Active Directory Naming context that you want to scan for lingering objects, you can select it from this menu. (Note: The Schema partition is omitted because it does not support deletion, so in theory it cannot contain lingering objects.) If you do not know which naming contexts may contain lingering objects, you can select the "[Scan All NCs]" option and the tool will scan each Naming Context that it was able to discover during the AD Topology phase.

E) "Reference DC" drop-down menu. Note that this drop-down menu is only available after AD Topology has been successfully discovered. The reference DC is the "known-good" DC against which you will compare other domain controllers for lingering objects. If a domain controller contains AD objects that do not exist on the Reference DC, they will be considered lingering objects. If you select the "[Scan Entire Forest]" option, then the tool will (arbitrarily) select one global catalog from each domain in the forest that is known to be reachable. <b>It is recommended that you wisely choose a known-good DC yourself, because the tool doesn't necessarily know "the best" reference DC to pick. It will pick one at random.</b>

F) "Target DC" drop-down menu. Note that this drop-down menu is only available after AD Topology has been successfully discovered. The Target DC is the domain controller that is suspected of containing lingering objects. The Target DC will be compared against the Reference DC, and each object that exists on the Target DC but not on the Reference DC is considered a lingering object. If you aren’t sure which DC(s) contain lingering objects, or just want to scan all domain controllers, select the "[Target All DCs]" option from the drop-down menu.

G) "Detect Lingering Objects" button. Note that this button is only available after AD Topology has been successfully discovered. After you have made the appropriate selections in the three aforementioned drop-down menus, click the Detect Lingering Objects button to run the scan. Clicking this button only runs a scan; it does not delete anything. The tool will automatically detect and avoid certain nonsensical situations, such as the user specifying the same Reference and Target DCs, or selecting a Read-Only Domain Controller (RODC) as a Reference DC.

H) "Select All" button. Note that this button does not become available until after lingering objects have been detected. Clicking it merely selects all rows from the table below.

I) "Remove Selected Lingering Objects" button. This button will attempt to delete all lingering objects that have been detected by the detection process. You can select a range of items from the list using the shift key and the arrow keys. You can select and unselect specific items by holding down the control key and clicking on them. If you want to just select all items, click the "Select All" button.

J) "Removal Method" radio buttons. These are mutually exclusive. You can choose which of the two supported methods you want to use to remove the lingering objects that have been detected. The "removeLingeringObject" method refers to the <a href="https://msdn.microsoft.com/en-us/library/cc223303.aspx">rootDSE modify operation</a>, which can be used to "spot-remove" individual lingering objects. In contrast, the <a href="https://msdn.microsoft.com/en-us/library/ms676035(v=vs.85).aspx">DsReplicaVerifyObjects method</a> will remove <b>all</b> lingering objects all at once. This intention is reflected in the GUI by all lingering objects automatically being selected when the DsReplicaVerifyObjects method is chosen.

K) "Import" button. This imports a previously-exported list of lingering objects.

L) "Export" button. This exports the selected lingering objects to a file.

M) The "Target DC Column." This column tells you which Target DC was seen to have contained the lingering object.

N) The "Reference DC Column." This column tells you which Reference DC was used to determine that the object in question was lingering.

O) The "Object DN Column." This column contains the distinguished name of the lingering object.

P) The "Naming Context Column." This column contains the Naming Context that the lingering object resides in.

Q) The "Lingering Object ListView". This "ListView" works similarly to a spreadsheet. It will display all lingering objects that were detected. You can think of each row as a lingering object. You can click on the column headers to sort the rows in ascending or descending order, and you can resize the columns to fit your needs. <b>NOTE: If you right-click on the lingering object listview, the selected lingering objects (if any) will be copied to your clipboard.</b>

R) The "Status" box. The status box contains diagnostics and operational messages from the Lingering Object Liquidator tool. Everything that is logged to the status box in the GUI is also mirrored to a text log file.
<h2>User-configurable Settings</h2>
&nbsp;

The user-configurable settings in Lingering Object Liquidator are alluded to in the Status box when the application first starts.
<pre>Key: HKLM\SOFTWARE\LingeringObjectLiquidator
Value: DetectionTimeoutPerDCSeconds
Type: DWORD
Default: 300 seconds
</pre>
This setting affects the “Detect Lingering Objects” scan. Lingering Object Liquidator establishes event log “subscriptions” to each Target DC that it needs to scan. The tool then waits for the DC to log an event (Event ID 1942 in the Directory Service event log) signaling that lingering object detection has completed for a specific naming context. Only once a certain number of those events (depending on your choices in the “Naming Contexts” drop-down menu,) have been received from the remote domain controller, does the tool know that particular domain controller has been fully scanned. However, there is an overall timeout, and if the tool does not receive the requisite number of Event ID 1942s in the allotted time, the tool “gives up” and proceeds to the next domain controller.
<pre>Key: HKLM\SOFTWARE\LingeringObjectLiquidator
Value: ThreadCount
Type: DWORD
Default: 8 threads
</pre>
This setting sets the maximum number of threads to use during the “Detect Lingering Objects” scan. Using more threads may decrease the overall time it takes to complete a scan, especially in very large environments.
<h2>Tips</h2>
The domain controllers must allow the network connectivity required for remote event log management for Lingering Object Liquidator to work. You can enable the required Windows Firewall rules using the following line of PowerShell:
<pre>Get-NetFirewallRule -DisplayName "Remote Event Log*" | Enable-NetFirewallRule
</pre>
Check the download site often for new versions! (There's also a handy "check for updates" option in the tool.)

&nbsp;
<h2>Final Words</h2>
We provide this tool because we at AskDS want your Active Directory lingering object removal experience to go as smoothly as possible. If you find any bugs or have any feature requests, please drop a note to <a href="mailto:askdspub@microsoft.com">our public contact alias</a>.

Download: <a href="http://aka.ms/msftlol">http://aka.ms/msftlol</a>

&nbsp;
<h2>Release Notes</h2>
v2.0.19:
- Initial release to the public.

v2.0.21:
- Added new radio buttons that allow the user more control over which lingering object removal method they want to use - the DsReplicaVerifyObjects method or removeLingeringObject method.
- Fixed issue with Export button not displaying the full path of the export file.
- Fixed crash when unexpected or corrupted data is returned from event log subscription.
]]></content:encoded>
    </item>
    <item>
      <title>Active Directory Experts: apply within</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/active-directory-experts-apply-within</link>
      <pubDate>Wed, 26 Jul 2017 21:56:50 GMT</pubDate>
      <dc:creator><![CDATA[Justin Turner [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=16955</guid>
      <description><![CDATA[Hi all! Justin Turner here from the Directory Services team with a brief announcement: We are...]]></description>
      <content:encoded><![CDATA[<p>Hi all! Justin Turner here from the Directory Services team with a brief announcement: <b>We are hiring!</b></p><p>Would you like to join the U.S. Directory Services team and work on the most technically challenging and interesting Active Directory problems? Do you want to be the next <a href="https://blogs.technet.microsoft.com/askds/tag/ned-pyle/" target="_blank">Ned Pyle</a> or <a href="https://blogs.technet.microsoft.com/askds/tag/linda-taylor/" target="_blank">Linda Taylor</a>?</p><p>Then read more…</p><p>We are an escalation team based out of Irving, Texas; Charlotte, North Carolina; and Fargo, North Dakota. We work with enterprise customers helping them resolve the most critical Active Directory infrastructure problems as well as enabling them to get the best of Microsoft Windows and Identity-related technologies. The work we do is no ordinary support – we work with a huge variety of customer environments and there are rarely two problems which are the same. </p><p>You will need strong AD knowledge, strong troubleshooting skills, along with great collaboration, team work and customer service skills.</p><p>If this sounds like you, please apply here:</p><p>Irving, Texas (Las Colinas):<br><a href="https://careers.microsoft.com/jobdetails.aspx?ss=&amp;pg=0&amp;so=&amp;rw=2&amp;jid=290399&amp;jlang=en&amp;pp=ss">https://careers.microsoft.com/jobdetails.aspx?ss=&amp;pg=0&amp;so=&amp;rw=2&amp;jid=290399&amp;jlang=en&amp;pp=ss</a><p>Charlotte, North Carolina:<br><a href="https://careers.microsoft.com/jobdetails.aspx?ss=&amp;pg=0&amp;so=&amp;rw=1&amp;jid=290398&amp;jlang=en&amp;pp=ss">https://careers.microsoft.com/jobdetails.aspx?ss=&amp;pg=0&amp;so=&amp;rw=1&amp;jid=290398&amp;jlang=en&amp;pp=ss</a><p>U.S. citizenship is required for these positions.<p><br><p>Justin</p>]]></content:encoded>
    </item>
    <item>
      <title>Using Debugging Tools to Find Token and Session Leaks</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/using-debugging-tools-to-find-token-and-session-leaks</link>
      <pubDate>Wed, 05 Apr 2017 17:59:27 GMT</pubDate>
      <dc:creator><![CDATA[Ryan Ries [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=16645</guid>
      <description><![CDATA[Hello AskDS readers and Identity aficionados. Long time no blog.

Ryan Ries here, and today I have...]]></description>
      <content:encoded><![CDATA[Hello AskDS readers and Identity aficionados. Long time no blog.

<a href="https://blogs.technet.microsoft.com/askds/tag/ryan-ries/">Ryan Ries</a> here, and today I have a relatively "hardcore" blog post that will not be for the faint of heart. However, it's about an important topic.

The behavior surrounding security tokens and logon sessions has recently changed on all supported versions of Windows. IT professionals - developers and administrators alike - should understand what this new behavior is, how it can affect them, and how to troubleshoot it.

But first, a little background...

[caption id="attachment_16655" align="alignnone" width="394"]<img width="394" height="302" class="wp-image-16655 size-full" alt="Figure 1 - Tokens" src="https://msdnshared.blob.core.windows.net/media/2017/03/tokens.png" /> Figure 1 - Tokens[/caption]

Windows uses <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa374909(v=vs.85).aspx">security tokens</a> (or access tokens) extensively to control access to system resources. Every thread running on the system uses a security token, and may own several at a time. Threads inherit the security tokens of their parent processes by default, but they may also use special security tokens that represent other identities in an activity known as impersonation. Since security tokens are used to grant access to resources, they should be treated as highly sensitive, because if a malicious user can gain access to someone else's security token, they will be able to access resources that they would not normally be authorized to access.

<em> Note: Here are some additional references you should read first if you want to know more about access tokens:</em>
<ul>
 	<li><a href="https://blogs.technet.microsoft.com/askds/2007/11/02/whats-in-a-token/"><em>What's in a Token</em></a></li>
 	<li><a href="https://blogs.technet.microsoft.com/askds/2008/01/11/whats-in-a-token-part-2-impersonation/"><em>What's in a Token Part 2 - Impersonation</em></a></li>
 	<li><i><em><a href="https://technet.microsoft.com/en-us/sysinternals/bb963901.aspx">Windows Internals, 6<sup>th</sup> Ed. Chapter 6</a></em></i></li>
</ul>
If you are an application developer, your application or service may want to create or duplicate tokens for the legitimate purpose of impersonating another user. A typical example would be a server application that wants to impersonate a client to verify that the client has permissions to access a file or database. The application or service must be diligent in how it handles these access tokens by releasing/destroying them as soon as they are no longer needed. If the code fails to call the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa379295(v=vs.85).aspx">CloseHandle</a> function on a token handle, that token can then be "leaked" and remain in memory long after it is no longer needed.

And that brings us to <a href="https://technet.microsoft.com/en-us/library/security/ms16-111.aspx">Microsoft Security Bulletin MS16-111</a>.

Here is an excerpt from that Security Bulletin:
<blockquote style="background-color: #eeeeee">Multiple Windows session object elevation of privilege vulnerabilities exist in the way that Windows handles session objects.

A locally authenticated attacker who successfully exploited the vulnerabilities could hijack the session of another user.
To exploit the vulnerabilities, the attacker could run a specially crafted application.
The update corrects how Windows handles session objects to prevent user session hijacking.</blockquote>
Those vulnerabilities were fixed with that update, and I won't further expound on the "hacking/exploiting" aspect of this topic. We're here to explore this from a debugging perspective.

This update is significant because it changes how the relationship between tokens and logon sessions is treated across all supported versions of Windows going forward. Applications and services that erroneously leak tokens have always been with us, but the penalty paid for leaking tokens is now greater than before. After MS16-111, when security tokens are leaked, the logon sessions associated with those security tokens also remain on the system until all associated tokens are closed... even after the user has logged off the system. If the tokens associated with a given logon session are never released, then the system now also has a permanent logon session leak as well. If this leak happens often enough, such as on a busy Remote Desktop/Terminal Server where users are logging on and off frequently, it can lead to resource exhaustion on the server, performance issues and denial of service, ultimately causing the system to require a reboot to be returned to service.

Therefore, it's more important than ever to be able to identify the symptoms of token and session leaks, track down token leaks on your systems, and get your application vendors to fix them.

<span style="font-size: large"><b>How Do I Know If My Server Has Leaks?</b></span>

As mentioned earlier, this problem affects heavily-utilized Remote Desktop Session Host servers the most, because users are constantly logging on and logging off the server. The issue is not limited to Remote Desktop servers, but symptoms will be most obvious there.

Figuring out that you have logon session leaks is the easy part. Just run <a href="https://technet.microsoft.com/en-us/library/cc731503(v=ws.11).aspx"><span style="font-family: monospace">qwinsta</span></a> at a command prompt:

[caption id="attachment_16665" align="alignnone" width="621"]<img width="621" height="250" class="size-full wp-image-16665" alt="Figure 2 - qwinsta" src="https://msdnshared.blob.core.windows.net/media/2017/03/qwinsta.png" /> Figure 2 - qwinsta[/caption]

Pay close attention to the session ID numbers, and notice the large gap between session 2 and session 152. This is the clue that the server has a logon session leak problem. The next user that logs on will get session 153, the next user will get session 154, the next user will get session 155, and so on. But the session IDs will never be reused. We have 150 "leaked" sessions in the screenshot above, where no one is logged on to those sessions, no one will ever be able to log on to those sessions ever again (until a reboot,) yet they remain on the system indefinitely. This means each user who logs onto the system is inadvertently leaving tokens lying around in memory, probably because some application or service on the system duplicated the user's token and didn't release it. These leaked sessions will forever be unusable and soak up system resources. And the problem will only get worse as users continue to log on to the system. In an optimal situation where there were no leaks, sessions 3-151 would have been destroyed after the users logged out and the resources consumed by those sessions would then be reusable by subsequent logons.

<span style="font-size: large"><b>How Do I Find Out Who's Responsible?</b></span>

Now that you know you have a problem, next you need to track down the application or service that is responsible for leaking access tokens. When an access token is created, the token is associated to the logon session of the user who is represented by the token, and an internal reference count is incremented. The reference count is decremented whenever the token is destroyed. If the reference count never reaches zero, then the logon session is never destroyed or reused. Therefore, to resolve the logon session leak problem, you must resolve the underlying token leak problem(s). It's an all-or-nothing deal. If you fix 10 token leaks in your code but miss 1, the logon session leak will still be present as if you had fixed none.

Before we proceed: I would recommend debugging this issue on a lab machine, rather than on a production machine. If you have a logon session leak problem on your production machine, but don't know where it's coming from, then install all the same software on a lab machine as you have on the production machine, and use that for your diagnostic efforts. You'll see in just a second why you probably don't want to do this in production.

The first step to tracking down the token leaks is to enable token leak tracking on the system.

Modify this registry setting:
<pre>HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Kernel
    SeTokenLeakDiag = 1 (DWORD)
</pre>
The registry setting won't exist by default unless you've done this before, so create it. It also did not exist prior to MS16-111, so don't expect it to do anything if the system does not have MS16-111 installed. This registry setting enables extra accounting on token issuance that you will be able to detect in a debugger, and there may be a noticeable performance impact on busy servers. Therefore, it is not recommended to leave this setting in place unless you are actively debugging a problem. (i.e. don't do it in production exhibit A.)

Prior to the existence of this registry setting, token leak tracing of this kind used to require using a checked build of Windows. And Microsoft seems to not be releasing a checked build of Server 2016, so... good timing.

Next, you need to configure the server to take a full or kernel memory dump when it crashes. (A live kernel debug may also be an option, but that is outside the scope of this article.) I recommend using <a href="http://winplattools.codeplex.com/SourceControl/changeset/view/14600">DumpConfigurator</a> to configure the computer for complete crash dumps. A kernel dump should be enough to see most of what we need, but get a Complete dump if you can.

[caption id="attachment_16675" align="alignnone" width="860"]<img width="860" height="451" class="size-full wp-image-16675" alt="Figure 3 - DumpConfigurator" src="https://msdnshared.blob.core.windows.net/media/2017/03/dumpconfigurator1.png" /> Figure 3 - DumpConfigurator[/caption]

Then reboot the server for the settings to take effect.

Next, you need users to log on and off the server, so that the logon session IDs continue to climb. Since you're doing this in a lab environment, you might want to use a script to automatically logon and logoff a set of test users. (I provided a sample script for you <a href="https://gallery.technet.microsoft.com/scriptcenter/LogonRDPUsersps1-5ff28b57">here</a>.) Make sure you've waited 10 minutes after the users have logged off to verify that their logon sessions are permanently leaked before proceeding.

Finally, crash the box. Yep, just crash it. (i.e. don't do it in production exhibit B.) On a physical machine, this can be done by hitting Right-Ctrl+Scroll+Scroll if you configured the appropriate setting with DumpConfigurator earlier. If this is a Hyper-V machine, you can use the following PowerShell cmdlet on the Hyper-V host:
<pre>Debug-VM -VM (Get-VM RDS1) -InjectNonMaskableInterrupt</pre>
You may have at your disposal other means of getting a non-maskable interrupt to the machine, such as an out-of-band management card (iLO/DRAC, etc.,) but the point is to deliver an NMI to the machine, and it will bugcheck and generate a memory dump.

Now transfer the memory dump file (C:\Windows\Memory.dmp usually) to whatever workstation you will use to perform your analysis.

<em> Note: Memory dumps may contain sensitive information, such as passwords, so be mindful when sharing them with strangers.</em>

Next, install the Windows Debugging Tools on your workstation if they're not already installed. I downloaded mine for this demo from the Windows Insider Preview SDK <a href="https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewSDK">here</a>. But they also come with the SDK, the WDK, WPT, Visual Studio, etc. The more recent the version, the better.

Next, download the <a href="https://www.microsoft.com/en-us/download/details.aspx?id=53304">MEX Debugging Extension for WinDbg</a>. Engineers within Microsoft have been using the MEX debugger extension for years, but only recently has a public version of the extension been made available. The public version is stripped-down compared to the internal version, but it's still quite useful. Unpack the file and place mex.dll into your C:\Debuggers\winext directory, or wherever you installed WinDbg.

Now, ensure that your symbol path is configured correctly to use the Microsoft public symbol server within WinDbg:

[caption id="attachment_16685" align="alignnone" width="596"]<img width="596" height="263" class="size-full wp-image-16685" alt="Figure 4 - Example Symbol Path in WinDbg" src="https://msdnshared.blob.core.windows.net/media/2017/03/sympath.png" /> Figure 4 - Example Symbol Path in WinDbg[/caption]

The example symbol path above tells WinDbg to download symbols from the specified URL, and store them in your local C:\Symbols directory.

Finally, you are ready to open your crash dump in WinDbg:

[caption id="attachment_16695" align="alignnone" width="415"]<img width="415" height="428" class="size-full wp-image-16695" alt="Figure 5 - Open Crash Dump from WinDbg" src="https://msdnshared.blob.core.windows.net/media/2017/03/opencrashdump.png" /> Figure 5 - Open Crash Dump from WinDbg[/caption]

After opening the crash dump, the first thing you'll want to do is load the MEX debugging extension that you downloaded earlier, by typing the command:

[caption id="attachment_16705" align="alignnone" width="269"]<img width="269" height="128" class="size-full wp-image-16705" alt="Figure 6 - .load mex" src="https://msdnshared.blob.core.windows.net/media/2017/03/loadmex.png" /> Figure 6 - .load mex[/caption]

The next thing you probably want to do is start a log file. It will record everything that goes on during this debugging session, so that you can refer to it later in case you forgot what you did or where you left off.

[caption id="attachment_16715" align="alignnone" width="652"]<img width="652" height="106" class="size-full wp-image-16715" alt="Figure 7 - !logopen" src="https://msdnshared.blob.core.windows.net/media/2017/03/logopen.png" /> Figure 7 - !logopen[/caption]

Another useful command that is among the first things I always run is <span style="font-family: monospace">!DumpInfo</span>, abbreviated <span style="font-family: monospace">!di</span>, which simply gives some useful basic information about the memory dump itself, so that you can verify at a glance that you've got the correct dump file, which machine it came from and what type of memory dump it is.

[caption id="attachment_16725" align="alignnone" width="620"]<img width="620" height="240" class="size-full wp-image-16725" alt="Figure 8 - !DumpInfo" src="https://msdnshared.blob.core.windows.net/media/2017/03/dumpinfo.png" /> Figure 8 - !DumpInfo[/caption]

You're ready to start debugging.

At this point, I have good news and I have bad news.

The good news is that there already exists a super-handy debugger extension that lists all the logon session kernel objects, their associated token reference counts, what process was responsible for creating the token, and even the token creation stack, all with a single command! It's
<a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff564016(v=vs.85).aspx"><span style="font-family: monospace">!kdexts.logonsession</span></a>, and it is <em>awesome</em>.

The bad news is that it doesn't work... not with public symbols. It only works with private symbols. Here is what it looks like with public symbols:

[caption id="attachment_16735" align="alignnone" width="1163"]<img width="1163" height="247" class="size-full wp-image-16735" alt="Figure 9 - !kdexts.logonsession - public symbols lead to lackluster output" src="https://msdnshared.blob.core.windows.net/media/2017/03/logonsessionwithpublics.png" /> Figure 9 - !kdexts.logonsession - public symbols lead to lackluster output[/caption]

As you can see, most of the useful stuff is zeroed out.

Since public symbols are all you have unless you work at Microsoft, (<a href="https://www.linkedin.com/jobs/view/267880195/">and we wish you did</a>,) I'm going to teach you how to do what
<span style="font-family: monospace">!kdexts.logonsession</span> does, manually. The hard way. Plus some extra stuff. Buckle up.

First, you should verify whether token leak tracking was turned on when this dump was taken. (That was the registry setting mentioned earlier.)

[caption id="attachment_16745" align="alignnone" width="530"]<img width="530" height="72" class="size-full wp-image-16745" alt="Figure 10 - SeTokenLeakTracking = &lt;no type information&gt;" src="https://msdnshared.blob.core.windows.net/media/2017/03/setokenleaktracking.png" /> Figure 10 - x nt!SeTokenLeakTracking = &lt;no type information&gt;[/caption]

OK... That was not very useful. We're getting <span style="font-family: monospace">&lt;no type information&gt;</span> because we're using public symbols. But this symbol corresponds to the <span style="font-family: monospace">SeTokenLeakDiag</span> registry setting that we configured earlier, and we know that's just 0 or 1, so we can just guess what type it is:

[caption id="attachment_16755" align="alignnone" width="307"]<img width="307" height="73" class="size-full wp-image-16755" alt="Figure 11 - db nt!SeTokenLeakTracking L1" src="https://msdnshared.blob.core.windows.net/media/2017/03/setokenleaktracking2.png" /> Figure 11 - db nt!SeTokenLeakTracking L1[/caption]

The <span style="font-family: monospace">db</span> command means "dump bytes." (<span style="font-family: monospace">dd</span>, or "dump DWORDs," would have worked just as well.) You should have a symbol for
<span style="font-family: monospace">nt!SeTokenLeakTracking</span> if you configured your symbol path properly, and the <span style="font-family: monospace">L1</span> tells the debugger to just dump the first byte it finds. It should be either 0 or 1. If it's 0, then the registry setting that we talked about earlier was not set properly, and you can basically just discard this dump file and get a new one. If it's 1, you're in business and may proceed.

Next, you need to locate the logon session lists.

[caption id="attachment_16765" align="alignnone" width="305"]<img width="305" height="73" class="size-full wp-image-16765" alt="Figure 12 - dp nt!SepLogonSessions L1" src="https://msdnshared.blob.core.windows.net/media/2017/03/seplogonsessionslist.png" /> Figure 12 - dp nt!SepLogonSessions L1[/caption]

Like the previous step, <span style="font-family: monospace">dp</span> means "display pointer," then the name of the symbol, and <span style="font-family: monospace">L1</span> to just display a single pointer. The 64-bit value on the right is the pointer, and the 64-bit value on the left is the memory address of that pointer.

Now we know where our lists of logon sessions begin. (Lists, plural.)

The <span style="font-family: monospace">SepLogonSessions</span> pointer points to not just a list, but an array of lists. These lists are made up of <span style="font-family: monospace">_SEP_LOGON_SESSION_REFERENCES</span> structures.

Using the <span style="font-family: monospace">dps</span> command (display contiguous pointers) and specifying the beginning of the array that we got from the last step, we can now see where each of the lists in the array begins:

[caption id="attachment_16775" align="alignnone" width="345"]<img width="345" height="277" class="size-full wp-image-16775" alt="Figure 13 - dps 0xffffb808&#096;3ea02650 – displaying pointers that point to the beginning of each list in the array" src="https://msdnshared.blob.core.windows.net/media/2017/03/dps1.png" /> Figure 13 - dps 0xffffb808`3ea02650 – displaying pointers that point to the beginning of each list in the array[/caption]

If there were not very many logon sessions on the system when the memory dump was taken, you might notice that not all the lists are populated:

[caption id="attachment_16785" align="alignnone" width="337"]<img width="337" height="251" class="size-full wp-image-16785" alt="Figure 14 - Some of the logon session lists are empty because not very many users had logged on in this example" src="https://msdnshared.blob.core.windows.net/media/2017/04/emptylogonsessionlists.png" /> Figure 14 - Some of the logon session lists are empty because not very many users had logged on in this example[/caption]

The array doesn't fill up contiguously, which is a bummer. You'll have to skip over the empty lists.

If we wanted to walk just the first list in the array (we'll talk more about <span style="font-family: monospace">dt</span> and linked lists in just a minute,) it would look something like this:

[caption id="attachment_16795" align="alignnone" width="721"]<img width="721" height="273" class="size-full wp-image-16795" alt="Figure 15 - Walking the first list in the array and using !grep to filter the output" src="https://msdnshared.blob.core.windows.net/media/2017/04/walkinglist1.png" /> Figure 15 - Walking the first list in the array and using !grep to filter the output[/caption]

Notice that I used the <span style="font-family: monospace">!grep</span> command to filter the output for the sake of brevity and readability. It's part of the Mex debugger extension. I told you it was handy. If you omit the <span style="font-family: monospace">!grep AccountName</span> part, you would get the full, unfiltered output. I chose "AccountName" arbitrarily as a keyword because I knew that was a word that was unique to each element in the list. <span style="font-family: monospace">!grep</span> will only display lines that contain the keyword(s) that you specify.

Next, if we wanted to walk through the entire array of lists all at once, it might look something like this:

[caption id="attachment_16797" align="alignnone" width="1031"]<img width="1031" height="80" class="size-full wp-image-16797" alt="Figure 16 - Walking through the entire array of lists!" src="https://msdnshared.blob.core.windows.net/media/2017/04/walkingallthelists.png" /> Figure 16 - Walking through the entire array of lists![/caption]

OK, I realize that I just went bananas there, but I'll explain what just happened step-by-step.

When you are using the Mex debugger extension, you have access to many new text parsing and filtering commands that can truly enhance your debugging experience. When you look at a long command like the one I just showed, read it from right to left. The commands on the right are fed into the command to their left.

So from right to left, let's start with <span style="font-family: monospace">!cut -f 2 dps ffffb808`3ea02650</span>

We already showed what the <span style="font-family: monospace">dps &lt;address&gt;</span> command did earlier. The <span style="font-family: monospace">!cut -f 2</span> command filters that command's output so that it only displays the second part of each line separated by whitespace. So essentially, it will display only the pointers themselves, and not their memory addresses.

Like this:

[caption id="attachment_16805" align="alignnone" width="324"]<img width="324" height="269" class="size-full wp-image-16805" alt="Figure 17 - Using !cut to select just the second token in each line of output" src="https://msdnshared.blob.core.windows.net/media/2017/04/cut1.png" /> Figure 17 - Using !cut to select just the second token in each line of output[/caption]

Then that is "piped" line-by-line into the next command to the left, which was:

<span style="font-family: monospace">!fel -x "dt nt!_SEP_LOGON_SESSION_REFERENCES @#Line -l Next"</span>

<span style="font-family: monospace">!fel</span> is an abbreviation for <span style="font-family: monospace">!foreachline</span>.

This command instructs the debugger to execute the given command for each line of output supplied by the previous command, where the <span style="font-family: monospace">@#Line</span> pseudo-variable represents the individual line of output. For each line of output that came from the <span style="font-family: monospace">dps</span> command, we are going to use the <span style="font-family: monospace">dt</span> command with the <span style="font-family: monospace">-l</span> parameter to walk that list. (More on walking lists in just a second.)

Next, we use the <span style="font-family: monospace">!grep</span> command to filter all of that output so that only a single unique line is shown from each list element, as I showed earlier.

Finally, we use the <span style="font-family: monospace">!count -q</span> command to suppress all of the output generated up to that point, and instead only tell us how many lines of output it <em>would have</em> generated. This should be the total number of logon sessions on the system.

And 380 was in fact the exact number of logon sessions on the computer when I collected this memory dump. (Refer to Figure 16.)

Alright... now let's take a deep breath and a step back. We just walked an entire array of lists of structures with a single line of commands. But now we need to zoom in and take a closer look at the data structures contained within those lists.

Remember, <span style="font-family: monospace">ffffb808`3ea02650</span> was the very beginning of the entire array.

Let's examine just the very first <span style="font-family: monospace">_SEP_LOGON_SESSION_REFERENCES</span> entry of the first list, to see what such a structure looks like:

[caption id="attachment_16806" align="alignnone" width="705"]<img width="705" height="294" class="size-full wp-image-16806" alt="Figure 18 - dt _SEP_LOGON_SESSION_REFERENCES* ffffb808&#096;3ea02650" src="https://msdnshared.blob.core.windows.net/media/2017/04/seplogonsessions1.png" /> Figure 18 - dt _SEP_LOGON_SESSION_REFERENCES* ffffb808`3ea02650[/caption]

That's a logon session!

Let's go over a few of the basic fields in this structure. (Skipping some of the more advanced ones.)
<ul>
 	<li><span style="font-family: monospace"><strong>Next</strong></span>: This is a pointer to the next element in the list. You might notice that there's a "<span style="font-family: monospace">Next</span>," but there's no "<span style="font-family: monospace">Previous</span>." So, you can only walk the list in one direction. This is a singly-linked list.</li>
 	<li><span style="font-family: monospace"><strong>LogonId</strong></span>: Every logon gets a unique one. For example, "<span style="font-family: monospace">0x3e7</span>" is always the "System" logon.</li>
 	<li><span style="font-family: monospace"><strong>ReferenceCount</strong></span>: This is how many outstanding token references this logon session has. This is the number that must reach zero before the logon session can be destroyed. In our example, it's 4.</li>
 	<li><span style="font-family: monospace"><strong>AccountName</strong></span>: The user who does or used to occupy this session.</li>
 	<li><span style="font-family: monospace"><strong>AuthorityName</strong></span>: Will be the user's Active Directory domain, typically. Or the computer name if it's a local account.</li>
 	<li><span style="font-family: monospace"><strong>TokenList</strong></span>: This is a doubly or circularly-linked list of the tokens that are associated with this logon session. The number of tokens in this list should match the <span style="font-family: monospace">ReferenceCount</span>.</li>
</ul>
The following is an illustration of a doubly-linked list:

[caption id="attachment_16815" align="alignnone" width="567"]<img width="567" height="359" class="size-full wp-image-16815" alt="Figure 19 - Doubly or circularly-linked list" src="https://msdnshared.blob.core.windows.net/media/2017/04/doublylinkedlist.png" /> Figure 19 - Doubly or circularly-linked list[/caption]

"<span style="font-family: monospace">Flink</span>" stands for Forward Link, and "<span style="font-family: monospace">Blink</span>" stands for Back Link.

So now that we understand that the <span style="font-family: monospace">TokenList</span> member of the <span style="font-family: monospace">_SEP_LOGON_SESSION_REFERENCES</span> structure is a linked list, here is how you walk that list:

[caption id="attachment_16825" align="alignnone" width="862"]<img width="862" height="480" class="size-full wp-image-16825" alt="Figure 20 - dt nt!_LIST_ENTRY* 0xffffb808&#096;500bdba0+0x0b0 -l Flink" src="https://msdnshared.blob.core.windows.net/media/2017/04/walktokenlist1.png" /> Figure 20 - dt nt!_LIST_ENTRY* 0xffffb808`500bdba0+0x0b0 -l Flink[/caption]

The <span style="font-family: monospace">dt</span> command stands for "display type," followed by the symbol name of the type that you want to cast the following address to. The reason why we specified the address <span style="font-family: monospace">0xffffb808`500bdba0</span> is because that is the address of the <span style="font-family: monospace">_SEP_LOGON_SESSION_REFERENCES</span> object that we found earlier. The reason why we added <span style="font-family: monospace">+0x0b0</span> after the memory address is because that is the offset from the beginning of the structure at which the <span style="font-family: monospace">TokenList</span> field begins. The <span style="font-family: monospace">-l</span> parameter specifies that we're trying to walk a list, and finally you must specify a field name (<span style="font-family: monospace">Flink</span> in this case) that tells the debugger which field to use to navigate to the next node in the list.

We walked a list of tokens and what did we get? A list head and 4 data nodes, 5 entries total, which lines up with the <span style="font-family: monospace">ReferenceCount</span> of 4 tokens that we saw earlier. One of the nodes won't have any data – that's the list head.

Now, for each entry in the linked list, we can examine its data. We know the payloads that these list nodes carry are tokens, so we can use <span style="font-family: monospace">dt</span> to cast them as such:

[caption id="attachment_16835" align="alignnone" width="773"]<img width="773" height="703" class="size-full wp-image-16835" alt="Figure 21 - dt _TOKEN*0xffffb808&#096;4f565f40+8+8 - Examining the first token in the list" src="https://msdnshared.blob.core.windows.net/media/2017/04/tokendbg1.png" /> Figure 21 - dt _TOKEN*0xffffb808`4f565f40+8+8 - Examining the first token in the list[/caption]

The reason for the <span style="font-family: monospace">+8+8</span> on the end is because that's the offset of the payload. It's just after the <span style="font-family: monospace">Flink</span> and <span style="font-family: monospace">Blink</span> as shown in Figure 19. You want to skip over them.

We can see that this token is associated to <span style="font-family: monospace">SessionId 0x136/0n310</span>. (Remember I had 380 leaked sessions in this dump.) If you examine the <span style="font-family: monospace">UserAndGroups</span> member by clicking on its DML (click the link,) you can then use <span style="font-family: monospace">!sid</span> to see the SID of the user this token represents:

[caption id="attachment_16845" align="alignnone" width="962"]<img width="962" height="148" class="size-full wp-image-16845" alt="Figure 22 - Using !sid to see the security identifier in the token" src="https://msdnshared.blob.core.windows.net/media/2017/04/bangsid.png" /> Figure 22 - Using !sid to see the security identifier in the token[/caption]

The token also has a <span style="font-family: monospace">DiagnosticInfo</span> structure, which is super-interesting, and is the coolest thing that we unlocked when we set the <span style="font-family: monospace">SeTokenLeakDiag</span> registry setting on the machine earlier. Let's look at it:

[caption id="attachment_16846" align="alignnone" width="1096"]<img width="1096" height="189" class="size-full wp-image-16846" alt="Figure 23 - Examining the DiagnosticInfo structure of the first token" src="https://msdnshared.blob.core.windows.net/media/2017/04/DiagnosticInfo.png" /> Figure 23 - Examining the DiagnosticInfo structure of the first token[/caption]

We now have the process ID and the thread ID that was responsible for creating this token! We could examine the <span style="font-family: monospace">ImageFileName</span>, or we could use the <span style="font-family: monospace">ProcessCid</span> to see who it is:

[caption id="attachment_16855" align="alignnone" width="635"]<img width="635" height="185" class="size-full wp-image-16855" alt="Figure 24 - Using !mex.tasklist to find a process by its PID" src="https://msdnshared.blob.core.windows.net/media/2017/04/mexpid.png" /> Figure 24 - Using !mex.tasklist to find a process by its PID[/caption]

Oh... <em>Whoops</em>. Looks like this particular token leak is lsass's fault. You're just going to have to let the <em>*ahem*</em> application vendor take care of that one.

Let's move on to a different token leak. We're moving on to a different memory dump file as well, so the memory addresses are going to be different from here on out.

I created a special token-leaking application specifically for this article. It looks like this:

[caption id="attachment_16856" align="alignnone" width="618"]<img width="618" height="370" class="size-full wp-image-16856" alt="Figure 25 - RyansTokenGrabber.exe" src="https://msdnshared.blob.core.windows.net/media/2017/04/tokengrabber.png" /> Figure 25 - RyansTokenGrabber.exe[/caption]

It monitors the system for users logging on, and as soon as they do, it duplicates their token via the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa446616(v=vs.85).aspx">DuplicateToken</a> API call. I purposely never release those tokens, so if I collect a memory dump of the machine while this is running, then evidence of the leak should be visible in the dump, using the same steps as before.

Using the same debugging techniques I just demonstrated, I verified that I have leaked logon sessions in this memory dump as well, and each leaked session has an access token reference that looks like this:

[caption id="attachment_16865" align="alignnone" width="628"]<img width="628" height="77" class="size-full wp-image-16865" alt="Figure 26 - A _TOKEN structure shown with its attached DiagnosticInfo" src="https://msdnshared.blob.core.windows.net/media/2017/04/DiagnosticInfo2.png" /> Figure 26 - A _TOKEN structure shown with its attached DiagnosticInfo[/caption]

And then by looking at the token's <span style="font-family: monospace">DiagnosticInfo</span>, we find that the guilty party responsible for leaking this token is indeed RyansTokenGrabber.exe:

[caption id="attachment_16875" align="alignnone" width="745"]<img width="745" height="138" class="size-full wp-image-16875" alt="Figure 27 - The process responsible for leaking this token" src="https://msdnshared.blob.core.windows.net/media/2017/04/tokengrabberleak.png" /> Figure 27 - The process responsible for leaking this token[/caption]

By this point you know who to blame, and now you can go find the author of RyansTokenGrabber.exe, and show them the stone-cold evidence that you've collected about how their application is leaking access tokens, leading to logon session leaks, causing you to have to reboot your server every few days, which is a ridiculous and inconvenient thing to have to do, and you shouldn't stand for it!

We're almost done. but I have one last trick to show you.

If you examine the <span style="font-family: monospace">StackTrace</span> member of the token's <span style="font-family: monospace">DiagnosticInfo</span>, you'll see something like this:

[caption id="attachment_16885" align="alignnone" width="1009"]<img width="1009" height="450" class="size-full wp-image-16885" alt="Figure 28 - DiagnosticInfo.CreateTrace" src="https://msdnshared.blob.core.windows.net/media/2017/04/CreateTrace1.png" /> Figure 28 - DiagnosticInfo.CreateTrace[/caption]

This is a stack trace. It's a snapshot of all the function calls that led up to this token's creation. These stack traces grew upwards, so the function at the top of the stack was called last. But the function addresses are not resolving. We must do a little more work to figure out the names of the functions.

First, clean up the output of the stack trace:

[caption id="attachment_16895" align="alignnone" width="738"]<img width="738" height="453" class="size-full wp-image-16895" alt="Figure 29 - Using !grep and !cut to clean up the output" src="https://msdnshared.blob.core.windows.net/media/2017/04/grepcleanstacktrace.png" /> Figure 29 - Using !grep and !cut to clean up the output[/caption]

Now, using all the snazzy new Mex magic you've learned, see if you can unassemble (that's the <span style="font-family: monospace">u</span> command) each address to see if resolves to a function name:

[caption id="attachment_16896" align="alignnone" width="917"]<img width="917" height="252" class="size-full wp-image-16896" alt="Figure 30 - Unassemble instructions at each address in the stack trace" src="https://msdnshared.blob.core.windows.net/media/2017/04/unassemblefuncs.png" /> Figure 30 - Unassemble instructions at each address in the stack trace[/caption]

The output continues beyond what I've shown above, but you get the idea.

The function on top of the trace will almost always be <span style="font-family: monospace">SepDuplicateToken</span>, but could also be <span style="font-family: monospace">SepCreateToken</span> or <span style="font-family: monospace">SepFilterToken</span>, and whether one creation method was used versus another could be a big hint as to where in the program's code to start searching for the token leak. You will find that the usefulness of these stacks will vary wildly from one scenario to the next, as things like inlined functions, lack of symbols, unloaded modules, and managed code all influence the integrity of the stack. However, you (or the developer of the application you're using) can use this information to figure out where the token is being created in this program, and fix the leak.

Alright, that's it. If you're still reading this, then... thank you for hanging in there. I know this wasn't exactly a light read.

And lastly, allow me to reiterate that this is not just a contrived, unrealistic scenario; There's a lot of software out there on the market that does this kind of thing. And if you happen to write such software, then I really hope you read this blog post. It may help you improve the quality of your software in the future. Windows needs application developers to be "good citizens" and avoid writing software with the ability to destabilize the operating system. Hopefully this blog post helps someone out there do just that.

Until next time,
Ryan "Too Many Tokens" Ries]]></content:encoded>
    </item>
    <item>
      <title>Troubleshooting failed password changes after installing MS16-101</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/troubleshooting-failed-password-changes-after-installing-ms16-101</link>
      <pubDate>Thu, 13 Oct 2016 19:22:50 GMT</pubDate>
      <dc:creator><![CDATA[Linda Taylor (Microsoft GBS UK)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=16625</guid>
      <description><![CDATA[Hi!

Linda Taylor here, Senior Escalation Engineer in the Directory Services space.

I have...]]></description>
      <content:encoded><![CDATA[Hi!

Linda Taylor here, Senior Escalation Engineer in the Directory Services space.

I have spent the last month working with customers worldwide who experienced password change failures after installing the updates under Ms16-101 security bulletin KB’s (listed below), as well as working with the product group in getting those addressed and documented in the public KB articles under the <b>known issues</b> section. It has been busy!

In this post I will aim to provide you with a quick “cheat sheet” of known issues and needed actions as well as ideas and troubleshooting techniques to get there.
<h6><span style="font-weight: bold">Let’s start by understanding the changes. </span></h6>
The following 6 articles describe the changes in MS16-101 as well as a list of <b>Known issues.</b> If you have not yet applied MS16-101 I would strongly recommend reading these and understanding how they may affect you.

<a href="http://support.microsoft.com/kb/3176492/en-US">3176492</a> Cumulative update for Windows 10: August 9, 2016
<a href="http://support.microsoft.com/kb/3176493/en-US">3176493</a> Cumulative update for Windows 10 Version 1511: August 9, 2016
<a href="http://support.microsoft.com/kb/3176495/en-US">3176495</a> Cumulative update for Windows 10 Version 1607: August 9, 2016
<a href="http://support.microsoft.com/kb/3178465/en-US">3178465</a> MS16-101: Security update for Windows authentication methods: August 9, 2016
<a href="http://support.microsoft.com/kb/3167679/en-US">3167679</a> MS16-101: Description of the security update for Windows authentication methods: August 9, 2016
<a href="http://support.microsoft.com/kb/3177108/en-US">3177108</a> MS16-101: Description of the security update for Windows authentication methods: August 9, 2016

<b><strong><strong><strong><strong><strong>The good news</strong></strong></strong></strong></strong> is</b> that this month’s updates address some of the known issues with MS16-101.

<b>The bad news</b> <strong>is</strong> that not all the issues are caused by some code defect in MS16-101 and in some cases the right solution is to make your environment more secure by ensuring that the password change can happen over Kerberos and does not need to fall back to NTLM. That may include opening TCP ports used by Kerberos, fixing other Kerberos problems like missing SPN’s or changing your application code to pass in a valid domain name.

Let’s start with the basics…
<h5><span style="color: #4f81bd"><span style="font-weight: bold">Symptoms:

</span></span></h5>
After applying MS16-101 fixes listed above, password changes may fail with the error code

<span style="color: #ff0000">“The system detected a possible attempt to compromise security. Please make sure that you can contact the server that authenticated you.”
</span>Or
<span style="color: #ff0000">“The system cannot contact a domain controller to service the authentication request. Please try again later.”</span>

This text maps to the error codes below:
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top"><strong>Hexadecimal</strong></td>
<td valign="top"><strong>Decimal</strong></td>
<td valign="top"><strong>Symbolic</strong></td>
<td valign="top"><b><strong><strong><strong>Friendly</strong></strong></strong></b></td>
</tr>
<tr>
<td valign="top">0xc0000388</td>
<td valign="top">1073740920</td>
<td valign="top">STATUS_DOWNGRADE_DETECTED</td>
<td valign="top">The system detected a possible attempt to compromise security. Please make sure that you can contact the server that authenticated you.</td>
</tr>
<tr>
<td valign="top">0x80074f1</td>
<td valign="top">1265</td>
<td valign="top">ERROR_DOWNGRADE_DETECTED</td>
<td valign="top">The system detected a possible attempt to compromise security. Please make sure that you can contact the server that authenticated you.</td>
</tr>
</tbody>
</table>
<table width="400" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td width="400" valign="top"></td>
</tr>
</tbody>
</table>
<b><span style="color: #4f81bd"><strong><strong>Question: What does MS16-101 do and why would password changes fail after installing it?</strong></strong></span> </b>

<b><span style="color: #4f81bd"><strong>Answer:</strong></span></b> As documented in the listed KB articles, the security updates that are provided in MS16-101 disable the ability of the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa378748(v=vs.85).aspx">Microsoft Negotiate SSP</a> to fall back to NTLM for password change operations in the case where Kerberos fails with the <span style="color: #ff0000">STATUS_NO_LOGON_SERVERS</span> (<span style="color: #ff0000">0xc000005e</span>) error code.
In this situation, the password change will now fail (post MS16-101) with the above mentioned error codes (<span style="color: #ff0000">ERROR_DOWNGRADE_DETECTED / STATUS_DOWNGRADE_DETECTED</span>).
<strong><strong>Important:</strong></strong> Password RESET is not affected by MS16-101 at all in any scenario. Only password change using the Negotiate package is affected.

So, now you understand the change, let’s look at the known issues and learn how to best identify and resolve those.
<h5><span style="color: #4f81bd;font-weight: bold">Summary and Cheat Sheet

</span></h5>
To make it easier to follow I have matched the ordering of known issues in this post with the public KB articles above.

First, when troubleshooting a failed password change post MS16-101 you will need to understand <i>HOW</i> and <i>WHERE </i>the password change is happening and if it is for a domain account or a local account. Here is a cheat sheet.
<h6><span style="font-weight: bold">Summary of SCENARIO’s and a quick reference table of actions needed.</span></h6>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top">
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top"><strong>Scenario / Known issue # </strong></td>
<td valign="top"><strong>Description</strong></td>
<td valign="top"><strong>Action Needed</strong></td>
</tr>
<tr>
<td valign="top">1.</td>
<td valign="top">Domain password change fails via CTRL+ALT+DEL and shows an error like this:

<a href="https://msdnshared.blob.core.windows.net/media/2016/10/clip_image00113.png"><img width="533" height="178" title="clip_image001" alt="clip_image001" src="https://msdnshared.blob.core.windows.net/media/2016/10/clip_image001_thumb7.png" border="0" /></a>

Text: “System detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you. “</td>
<td valign="top">Troubleshoot using this guide and fix Kerberos.</td>
</tr>
<tr>
<td valign="top">2.</td>
<td valign="top">Domain password change fails via application code with an INCORRECT/UNEXPECTED Error code when a password which does not meet password complexity is entered.

For example, before installing MS16-101, such password change may have returned a status like STATUS_PASSWORD_RESTRICTION and it now returns STATUS_DOWNGRADE_DETECTED (after installing Ms16-101) causing your application to behave in an expected way or even crash.

Note: In these cases password change works ok when correct new password is entered that complies with the password policy.</td>
<td valign="top">Install October fixes in the table below.</td>
</tr>
<tr>
<td valign="top">3.</td>
<td valign="top">Local user account password change fails via CTRL+ALT+DEL or application code.</td>
<td valign="top">Install October fixes in the table below.</td>
</tr>
<tr>
<td valign="top">4.</td>
<td valign="top">Passwords for disabled and locked out user accounts cannot be changed using Negotiate method.</td>
<td valign="top">None. By design.</td>
</tr>
<tr>
<td valign="top">5.</td>
<td valign="top">Domain password change fails via application code when a good password is entered.

This is the case where if you pass a servername to NetUserChangePassword, the password change will fail post MS16-101. This is because it would have previously worked and relied on NTLM. NTLM is insecure and Kerberos is always preferred. Therefore passing a domain name here is the way forward.

One thing to note for this one is that most of the ADSI and C#/.NET changePassword API’s end up calling NetUserChangePassword under the hood. Therefore, also passing invalid domain names to these API’s will fail. I have provided a detailed walkthrough example in this post with log snippets.</td>
<td valign="top">Troubleshoot using this guide and fix code to use Kerberos.</td>
</tr>
<tr>
<td valign="top">6.</td>
<td valign="top">After you install MS 16-101 update, you may encounter 0xC0000022 NTLM authentication errors.</td>
<td valign="top">To resolve this issue, see <a href="https://support.microsoft.com/kb/3195799">KB3195799</a> NTLM authentication fails with 0xC0000022 error for Windows Server 2012, Windows 8.1, and Windows Server 2012 R2 after update is applied.</td>
</tr>
<tr>
<td valign="top">7.</td>
<td valign="top">After you install the security updates that are described in MS16-101, remote, programmatic changes of a local user account password remotely, and password changes across untrusted forest fail with the STATUS_DOWNGRADE_DETECTED error as documented in this post.

This happens because the operation relies on NTLM fall-back since there is no Kerberos without a trust.  NTLM fall-back is forbidden by MS16-101.</td>
<td valign="top">For this scenario you will need to install October fixes in the table below and set the registry key <b><span style="color: #ff0000">NegoAllowNtlmPwdChangeFallback </span></b>documented in KB’s below which allows the NTLM fall back to happen again and unblocks this scenario.

<a href="http://support.microsoft.com/kb/3178465">http://support.microsoft.com/kb/3178465</a>
<a href="http://support.microsoft.com/kb/3167679">http://support.microsoft.com/kb/3167679</a>
<a href="http://support.microsoft.com/kb/3177108">http://support.microsoft.com/kb/3177108</a>
<a href="http://support.microsoft.com/kb/3176492">http://support.microsoft.com/kb/3176492</a>
<a href="http://support.microsoft.com/kb/3176495">http://support.microsoft.com/kb/3176495</a>
<a href="http://support.microsoft.com/kb/3176493">http://support.microsoft.com/kb/3176493</a>

<strong>Note</strong>: you may also consider using this registry key in an emergency for Known Issue#5 when it takes time to update the application code. However please read the above articles carefully and only consider this as a short term solution for scenario 5.</td>
</tr>
</tbody>
</table>
<i> </i></td>
</tr>
<tr>
<td valign="top"></td>
</tr>
</tbody>
</table>
<h6><span style="font-weight: bold">Table of Fixes for known issues above release 2016.10.11, taken from </span><a href="https://technet.microsoft.com/en-us/library/security/ms16-101.aspx"><span style="font-weight: bold">MS16-101 Security Bulletin</span></a><span style="font-weight: bold">:

</span></h6>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">OS </span></b></td>
<td width="456" valign="top"><b>Fix needed</b></td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080"><strong>Vista / W2K8</strong></span> </b></td>
<td width="456" valign="top">Re-install <a href="https://support.microsoft.com/en-us/kb/3167679">3167679</a>, re-released 2016.10.11</td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">Win7 / W2K8 R2</span></b></td>
<td width="456" valign="top">Install <a href="https://support.microsoft.com/en-us/kb/3192391">3192391</a> (security only)
or
Install <a href="https://support.microsoft.com/en-us/kb/3185330">3185330</a> (monthly rollup that includes security fixes)</td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">WS12 </span></b></td>
<td width="456" valign="top"><a href="https://support.microsoft.com/en-us/kb/3192393">3192393</a> (security only)
or
<a href="https://support.microsoft.com/en-us/kb/3185332">3185332</a> (monthly rollup that includes security fixes)</td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">Win8.1 / WS12 R2</span></b></td>
<td width="456" valign="top"><a href="https://support.microsoft.com/en-us/kb/3192392">3192392</a> (security only)
OR
<a href="https://support.microsoft.com/en-us/kb/3185331">3185331</a> ((monthly rollup that includes security fixes)</td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">Windows 10</span></b></td>
<td width="456" valign="top"><b>For 1511:</b> <a href="https://support.microsoft.com/en-us/kb/3192241">3192441</a> Cumulative update for Windows 10 Version 1511: October 11, 2016
<b>For 1607:</b> <a href="https://support.microsoft.com/en-us/kb/3194798">3194798</a> Cumulative update for Windows 10 Version 1607 and Windows Server 2016: October 11, 2016</td>
</tr>
</tbody>
</table>
<h5><span style="color: #4f81bd"><span style="font-weight: bold">Troubleshooting</span></span></h5>
As I mentioned, this post is intended to support the documentation of the <b>known issues</b> in the Ms16-101 KB articles and provide help and guidance for troubleshooting. It should help you identify which known issue you are experiencing as well as provide resolution suggestions for each case.

I have also included a troubleshooting walkthrough of some of the more complex example cases. We will start with the problem definition, and then look at the available logs and tools to identify a suitable resolution. The idea is to teach “how to fish” because there can be many different scenario’s and hopefully you can apply these techniques and use the log files documented here to help resolve the issues when needed.

Once you know the scenario that you are using for the password change the next step is usually to collect some data on the server or client where the password change is occuring. For example if you have a web server running a password change application and doing password changes on behalf of users, you will need to collect the logs there. If in doubt collect the logs from all involved machines and then look for the right one doing the password change using the snippets in the examples. Here are the helpful logs.

<b><strong>DATA COLLECTION</strong></b>

The same logs will help in all the scenario’s.

<strong><strong>LOGS</strong></strong>

<strong>1<strong>. SPENGO debug log/ LSASS.log</strong></strong><b> </b>

To enable this log run the following commands from an elevated admin CMD prompt to set the below registry keys:
<table width="400" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td width="400" valign="top"><strong>reg add HKLM\SYSTEM\CurrentControlSet\Control\LSA /v SPMInfoLevel /t REG_DWORD /d 0xC03E3F /f
reg add HKLM\SYSTEM\CurrentControlSet\Control\LSA /v LogToFile /t REG_DWORD /d 1 /f
reg add HKLM\SYSTEM\CurrentControlSet\Control\LSA /v NegEventMask /t REG_DWORD /d 0xF /f</strong></td>
</tr>
</tbody>
</table>
&nbsp;
<ul>
 	<li>This will log Negotiate debug output to the %windir%\system32<b>\lsass.log.</b></li>
 	<li>There is no need for reboot. The log is effective immediately.</li>
 	<li>Lsass.log is a text file that is easy to read with a text editor such as Wordpad.</li>
</ul>
<strong><strong>2. Netlogon.log:</strong></strong>

This log has been around for many years and is useful for troubleshooting DC LOCATOR traffic. It can be used together with a network trace to understand why the STATUS_NO_LOGON_SERVERS is being returned for the Kerberos password change attempt.

· To enable Netlogon debug logging run the following command from an elevated CMD prompt:

nltest /dbflag:0x26FFFFFF

· The resulting log is found in %windir%\debug\<b>netlogon.log</b> &amp; <b>netlogon.bak</b>

· There is no need for reboot. The log is effective immediately. See also <a href="http://support.microsoft.com/kb/109626/EN-US">109626</a> Enabling debug logging for the Net Logon service

· The <b>Netlogon.log</b> (and Netlogon.bak) is a text file.

Open the log with any text editor (I like good old Notepad.exe)

3. Collect a <b><strong>Network trace</strong></b> during the password change issue using the tool of your choice.
<h5><span style="color: #4f81bd;font-weight: bold">Scenario’s, Explanations and Walkthrough’s: </span></h5>
When reading this you should keep in mind that you may be seeing more than one scenario. The best thing to do is to start with one, fix that and see if there are any other problems left.
<h6><span style="color: #000080;font-weight: bold">1. Domain password change fails via CTRL+ALT+DEL</span></h6>
This is most likely a Kerberos DC locator failure of some kind where the password changes were relying on NTLM before installing MS16-101 and are now failing. This is the simplest and easiest case to resolve using basic Kerberos troubleshooting methods.

<b><strong><strong>Solution:</strong></strong> </b>Fix Kerberos. <b></b>

<b>Some tips from cases which we saw: </b>

1. Use the Network trace to identify if the necessary communication ports are open. This was quite a common issue. So start by checking this.

In order for Kerberos password changes to work communication on TCP port 464 needs to be open between the client doing the
password change and the domain controller.

<span>Note on RODC: Read-only domain controllers (RODCs) can service password changes if the user is allowed by the RODCs password replication policy. Users who are not allowed by the RODC password policy require network connectivity to a read/write domain controller (RWDC) in the user account domain to be able to change the password.</span>

<strong>           To check whether TCP port 464 is open, follow these steps (also documented in KB</strong><a href="https://support.microsoft.com/en-us/kb/3167679"><strong>3167679</strong></a><strong>):</strong>

a. Create an equivalent display filter for your network monitor parser. For example:

<strong>                            ipv4.address== &lt;ip address of client&gt; &amp;&amp; tcp.port==464</strong>

b. In the results, look for the <span style="color: #ff0000">"TCP:[SynReTransmit"</span> frame.

If you find these, then investigate firewall and open ports. It is often useful to take a simultaneous trace from the client and the domain controller and check if the packets are arriving at the other end.

2. Make sure that the target Kerberos names are valid.
<ul>
 	<li>IP addresses are not valid Kerberos names</li>
 	<li>Kerberos supports short names and fully qualified domain names. Like CONTOSO or Contoso.com</li>
</ul>
<strong>3. Make sure that service principal names (SPNs) are registered correctly.</strong>

For more information on troubleshooting Kerberos see <a href="https://blogs.technet.microsoft.com/askds/2008/05/14/troubleshooting-kerberos-authentication-problems-name-resolution-issues/ or">https://blogs.technet.microsoft.com/askds/2008/05/14/troubleshooting-kerberos-authentication-problems-name-resolution-issues/ or</a> <a href="https://technet.microsoft.com/en-us/library/cc728430(v=ws.10).aspx">https://technet.microsoft.com/en-us/library/cc728430(v=ws.10).aspx</a>
<h6><span style="font-weight: bold"><span style="color: #000080">2. Domain password change fails via application code with an INCORRECT/UNEXPECTED Error code when a password which does not meet password complexity is entered.</span>

</span></h6>
For example, before installing MS16-101, such password change may have returned a status like STATUS_PASSWORD_RESTRICTION. After installing Ms16-101 it returns STATUS_DOWNGRADE_DETECTED causing your application to behave in an expected way or even crash.

Note: In this scenario, password change succeeds when correct new password is entered that complies with the password policy.

<b></b>

<b><strong>Cause:</strong> </b>

This issue is caused by a code defect in ADSI whereby the status returned from Kerberos was not returned to the user by ADSI correctly.
Here is a more detailed explanation of this one for the geek in you:

<b>Before MS16-101 behavior: </b>

1. An application calls ChangePassword method from using the ADSI LDAP provider.
Setting and changing passwords with the ADSI LDAP Provider is documented <a href="https://msdn.microsoft.com/en-us/library/aa746487(v=vs.85).aspx">here.</a>
Under the hood this calls Negotiate/Kerberos to change the password using a valid realm name.
Kerberos returns STATUS_PASSWORD_RESTRICTION or Other failure code.

2. A 2nd changepassword call is made via NetUserChangePassword API with an intentional realmname as the &lt;dcname&gt; which uses
Negotiate and will retry Kerberos. Kerberos fails with STATUS_NO_LOGON_SERVERS because a DC name is not a valid realm name.

3.Negotiate then retries over NTLM which succeeds or returns the same previous failure status.

The password change fails if a bad password was entered and the NTLM error code is returned back to the application. If a valid password was entered, everything works because the 1st change password call passes in a good name and if Kerberos works, the password change operation succeeds and you never enter into step 3.

<b><strong>Post MS16-101 behavior /why it fails with MS16-101 installed:</strong> </b>

1. An application calls ChangePassword method from using the ADSI LDAP provider. This calls Negotiate for the password change with
a valid realm name.
Kerberos returns STATUS_PASSWORD_RESTRICTION or Other failure code.

2. A 2nd ChangePassword call is made via NetUserChangePassword with a &lt;dcname&gt; as realm name which fails over Kerberos with
STATUS_NO_LOGON_SERVERS which triggers NTLM fallback.

3. Because NTLM fallback is blocked on MS16-101, Error STATUS_DOWNGRADE_DETECTED is returned to the calling app.

<b><strong>Solution:</strong> </b>Easy. Install the October update which will fix this issue. The fix lies in <b><strong>adsmsext.dll</strong></b> included in the October updates.

Again, here are the updates you need to install, Taken from <a href="https://technet.microsoft.com/en-us/library/security/ms16-101.aspx">MS16-101 Security Bulletin</a>:
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="156" valign="top"><strong><span style="color: #000080">OS </span></strong></td>
<td width="456" valign="top"><b><strong>Fix needed</strong></b></td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">Vista / W2K8</span> </b></td>
<td width="456" valign="top">Re-install <a href="https://support.microsoft.com/en-us/kb/3167679">3167679</a>, re-released 2016.10.11</td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">Win7 / W2K8 R2</span></b></td>
<td width="456" valign="top">Install <a href="https://support.microsoft.com/en-us/kb/3192391">3192391</a> (security only)
or
Install <a href="https://support.microsoft.com/en-us/kb/3185330">3185330</a> (monthly rollup that includes security fixes)</td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">WS12</span> </b></td>
<td width="456" valign="top"><a href="https://support.microsoft.com/en-us/kb/3192393">3192393</a> (security only)
or
<a href="https://support.microsoft.com/en-us/kb/3185332">3185332</a> (monthly rollup that includes security fixes)</td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">Win8.1 / WS12 R2</span></b></td>
<td width="456" valign="top"><a href="https://support.microsoft.com/en-us/kb/3192392">3192392</a> (security only)
OR
<a href="https://support.microsoft.com/en-us/kb/3185331">3185331</a> ((monthly rollup that includes security fixes)</td>
</tr>
<tr>
<td width="156" valign="top"><b><span style="color: #000080">Windows 10</span></b></td>
<td width="456" valign="top"><b>For 1511:</b> <a href="https://support.microsoft.com/en-us/kb/3192241">3192441</a> Cumulative update for Windows 10 Version 1511: October 11, 2016
<b>For 1607:</b> <a href="https://support.microsoft.com/en-us/kb/3194798">3194798</a> Cumulative update for Windows 10 Version 1607 and Windows Server 2016: October 11, 2016</td>
</tr>
</tbody>
</table>
<h6><span style="color: #000080;font-weight: bold">3.Local user account password change fails via CTRL+ALT+DEL or application code.

</span></h6>
Installing October updates above should also resolve this.

MS16-101 had a defect where Negotiate did not correctly determine that the password change was local and would try to find a DC using the local machine as the domain name.

This failed and NTLM fallback was no longer allowed post MS16-101. Therefore, the password changes failed with STATUS_DOWNGRADE_DETECTED.

<b><strong>Example:</strong> </b>

<b></b>

One such scenario which I saw where password changes of local user accounts via ctrl+alt+delete failed with the message "The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you." Was when you have the following group policy set and you try to change a password of a local account:
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="85" valign="top">Policy</td>
<td width="538" valign="top">Computer Configuration \ Administrative Templates \ System \ Logon\“Assign a default domain for logon”</td>
</tr>
<tr>
<td width="85" valign="top">Path</td>
<td width="538" valign="top">HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\DefaultLogonDomain</td>
</tr>
<tr>
<td width="85" valign="top">Setting</td>
<td width="538" valign="top">DefaultLogonDomain</td>
</tr>
<tr>
<td width="85" valign="top">Data Type</td>
<td width="538" valign="top">REG_SZ</td>
</tr>
<tr>
<td width="85" valign="top">Value</td>
<td width="538" valign="top">"."    (less quotes). The period or "dot" designates the local machine name</td>
</tr>
<tr>
<td width="85" valign="top">Notes</td>
<td width="538" valign="top"></td>
</tr>
</tbody>
</table>
<b><strong>Cause:</strong></b> In this case, post MS16-101 Negotiate incorrectly determined that the account is not local and tried to discover a DC using \\&lt;machinename&gt; as the domain and failed. This caused the password change to fail with the STATUS_DOWNGRADE_DETECTED error.

<b></b>

<b><strong>Solution:</strong> </b>Install October fixes listed in the table at the top of this post.<b></b>
<h6><span style="color: #000080;font-weight: bold">4.Passwords for disabled and locked out user accounts cannot be changed using Negotiate method.

</span></h6>
MS16-101 purposely disabled changing the password of locked-out or disabled user account passwords via Negotiate by design.

<span style="color: #ff0000">Important: Password Reset is not affected by MS16-101 at all in any scenario. Only password change. Therefore, any application which is doing a password Reset will be <u>unaffected</u> by Ms16-101.</span>

Another important thing to note is that MS16-101 only affects applications using Negotiate. Therefore, it is possible to change locked-out and disabled account password using other method’s such as LDAPs.

For example, the PowerShell cmdlet <b><i>Set-ADAccountPassword </i></b>will continue to work for locked out and disabled account password changes as it does not use Negotiate.<i> </i>
<h6><span style="color: #000080;font-weight: bold">5. Troubleshooting Domain password change failure via application code when a good password is entered.

</span></h6>
This is one of the most difficult scenarios to identify and troubleshoot. And therefore I have provided a more detailed example here including sample code, the cause and solution.

<b>In summary,</b> the solution for these cases is almost always to correct the application code which maybe passing in an invalid domain name such that Kerberos fails with STATUS_NO_LOGON_SERVERS.

<b>Scenario:</b>

An application is using <b>system.directoryservices.accountmanagement</b> namespace to change a users password.
<a href="https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement(v=vs.110).aspx">https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement(v=vs.110).aspx</a>

After installing Ms16-101 password changes fail with STATUS_DOWNGRADE_DETECTED. Example .NET failing code snippet using PowerShell which worked before MS16-101:

&lt;snip&gt;

<span style="color: #c0504d">Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$ctoptions = [System.DirectoryServices.AccountManagement.ContextOptions]::SimpleBind -bor [System.DirectoryServices.AccountManagement.ContextOptions]::ServerBind
$pc = New-Object System.DirectoryServices.AccountManagement.PrincipalContext($ct, "contoso.com","OU=Accounts,DC=Contoso,DC=Com", ,$ctoptions)
$idType = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
$up = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($pc,$idType, "TestUser")
$up.ChangePassword("oldPassword!123", “newPassword!123”)</span>

&lt;snip&gt;

<strong><strong>Data Analysis</strong>
</strong><b></b>

There are 2 possibilities here:
<strong>(a)</strong> The application code is passing an incorrect domain name parameter causing Kerberos password change to fail to locate a DC.
<strong>(b)</strong>  Application code is good and Kerberos password change fails for other reason like blocked port or DNS issue or missing SPN.

Let’s start with <strong>(a) </strong>The application code is passing an incorrect domain name/parameter causing Kerberos password change to fail to locate a DC.
<h6><span style="color: #4f81bd"><span style="font-weight: bold">(a)</span></span><span style="color: #4f81bd"><span style="font-weight: bold"> Data Analysis Walkthrough Example based on a real case:</span></span></h6>
<strong>1. Start with Lsass.log (SPNEGO trace)</strong>

If you are troubleshooting a password change failure after MS16-101 look for the following text in <b>Lsass.log</b> to indicate that Kerberos failed and NTLM fallback was forbidden by Ms16-101:

<b>Failing Example:</b>

[ 9/13 10:23:36] 492.2448&gt; SPM-WAPI: [11b0.1014] Dispatching API (Message 0)
[ 9/13 10:23:36] 492.2448&gt; SPM-Trace: [11b0] LpcDispatch: dispatching ChangeAccountPassword (1a)
[ 9/13 10:23:36] 492.2448&gt; SPM-Trace: [11b0] LpcChangeAccountPassword()
[ 9/13 10:23:36] 492.2448&gt; SPM-Helpers: [11b0] LsapCopyFromClient(0000005EAB78C9D8, 000000DA664CE5E0, 16) = 0
[ 9/13 10:23:36] 492.2448&gt; SPM-Neg: NegChangeAccountPassword:
[ 9/13 10:23:36] 492.2448&gt; SPM-Neg: NegChangeAccountPassword, attempting: NegoExtender
[ 9/13 10:23:36] 492.2448&gt; SPM-Neg: NegChangeAccountPassword, attempting: Kerberos
[ 9/13 10:23:36] 492.2448&gt; SPM-Warning: Failed to change password for account Test: <span style="color: #ff0000">0xc000005e</span>
[ 9/13 10:23:36] 492.2448&gt; SPM-Neg: NegChangeAccountPassword, <span style="color: #ff0000">attempting: NTLM</span>
[ 9/13 10:23:36] 492.2448&gt; SPM-Neg: NegChangeAccountPassword, <span style="color: #ff0000">NTLM failed: not allowed to change domain passwords</span>
[ 9/13 10:23:36] 492.2448&gt; SPM-Neg: NegChangeAccountPassword, <span style="color: #ff0000">returning: 0xc0000388</span>
<ul>
 	<li>0xc000005E is STATUS_NO_LOGON_SERVERS
0xc0000388 is STATUS_DOWNGRADE_DETECTED</li>
</ul>
If you see this, it means Kerberos failed to locate a Domain Controller in the domain and fallback to NTLM is not allowed by Ms16-101. Next you should look at the <strong>Netlogon.log</strong> and the <strong>Network trace</strong> to understand why.

<strong>2. Network trace</strong>

Look at the network trace and filter the traffic based on the client IP, DNS and any authentication related traffic.
You may see the client is requesting a Kerberos ticket using an invalid SPN like:

<b></b>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top"><strong>Source </strong></td>
<td valign="top"><strong>Destination</strong></td>
<td valign="top"><strong>Description</strong></td>
</tr>
<tr>
<td valign="top">Client</td>
<td valign="top">DC1</td>
<td valign="top">KerberosV5:TGS Request Realm: CONTOSO.COM <span style="color: #ff0000">Sname: ldap/contoso.com</span>             {TCP:45, IPv4:7}</td>
</tr>
<tr>
<td valign="top">DC1</td>
<td valign="top">Client</td>
<td valign="top">KerberosV5:KRB_ERROR  - <span style="color: #ff0000">KDC_ERR_S_PRINCIPAL_UNKNOWN</span> (7)  {TCP:45, IPv4:7}</td>
</tr>
</tbody>
</table>
<b></b>

So here the client tried to get a ticket for this ldap\Contoso.com SPN and failed with KDC_ERR_S_PRINCIPAL_UNKNOWN because this SPN is not registered anywhere.
<ul>
 	<li>This is expected. A valid LDAP SPN is example like ldap\DC1.contoso.com</li>
</ul>
Next let’s check the Netlogon.log

<strong>3. Netlogon.log:</strong>

Open the log with any text editor (I like good old Notepad.exe) and check the following:
<ul>
 	<li><b><strong>Is a valid domain name being passed to DC locator?</strong> </b></li>
</ul>
Invalid names such as <a href="//servername.contoso.com">\\servername.contoso.com</a> or IP address <a href="//x.y.x.w">\\x.y.x.w</a> will cause dclocator to fail and thus Kerberos password change to return STATUS_NO_LOGON_SERVERS. Once that happens NTLM fall back is not allowed and you get a failed password change.

If you find this issue examine the application code and make necessary changes to <b>ensure correct domain name format is being passed to the ChangePassword API</b> that is being used.

<b>Example of failure in Netlogon.log:</b>

[MISC] [PID] DsGetDcName function called: client PID=1234, Dom:\\contoso.com Acct:(null) Flags: IP KDC
[MISC] [PID] DsGetDcName function returns <span style="color: #ff0000">1212 </span>(client PID=1234): Dom:<span style="color: #ff0000">\\contoso.com</span> Acct:(null) Flags: IP KDC

\\contoso.com is not a valid domain name. (contoso.com is a valid domain name)

This Error translates to:
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top">0x4bc</td>
<td valign="top">1212</td>
<td valign="top">ERROR_INVALID_DOMAINNAME</td>
<td valign="top">The format of the specified domain name is invalid.</td>
<td valign="top">winerror.h</td>
</tr>
</tbody>
</table>
<h6><span style="font-weight: bold"><span style="color: #4f81bd">So what happened here?</span> </span></h6>
The application code passed an invalid TargetName to kerberos. It used the domain name <b>as a server name</b> and so we see the SPN of LDAP\contoso.com.

The client tried to get a ticket for this SPN and failed with KDC_ERR_S_PRINCIPAL_UNKNOWN because this SPN is not registered anywhere. As Noted: this is expected. A valid LDAP SPN is example like ldap\<b>DC1</b>.contoso.com.

The application code then tried the password change again and passed in <a href="//contoso.com/">\\contoso.com</a> as a domain name for the password change. Anything beginning with \\ as domain name is not valid. IP address is not valid. So DCLOCATOR will fail to locate a DC when given this domain name. We can see this in the Netlogon.log and the Network trace.

<b><strong>Conclusion and Solution</strong> </b><b></b>

If the domain name is invalid here, examine the code snippet which is doing the password change to understand why the wrong name is passed in.

<b>The fix in these cases will be to change the code to ensure a valid domain name is passed to Kerberos to allow the password change to successfully happen over Kerberos and not NTLM. NTLM is not secure. If Kerberos is possible, it should be the protocol used. </b><b></b>

<b><strong>SOLUTION</strong></b>

The solution here was to remove "ContextOptions.<b>ServerBind </b>|  ContextOptions.SimpleBind " and allow the code to use the default (Negotiate). Note, because we were using a domain context but ServerBind this caused the issue. Negotiate with Domain context is the option that works and is successfully able to use kerberos.

Working code:

&lt;snip&gt;
<span style="color: #000080">Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$pc = New-Object System.DirectoryServices.AccountManagement.PrincipalContext($ct, "contoso.com","OU=Accounts,DC=Contoso,DC=Com")
$idType = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
$up = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($pc,$idType, "TestUser")
$up.ChangePassword("oldPassword!123", “newPassword!123”)</span>
&lt;snip&gt;
<h6><span style="font-weight: bold"><span style="color: #4f81bd">Why does this code work before MS16-101 and fail after?</span>

</span></h6>
<b> </b><b>ContextOptions</b> are documented here: <a href="https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.contextoptions(v=vs.110).aspx">https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.contextoptions(v=vs.110).aspx</a>

Specifically: <em>“This parameter specifies the options that are used for binding to the <b>server.</b> The application can set multiple options that are linked with a bitwise OR operation. “</em>

Passing in a domain name such as <b>contoso.com</b> with the ContextOptions ServerBind or SimpleBind causes the client to attempt to use an SPN like <b>ldap\contoso.com</b> because it expects the name which is passed in to be a ServerName.

This is not a valid SPN and does not exist, therefore this will fail and as a result Kerberos will fail with STATUS_NO_LOGON_SERVERS.
Before MS16-101, in this scenario, the Negotiate package would fall back to NTLM, attempt the password change using NTLM and succeed.
Post MS16-101 this fall back is not allowed and Kerberos is enforced.
<h6><span style="color: #4f81bd;font-weight: bold">(b) If Application Code is good but Kerberos fails to locate a DC for other reason

</span></h6>
If you see a correct domain name and SPN’s in the above logs, then the issue is that kerberos fails for some other reason such as blocked TCP ports. In this case revert to Scenario 1 to troubleshoot why Kerberos failed to locate a Domain Controller.

There is a chance that you may also have both (a) and (b). Traces and logs are the best tools to identify.
<h6><span style="color: #000080;font-weight: bold">Scenario6: After you install MS 16-101 update, you may encounter 0xC0000022 NTLM authentication errors.</span></h6>
I will not go into detail of this scenario as it is well described in the KB article <a href="https://support.microsoft.com/kb/3195799">KB3195799</a> NTLM authentication fails with 0xC0000022 error for Windows Server 2012, Windows 8.1, and Windows Server 2012 R2 after update is applied.

That’s all for today! I hope you find this useful. I will update this post if any new information arises.

<b>Linda Taylor | Senior Escalation Engineer | Windows Directory Services
</b>(A well established member of the content police.)]]></content:encoded>
    </item>
    <item>
      <title>Access-Based Enumeration (ABE) Troubleshooting (part 2 of 2)</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/access-based-enumeration-abe-troubleshooting-part-2-of-2</link>
      <pubDate>Wed, 21 Sep 2016 12:59:38 GMT</pubDate>
      <dc:creator><![CDATA[Justin Turner [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=16605</guid>
      <description><![CDATA[Hello everyone! Hubert from the German Networking Team here again with part two of my little Blog...]]></description>
      <content:encoded><![CDATA[<p>Hello everyone! <a href="https://blogs.technet.microsoft.com/askds/tag/hubert-sachs/">Hubert</a> from the German Networking Team here again with part two of my little Blog Post Series about <b>Access-Based Enumeration (ABE). </b>In the <a href="https://blogs.technet.microsoft.com/askds/2016/09/01/access-based-enumeration-abe-concepts-part-1-of-2/">first part</a> I covered some of the basic concepts of ABE. In this second part I will focus on monitoring and troubleshooting Access-based enumeration.<br>We will begin with a quick overview of Windows Explorer’s directory change notification mechanism (Change Notify), and how that mechanism can lead to performance issues before moving on to monitoring your environment for performance issues.<b><br><strong></strong></b><h5>Change Notify and its impact on DFSN servers with ABE</h5><p>Let’s say you are viewing the contents of a network share while a file or folder is added to the share remotely by someone else. Your view of this share will be updated automatically with the new contents of the share without you having to manually refresh (press F5) your view.<br>Change Notify is the mechanism that makes this work in all SMB Protocols (1,2 and 3).<br>The way it works is quite simple:<ol><li>The client sends a <a href="https://msdn.microsoft.com/en-us/library/cc246553.aspx">CHANGE_NOTIFY</a> request to the server indicating the directory or file it is interested in. Windows Explorer (as an application on the client) does this by default for the directory that is currently in focus.</li><li>Once there is a change to the file or directory in question, the server will respond with a CHANGE_NOTIFY Response, indicating that a change happened.</li><li>This causes the client to send a QUERY_DIRECTORY request (in case it was a directory or DFS Namespace) to the server to find out what has changed. <br><br>QUERY_DIRECTORY is the thing we discussed in the first post that causes ABE filter calculations. Recall that it’s these filter calculation that result in CPU load and client-side delays.<br>Let’s look at a common scenario:</li><li>During login, your users get a mapped drive pointing at a share in a DFS Namespace.</li><li>This mapped drive causes the clients to connect to your DFSN Servers </li><li>The client sends a Change Notification (even if the user hasn’t tried to open the mapped drive in Windows Explorer yet) for the DFS Root.<br><br>Nothing more happens until there is a change on the server-side. Administrative work, such as adding and removing links, typically happens during business hours, whenever the administrators find the time, or the script that does it, runs.<br><br>Back to our scenario. Let’s have a server-side change to illustrate what happens next:</li><li>We add a Link to the DFS Namespace.</li><li>Once the DFSN Server picks up the new link in the namespace from Active directory, it will create the corresponding reparse point in its local file system.<br>If you do not use <a href="https://technet.microsoft.com/en-us/library/cc782417(v=ws.10).aspx">Root Scalability Mode</a> (RSM) this will happen almost at the same time on all of the DFS Servers in that namespace. With RSM the changes will usually be applied by the different DFS servers over the next hour (or whatever your SyncInterval is set to).</li><li>These changes trigger CHANGE_NOTIFY responses to be sent out to any client that indicated interest in changes to the DFS Root on that server. This usually applies to hundreds of clients per DFS server.</li><li>This causes hundreds of Clients to send QUERY_DIRECTORY requests simultaneously.</li></ol><p>What happens next strongly depends on the size of your namespace (larger namespaces lead to longer duration per ABE calculation) and the number of Clients (aka Requests) per CPU of the DFSN Server (remember the calculation from the first part?)<p>As your Server does not have hundreds of CPUs there will definitely be some backlog. The numbers above decide how big this backlog will be, and how long it takes for the server to work its way back to normal. Keep in mind that while pedaling out of the backlog situation, your server still has to answer other, ongoing requests that are unrelated to our Change Notify Event.<br>Suffice it to say, this backlog and the CPU demand associated with it can also have negative impact to other jobs.&nbsp; For example, if you use this DFSN server to make a bunch of changes to your namespace, these changes will appear to take forever, simply because the executing server is starved of CPU Cycles. The same holds true if you run other workloads on the same server or want to RDP into the box.<br><b></b><p><b><strong><strong><strong>So! What can you do about it?</strong><br></strong></strong></b>As is common with an overloaded server, there are a few different approaches you could take:<ul><li>Distribute the load across more servers (and CPU cores)</li><li>Make changes outside of business hours</li><li>Disable Change Notify in Windows Explorer</li></ul><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td width="186" valign="top"><p>Approach</p></td><td width="418" valign="top"><p>Method</p></td></tr><tr><td width="186" valign="top"><p>Distribute the load / scale up</p></td><td width="418" valign="top"><p>An expensive way to handle the excessive load is to throw more servers/CPU cores into the DFS infrastructure. In theory, you could increase the number of Servers and the number of CPUs to a level where you can handle such peak loads without any issues, but that can be a very expensive approach.</p></td></tr><tr><td width="186" valign="top"><p>Make changes outside business hours</p></td><td width="418" valign="top"><p>Depending on your organizations structure, your business needs, SLAs and other requirements, you could simply make planned administrative changes to your Namespaces outside the main business hours, when there are less clients connected to your DFSN Servers.</p></td></tr><tr><td width="186" valign="top"><p>Disable Change Notify in Windows Explorer</p></td><td width="418" valign="top"><p>You can set:<br><i>NoRemoteChangeNotify</i><br><i>NoRemoteRecursiveEvents<br></i>See <a href="https://support.microsoft.com/en-us/kb/831129">https://support.microsoft.com/en-us/kb/831129</a><br>to prevent Windows Explorer from sending Change Notification Requests.<br>This is however a client-side setting that disables this functionality (change notify) not just for DFS shares but also for any fileserver it is working with. Thus you have to actively press F5 to see changes to a folder or a share in your Windows Explorer. This might or might not be a big deal for your users.</p></td></tr></tbody></table><h4>Monitoring ABE</h4><p>As you may have realized by now, ABE is not a fire and forget technology---it needs constant oversight and occasional tuning. We’ve mainly discussed the design and “tuning” aspect so far. Let’s look into the monitoring aspect.<h5>Using Task Manager / Process Explorer</h5><p>This is a bit tricky, unfortunately, as any load caused by ABE shows up in Task Manager inside the <b>System</b> process (as do many other things on the server). In order to correlate high CPU utilization in the System process to ABE load, you need to use a tool such as <a href="https://technet.microsoft.com/en-us/sysinternals/processexplorer.aspx">Process Explorer</a> and <a href="https://blogs.technet.microsoft.com/askperf/2007/03/07/memory-management-understanding-pool-resources/">configure it</a> to use <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff558823(v=vs.85).aspx">public symbols</a>. With this configured properly, you can drill deeper inside the System Process and see the different threads and the component names. We need to note, that ABE and the Fileserver both use functions in srv.sys and srv2.sys. So strictly speaking it’s not possible to differentiate between them just by the component names.  However, if you are troubleshooting a performance problem on an ABE-enabled server where most of the threads in the System process are sitting in functions from srv.sys and srv2.sys, then it’s very likely due to expensive ABE filter calculations.  This is, aside from disabling ABE, the best approach to reliably prove your problem to be caused by ABE.<h5>Using Network trace analysis</h5><p>Looking at CPU utilization shows us the server-side problem. We must use other measures to determine what the client-side impact is, one approach is to take a network trace and analyze the SMB/SMB2 Service Response times. You may however end up having to capture the trace on a mirrored switch port. To make analysis of this a bit easier, <a href="https://www.microsoft.com/en-us/download/details.aspx?id=44226">Message Analyzer</a> has an SMB Service Performance chart you can use.<p><a href="https://msdnshared.blob.core.windows.net/media/2016/09/clip_image00218.jpg"><img width="781" height="399" title="clip_image002" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/2016/09/clip_image002_thumb11.jpg" border="0"></a><p>You get there by using a New Viewer, like below.<br><p><a href="https://msdnshared.blob.core.windows.net/media/2016/09/smbserviceperf.jpg"><img width="815" height="744" title="smbserviceperf" alt="smbserviceperf" src="https://msdnshared.blob.core.windows.net/media/2016/09/smbserviceperf_thumb.jpg" border="0"></a></p><p>Wireshark also has a feature that provides you with statistics under Statistics -&gt; Service Response Times -&gt; SMB2. Ignore the values for ChangeNotify (its normal that they are several seconds or even minutes). All other response times translate into delays for the clients. If you see values over a second, you can consider your files service not only to be slow but outright broken.<br>While you have that trace in front of you, you can also look for SMB/TCP Connections that are terminated abnormally by the Client as the server failed to respond to the SMB Requests in time. If you have any of those, then you have clients unable to connect to your file service, likely throwing error messages.</p><h5>Using Performance Monitor</h5><p>If your server is running Windows Server 2012 or newer, the following performance counters are available:</p><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td width="150" valign="top"><p><b><strong>Object</strong></b><b></b></p></td><td width="253" valign="top"><p><b><strong>Counter</strong></b><b></b></p></td><td width="201" valign="top"><p><b><strong>Instance</strong></b><b></b></p></td></tr><tr><td width="150" valign="top"><p>SMB Server Shares</p></td><td width="253" valign="top"><p>Avg. sec /Data Request</p></td><td width="201" valign="top"><p>&lt;Share that has ABE Enabled&gt;</p></td></tr><tr><td width="150" valign="top"><p>SMB Server Shares</p></td><td width="253" valign="top"><p>Avg. sec/Read</p></td><td width="201" valign="top"><p>‘’</p></td></tr><tr><td width="150" valign="top"><p>SMB Server Shares</p></td><td width="253" valign="top"><p>Avg. sec/Request</p></td><td width="201" valign="top"><p>‘’</p></td></tr><tr><td width="150" valign="top"><p>SMB Server Shares</p></td><td width="253" valign="top"><p>Avg. sec/Write</p></td><td width="201" valign="top"><p>‘’</p></td></tr><tr><td width="150" valign="top"><p>SMB Server Shares</p></td><td width="253" valign="top"><p>Avg. Data Queue Length</p></td><td width="201" valign="top"><p>‘’</p></td></tr><tr><td width="150" valign="top"><p>SMB Server Shares</p></td><td width="253" valign="top"><p>Avg. Read Queue Length</p></td><td width="201" valign="top"><p>‘’</p></td></tr><tr><td width="150" valign="top"><p>SMB Server Shares</p></td><td width="253" valign="top"><p>Avg. Write Queue Length</p></td><td width="201" valign="top"><p>‘’</p></td></tr><tr><td width="150" valign="top"><p>SMB Server Shares</p></td><td width="253" valign="top"><p>Current Pending Requests</p></td><td width="201" valign="top"><p>‘’</p></td></tr></tbody></table><p><a href="https://msdnshared.blob.core.windows.net/media/2016/09/clip_image00513.png"><img width="767" height="223" title="clip_image005" alt="clip_image005" src="https://msdnshared.blob.core.windows.net/media/2016/09/clip_image005_thumb6.png" border="0"></a><p>Most noticeable here is <b><strong>Avg. sec/Request</strong></b> counter as this contains the response time to the QUERY_DIRECTORY requests (Wireshark displays them as Find Requests). The other values will suffer from a lack of CPU Cycles in varying ways but all indicate delays for the clients. As mentioned in the first part: We expect single digit millisecond response times from non-ABE Fileservers that are performing well. For ABE-enabled Servers (more precisely Shares) the values for QUERY_DIRECTORY / Find Requests will always be higher due to the inevitable length of the ABE Calculation.<p>When you reached a state where all the other SMB Requests aside of the QUERY_DIRECTORY are constantly responded to in less than 10ms and the QUERY_DIRECTORY constantly in less than 50ms you have a very good performing Server with ABE.<h5>Other Symptoms</h5><p>There are other symptoms of ABE problems that you may observe, however, none of them on their own is very telling, without the information from the points above.<b></b><p>At a first glance a high CPU Utilization and a high Processor Queue lengths are indicators of an ABE problem, however they are also indicators of other CPU-related performance issues. Not to mention there are cases where you encounter ABE performance problems without saturating all your CPUs.<p>The Server Work Queues\Active Threads (NonBlocking) will usually raise to their maximum allowed limit (<a href="https://msdn.microsoft.com/en-us/library/windows/hardware/dn567661(v=vs.85).aspx">MaxThreadsPerQueue</a> ) as well as the Server Work Queues\Queue Length increasing. Both indicate that the Fileserver is busy, but on their own don’t tell you how bad the situation is. However, there are scenarios where the File server will not use up all Worker Threads allowed due to a bottleneck somewhere else such as in the Disk Subsystem or CPU Cycles available to it.</p><p>See the following should you choose to setup long-term monitoring (which you should) in order to get some trends:</p><p><i>Number of Objects per Directory or Number of DFS Links</i><br><i>Number of Peak User requests (Performance Counter: Requests / sec.)</i><br><i>Peak Server Response time to Find Requests or Performance Counter: Avg. sec/Request</i><br><i>Peak CPU Utilization and Peak Processor Queue length.</i><i></i><p>If you collect those values every day (or a shorter interval), you can get a pretty good picture how much head-room you have left with your servers at the moment and if there are trends that you need to react to.<p>Feel free to add more information to your monitoring to get a better picture of the situation.&nbsp; For example: gather information on how many DFS servers were active at any given day for a certain site, so you can explain if unusual high numbers of user requests on the other servers come from a server downtime.<h4>ABELevel</h4><p>Some of you might have heard about the registry key <a href="https://support.microsoft.com/en-us/kb/2732618">ABELevel</a>. The ABELevel value specifies the maximum level of the folders on which the ABE feature is enabled. While the title of the KB sounds very promising, and the hotfix is presented as a “Resolution”, the hotfix and registry value have very little practical application.&nbsp; Here’s why:<br><strong>ABELevel</strong> is a system-wide setting and does not differentiate between different shares on the same server. If you host several shares, you are unable to filter to different depths as the setting forces you to go for the deepest folder hierarchy.  This results in unnecessary filter calculations for shares.<p>Usually the widest directories are on the upper levels---those levels that you need to filter.&nbsp; Disabling the filtering for the lower level directories doesn’t yield much of a performance gain, as those small directories don’t have much impact on server performance, while the big top-level directories do.&nbsp; Furthermore, the registry value doesn’t make any sense for DFS Namespaces as you have only one folder level there and you should avoid filtering on your fileservers anyway.<h5>While we are talking about Updates</h5><p>Here is one that you should install:<br>High CPU usage and performance issues occur when access-based enumeration is enabled in Windows 8.1 or Windows 7 - <a href="https://support.microsoft.com/en-us/kb/2920591">https://support.microsoft.com/en-us/kb/2920591</a><br></p><p>Furthermore you should definitely review the Lists of recommended updates for your server components:<br>DFS<br><a href="https://support.microsoft.com/en-us/kb/968429%20">https://support.microsoft.com/en-us/kb/968429</a> (2008 / 2008 R2)<br><a href="https://support.microsoft.com/en-us/kb/2951262">https://support.microsoft.com/en-us/kb/2951262</a> (2012 / 2012 R2)<br></p><p>File Services<br><a href="https://support.microsoft.com/en-us/kb/2473205">https://support.microsoft.com/en-us/kb/2473205</a> (2008 / 2008 R2)<br><a href="https://support.microsoft.com/en-us/kb/2899011">https://support.microsoft.com/en-us/kb/2899011</a> (2012 / 2012 R2)<br><br>Well then, this concludes this small (my first) blog series.<br>I hope you found reading it worthwhile and got some input for your infrastructures out there.</p><p>With best regards<br>Hubert]]></content:encoded>
    </item>
    <item>
      <title>Access-Based Enumeration (ABE) Concepts (part 1 of 2)</title>
      <link>https://docs.microsoft.com/archive/blogs/askds/access-based-enumeration-abe-concepts-part-1-of-2</link>
      <pubDate>Thu, 01 Sep 2016 21:50:57 GMT</pubDate>
      <dc:creator><![CDATA[Justin Turner [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/askds/?p=16535</guid>
      <description><![CDATA[Hello everyone, Hubert from the German Networking Team here.&nbsp; Today I want to revisit a topic...]]></description>
      <content:encoded><![CDATA[<p>Hello everyone, <a href="https://blogs.technet.microsoft.com/askds/tag/hubert-sachs/">Hubert</a> from the German Networking Team here.&nbsp; Today I want to revisit a topic that I wrote about in 2009: <b>Access-Based Enumeration (ABE)</b><b></b></p>
<p>This is the first part of a 2-part Series. This first part will explain some conceptual things around ABE.&nbsp; The second part will focus on diagnostic and troubleshooting of ABE related problems.&nbsp; The second post is <a href="https://blogs.technet.microsoft.com/askds/2016/09/21/access-based-enumeration-abe-troubleshooting-part-2-of-2/">here</a>.</p>
<p>Access-Based Enumeration has existed since Windows Server 2003 SP1 and has not change in any significant form since my <a href="https://blogs.technet.microsoft.com/deds/2009/03/27/access-based-enumeration-und-seine-performance/">Blog post</a> in 2009. However, what has significantly changed is its popularity.</p>
<p>With its integration into V2 (2008 Mode) DFS Namespaces and the increasing demand for data privacy, it became a tool of choice for many architects. However, the same strict limitations and performance impact it had in Windows Server 2003 still apply today. With this post, I hope to shed some more light here as these limitations and the performance impact are either unknown or often ignored. Read on to gain a little insight and background on ABE so that you:</p>
<ol>
<li>Understand its capabilities and limitations</li>
<li>Gain the background knowledge needed for my next post on how to troubleshoot ABE</li>
</ol>
<p>Two things to keep in mind:</p>
<ul>
<li>ABE is not a security feature (it’s more of a convenience feature)</li>
<li>There is no guarantee that ABE will perform well under all circumstances. If performance issues come up in your deployment, disabling ABE is a valid solution.</li>
</ul>
<p>So without any further ado let’s jump right in:</p>
<p><b><strong>What is ABE and what can I do with it?<br>
</strong></b>From the <a href="https://technet.microsoft.com/en-us/library/dd772681(v=ws.10).aspx">TechNet topic</a>:</p>
<blockquote><p>“Access-based enumeration displays only the files and folders that a user has permissions to access. If a user does not have Read (or equivalent) permissions for a folder, Windows hides the folder from the user’s view. This feature is active only when viewing files and folders in a shared folder; it is not active when viewing files and folders in the local file system.”</p></blockquote>
<p>Note that ABE has to check the user’s permissions at the time of enumeration and filter out files and folders they don’t have Read permissions to. Also note that this filtering only applies if the user is attempting to access the share via SMB versus simply browsing the same folder structure in the local file system.<br>
For example, let’s assume you have an ABE enabled file server share with 500 files and folders, but a certain user only has read permissions to 5 of those folders. The user is only able to view 5 folders when accessing the share over the network. If the user logons to this server and browses the local file system, they will see all of the files and folders.</p>
<p>In addition to file server shares, ABE can also be used to filter the links in DFS Namespaces.<br>
With V2 Namespaces DFSN got the capability to store permissions for each DFSN link, and apply those permissions to the local file system of each DFSN Server.<br>
Those NTFS permissions are then used by ABE to filter directory enumerations against the DFSN root share thus removing DFSN links from the results sent to the client.</p>
<p>Therefore, ABE can be used to either hide sensitive information in the link/folder names, or to increase usability by hiding hundreds of links/folders the user does not have access to.</p>
<p><b><strong>How does it work?<br>
</strong></b>The filtering happens on the file server at the time of the request.<br>
Any Object (File / Folder / Shortcut / Reparse Point / etc.) where the user has less than generic read permissions is omitted in the response by the server.<br>
Generic Read means:</p>
<ul>
<li>List Folder / Read Data</li>
<li>Read Attributes</li>
<li>Read Extended Attributes</li>
<li>Read Permissions</li>
</ul>
<p>If you take any of these permissions away, ABE will hide the object.<br>
So you could create a scenario (i.e. remove the Read Permission permission) where the object is hidden from the user, but he/she could still open/read the file or folder if the user knows its name.</p>
<p>That brings us to the next important conceptual point we need to understand:</p>
<p><b><strong>ABE does not do access control.</strong></b><br>
It only filters the response to a Directory Enumeration. The access control is still done through NTFS.<br>
Aside from that ABE only works when the access happens through the Server Service (aka the Fileserver). Any access locally to the file system is not affected by ABE. Restated:</p>
<blockquote><p>“Access-based enumeration does not prevent users from obtaining a referral to a folder target if they already know the DFS path of the folder with targets. Permissions set using Windows Explorer or the Icacls command on namespace roots or folders without targets control whether users can access the DFS folder or namespace root. However, they do not prevent users from directly accessing a folder with targets. Only the share permissions or the NTFS file system permissions of the shared folder itself can prevent users from accessing folder targets.” Recall what I said earlier, “ABE is not a security feature”. <a href="https://msdn.microsoft.com/en-us/library/dd759150(v=ws.11).aspx">TechNet</a></p></blockquote>
<p><b><strong>ABE does not do any caching.</strong></b><br>
Every requests causes a filter calculation. There is no cache. ABE will repeat the same exact work for identical directory enumerations by the same user.</p>
<p><b><strong>ABE cannot predict the permissions or the result.</strong></b><br>
It has to do the calculations for each object in every level of your folder hierarchy every time it is accessed.<br>
If you use inheritance on the folder structure, a user will have the same permission and thus the same filter result from ABE through the entire folder structure. Still ABE as to calculate this result, consuming CPU Cycles in the process.<br>
If you enable ABE on such a folder structure you are just wasting CPU cycles without any gain.</p>
<p>With those basics out of the way, let’s dive into the mechanics behind the scenes:</p>
<p><b><strong>How the filtering calculation works</strong></b><b></b></p>
<ol>
<li>When a QUERY_DIRECTORY request (<a href="https://msdn.microsoft.com/en-us/library/cc246551.aspx">https://msdn.microsoft.com/en-us/library/cc246551.aspx</a>) or its SMB1 equivalent arrives at the server, the server will get a list of objects within that directory from the filesystem.</li>
<li>With ABE enabled, this list is not immediately sent out to the client, but instead passed over to the ABE for processing.</li>
<li>ABE will iterate through EVERY object of this list and compare the permission of the user with the objects ACL.</li>
<li>The objects where the user does not have generic read access are removed from the list.</li>
<li>After ABE has completed its processing, the client receives the filtered list.</li>
</ol>
<p>This yields two effects:</p>
<ul>
<li>This comparison is an active operation and thus consumes CPU Cycles.</li>
<li>This comparison takes time, and this time is passed down to the User as the results will only be sent, when the comparisons for the entire directory are completed.</li>
</ul>
<p><b><strong>This brings us directly to the core point of this Blog:<br>
</strong></b>In order to successfully use ABE in your environment you have to manage both effects.<br>
If you don’t, ABE can cause a wide spread outage of your File services.</p>
<p><b><strong>The first effect can cause a complete saturation of your CPUs (all cores at 100%).</strong></b><br>
This does not only increase the response times of the Fileserver to its clients to a magnitude where the Server is not accepting any new connections or the clients kill their connection after not getting a response from the server for several minutes, but it can also prevent you from establishing a remote desktop connection to the server to make any changes (like disabling ABE for instance).</p>
<p><b><strong>The second effect can increase the response times of your fileserver (even if its otherwise Idle) to a magnitude that is not accepted by the Users anymore.</strong></b><br>
The comparison for a single directory enumeration by a single user can keep one CPU in your server busy for quite some time, thus making it more likely for new incoming requests to overlap with already running ABE calculations. This eventually results in a Backlog adding further to the delays experienced by your clients.<br>
<b></b></p>
<p><b>To illustrate this let’s roll some numbers:</b><br>
A little disclaimer:<br>
<i>The following calculation is what I’ve seen, your results may differ as there are many moving pieces in play here. In other words, your mileage may vary. That aside, the numbers seen here are not entirely off but stem from real production environments. </i><i>Performance of Disk and CPU and other workloads play into these numbers as well.</i><br>
<i>Thus the calculation and numbers are for illustration purposes only. Don’t use it to calculate your server’s performance capabilities.</i></p>
<p align="left">Let’s assume you have a DFS Namespace with 10,000 links that is hosted on DFS Servers that have 4 CPUs with 3.5 GHz (also assuming RSS is configured correctly and all 4 CPUs are used by the File service: <a href="https://blogs.technet.microsoft.com/networking/2015/07/24/receive-side-scaling-for-the-file-servers/">https://blogs.technet.microsoft.com/networking/2015/07/24/receive-side-scaling-for-the-file-servers/</a> ).<br>
We usually expect single digit millisecond response times measured at the fileserver to achieve good performance (network latency obviously adds to the numbers seen on the client).<br>
In our scenario above (10,000 Links, ABE, 3.5 Ghz CPU) it is not unseen that a single enumeration of the namespace would take 500ms.</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="114" valign="top">CPU cores and speed</td>
<td width="127" valign="top">DFS Namespace Links</td>
<td width="141" valign="top">RSS configured per recommendations</td>
<td width="121" valign="top">ABE enabled?</td>
<td width="101" valign="top">Response time</td>
</tr>
<tr>
<td width="114" valign="top">4 @ 3.5 GHz</td>
<td width="127" valign="top">10,000</td>
<td width="141" valign="top">Yes</td>
<td width="121" valign="top">No</td>
<td width="101" valign="top">&lt;10ms</td>
</tr>
<tr>
<td width="114" valign="top">4 @ 3.5 GHz</td>
<td width="127" valign="top">10,000</td>
<td width="141" valign="top">Yes</td>
<td width="121" valign="top"><b>Yes</b><b></b></td>
<td width="101" valign="top"><b>300 – 500 ms</b></td>
</tr>
</tbody>
</table>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="101" valign="top">
<p align="left"><strong></strong></p>
</td>
</tr>
</tbody>
</table>
<p>That means a single CPU can handle up to 2 Directory Enumerations per Second. Multiplied by 4 CPUs the server can handle 8 User Requests per Second. Any more than those 8 requests and we push the Server into a backlog.<br>
Backlog in this case means new requests are stuck in the Processor Queue behind other requests, therefore multiplying the wait time.<br>
This can reach dimensions where the client (and the user) is <b><u><strong>waiting for minutes</strong></u></b> and the client eventually decides to kill the TCP connection, and in case of DFSN, fail over to another server.</p>
<p>Anyone remotely familiar with Fileserver Scalability probably instantly recognizes how bad and frightening those numbers are.&nbsp; Please keep in mind, that not every request sent to the server is a QUERY_DIRECTORY request, and all other requests such as Write, Read, Open, Close etc. do not cause an ABE calculation (however they suffer from an ABE-induced lack of CPU resources in the same way).<br>
Furthermore, the Windows File Service Client caches the directory enumeration results if SMB2 or SMB3 is used (<a href="https://technet.microsoft.com/en-us/library/ff686200(v=ws.10).aspx">https://technet.microsoft.com/en-us/library/ff686200(v=ws.10).aspx</a> ).<br>
There is no such Cache for SMB1. Thus SMB1 Clients will send more Directory Enumeration Requests than SMB2 or SMB3 Clients (particularly if you keep the F5 key pressed).<br>
It should now be obvious that you should use SMB2/3 versus SMB1 and ensure you leave the caches enabled if you use ABE on your servers.</p>
<p>As you might have realized by now, there is no easy or reliable way to predict the CPU demand of ABE. If you are developing a completely new environment you usually cannot forecast the proportion of QUERY_DIRECTORY requests in relation to the other requests or the frequency of the same.</p>
<p><b><strong>Recommendations!<br>
</strong></b>The most important recommendation I can give you is:</p>
<p><b><strong>Do not enable ABE unless you really need to.</strong></b><br>
Let’s take the Users Home shares as an example:<br>
Usually there is no user browsing manually through this structure, but instead the users get a mapped drive pointing to their folder. So the usability aspect does not count.&nbsp; Additionally most users will know (or can find out from the Office Address book) the names or aliases of their colleagues. So there is no sensitive information to hide here.&nbsp; For ease of management most home shares live in big namespace or server shares, what makes them very unfit to be used with ABE.&nbsp; In many cases the user has full control (or at least write permissions) inside his own home share.&nbsp; Why should I waste my CPU Cycles to filter the requests inside someone’s Home Share?</p>
<p>Considering all those points, I would be intrigued to learn about a telling argument to enable ABE on User Home Shares or Roaming Profile Shares.&nbsp; Please sound off in the comments.</p>
<p>If you have a data structure where you really need to enable ABE, your file service concept needs to facilitate these four requirements:</p>
<p><b><strong>You need Scalability.</strong></b><br>
You need the ability to increase the number of CPUs doing the ABE calculations in order to react to increasing numbers (directory sizes, number of clients, usage frequency) and thus performance demand.<br>
The easiest way to achieve this is to do <a href="https://msdn.microsoft.com/en-us/library/dd759150(v=ws.11).aspx">ABE Filtering exclusively in DFS Domain Namespaces</a> and not on the Fileservers.<br>
By that you can add easily more CPUs by just adding further Namespace Servers in the sites where they are required.<br>
Also keep in mind, that you should have some redundancy and that another server might not be able to take the full additional load of a failing server on top of its own load.</p>
<p><b><strong>You need small chunks</strong></b><br>
The number of objects that ABE needs to check for each calculation is the single most important factor for the performance requirement.<br>
Instead of having a single big 10,000 link namespace (same applies to directories on file servers) build 10 smaller 1,000 link-namespaces and combine them into a DFS Cascade.<br>
By that ABE just needs to filter 1,000 objects for every request.<br>
Just re-do the example calculation above with 250ms, 100ms, 50ms or even less.<br>
You will notice that you are suddenly able to reach very decent numbers in terms of Requests/per Second.<br>
The other nice side effect is, that you will do less calculations, as the user will usually follow only one branch in the directory tree, and is thus not causing ABE calculations for the other branches.</p>
<p><b><strong>You need Separation of Workloads.</strong></b><br>
Having your SQL Server run on the same machine as your ABE Server can cause a lack of Performance for both workloads.<br>
Having ABE run on you Domain Controller exposes your Domain Controller Role to the risk of being starved of CPU Cycles and thus not facilitating Domain Logons anymore.</p>
<p><b><strong>You need to test and monitor your performance</strong></b><br>
In many cases you are deploying a new file service concept into an existing environment.<br>
Thus you can get some numbers regarding QUERY_DIRECTORY requests, from the existing DFS / Fileservers.<br>
Build up your Namespace / Shares as you envisioned and use the File Server Capacity Tool (<a href="https://msdn.microsoft.com/en-us/library/windows/hardware/dn567658(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/windows/hardware/dn567658(v=vs.85).aspx</a> ) to simulate the expected load against it.<br>
Monitor the SMB Service Response Times, the Processor utilization and Queue length and the feel on the client while browsing through the structures.<br>
This should give you an idea on how many servers you will need, and if it is required to go for a slimmer design of the data structures.<br>
Keep monitoring those values through the lifecycle of your file server deployment in order to scale up in time.<br>
Any deployment of new software, clients or the normal increase in data structure size could throw off your initial calculations and test results.<br>
<b><strong>This point should imho be outlined very clearly in any concept documentation.</strong></b></p>
<p>This concludes the first part of this Blog Series.<br>
I hope you found it worthwhile and got an understanding how to successfully design a File service with ABE.<br>
Now to round off your knowledge, or if you need to troubleshoot a Performance Issue on an ABE-enabled Server, I strongly encourage you to read the second part of this Blog Series. This post will be updated as soon as it’s live.</p>
<p>With best regards,<br>
Hubert</p>]]></content:encoded>
    </item>
  </channel>
</rss>