Microsoft's official enterprise support blog for AD DS and more
Hi folks, Ned here again. We've been asked many times to provide more specific information on what USMT migrates when using the included manifests and calling the OS' built-in manifests . We've touched on these details previously in the so-called "operating system components" listed under TechNet article "What Does USMT Migrate".
After deeper investigation over the past few months, I have compiled a list of explicit descriptions that cover exactly what components we migrate and what this means in practical terms. Because operating system manifests focus mainly on SCANSTATE behavior, these descriptions are currently for XP and Vista. XP and Vista are far more likely to be the source OS and I didn’t want you to wait another month or two (or six). I am working on the Windows 7 portion and will update this series when it's ready.
Ned “better than counting sheep” Pyle
Hi guys, Joji Oshima here again. Today I want to talk about configuring Kerberos authentication to work in a load-balanced environment. This is a more advanced topic that requires a basic understanding of how Kerberos works. If you want an overview of Kerberos, I would suggest Rob’s excellent post, Kerberos for the Busy Admin. In this post, I will be using a load balanced IIS web farm as the example, but the principal applies for other applications.
The Basics:
As you may know, Kerberos relies on Service Principal Names (SPNs). SPNs are associated with objects in Active Directory and registered under the servicePrincipalName attribute.
If you are using 2008 Server or higher, you can view this attribute using Active Directory Users and Computers (ADUC) with Advanced Features enabled and going to the Attribute Editor tab. Click the View menu and then select Advanced Features
You can also view attributes using ADSI Edit (adsiedit.msc) or the Setspn command line tool.
When an application makes a request for a Kerberos ticket, it makes that request for a specific SPN (like http/server01.contoso.com). The Key Distribution Center (KDC) will search Active Directory for the object that has that principal name registered to it, and encrypt the ticket with that object’s password. The object that is running the service has the same password, so when the ticket arrives, it can decrypt it.
The Problem:
If you have a single IIS server, the service is typically running under Local System. The standard SPNs are registered to the computer account (like host/server01 & host/server01.contoso.com)* so when a request for http/server01 comes in, the ticket will be encrypted using the computer account’s password. This configuration works well for a single server environment.
*The host SPN works for many services including http. If there is a specific entry for http, it will use that, otherwise it will fallback and use host.
In a load-balanced environment, users will access the service using a unified name instead of the individual servers. Therefore, instead of accessing server01.contoso.com or server02.contoso.com, they will access myapplication.contoso.com. In this scenario, there are two computer accounts, so where do you register the Service Principal Name? One idea would be to register the principal name to both computer accounts. The problem with this idea is that Service Principal Names must be unique. When the request comes in for http/myapplication.contoso.com, the KDC would not know which object’s password to encrypt the ticket with, so it will return an error. You will also see Event ID 11 populating your event logs if you have any duplicate SPNs in your directory.
The Solution:
Instead of running the service under Local System, have each server run the application using a specific service account. In IIS, you can accomplish this by having the application pool run under the service account. Here is how you would set it in IIS7. You could also follow the instructions in this TechNet article.
1. Open Internet Information Services (IIS Manager) and browse to the Application Pools page 2. Right click the application pool that is running your site, and choose Advanced Settings 3. Under Process Model, look for Identity and click the button to the right 4. This will bring up a dialog box where you can choose what credentials to use for the application pool. Choose Custom account and click the set button. 5. Enter the credentials for your service account and click ok 6. If you are using IIS7 and have Kernel Mode Authentication set, you will need to do one additional step. Open the ApplicationHost.config file and enable the useAppPoolCredentials setting. IIS7 added the option to authenticate users in Kernel mode to speed up the authentication process. By default, it will use the computer account for authentication requests even if the application pool is set to a service account. By changing this setting, you get the benefits of Kernel Mode Authentication, but still authenticate with the service account. Sample ApplicationHost.config change: <system.webServer> <security> <authentication> <windowsAuthentication enabled="true" useAppPoolCredentials="true" /> </authentication> </security> </system.webServer>
1. Open Internet Information Services (IIS Manager) and browse to the Application Pools page
2. Right click the application pool that is running your site, and choose Advanced Settings
3. Under Process Model, look for Identity and click the button to the right
4. This will bring up a dialog box where you can choose what credentials to use for the application pool. Choose Custom account and click the set button.
5. Enter the credentials for your service account and click ok
6. If you are using IIS7 and have Kernel Mode Authentication set, you will need to do one additional step. Open the ApplicationHost.config file and enable the useAppPoolCredentials setting. IIS7 added the option to authenticate users in Kernel mode to speed up the authentication process. By default, it will use the computer account for authentication requests even if the application pool is set to a service account. By changing this setting, you get the benefits of Kernel Mode Authentication, but still authenticate with the service account.
Sample ApplicationHost.config change:
<system.webServer> <security> <authentication> <windowsAuthentication enabled="true" useAppPoolCredentials="true" /> </authentication> </security> </system.webServer>
After you have the services running under the same service account, register the unified name, http/myapplication.contoso.com, to that service account. No matter which server the client is routed to, the service will be able to decrypt the ticket using its password. You can register SPNs using the command line tool Setspn.
Extra Credit:
Suppose you want the ability to use Kerberos authentication accessing the servers individually and using the unified name. Currently, if you request a ticket for http/server01.contoso.com, the KDC will encrypt the ticket using server01’s computer object password. The service is not running under local system, so it will not be able to decrypt that ticket. However, you can register additional SPNs to the service account. In this scenario, you could register the following SPNs to the service account.
You can also view the attributes currently registered to an account using the Setspn command line tool. Syntax: Setspn –l accountname
This will not interfere with the host SPNs registered to the computer account. When an incoming request comes for http/server01, it will check for the exact string first. If it cannot find it, it will look for host/server01.
Problems:
Remember that a Service Principal Name can only be registered on one account at a time. If you are using 2008 Server or higher, you can search for duplicate SPNs in your environment by using the command: Setxpn -f -q http/myapplication*
You can also use the command line tool LDIFDE to find duplicate SPNs. The command below will output a text file called SPN.txt that contains all objects with a service principal name that starts with http/myapplication. This file will be located in the same directory you run the command in unless you specify a path in the –f switch.
LDIFDE -f spn.txt -r (serviceprincipalname=http/myapplication*) -l serviceprincipalname
Final Thoughts:
There are many benefits to using Kerberos authentication but configuring it properly may feel like a daunting task, especially in a more complex environment. I hope this post makes configuring this a bit easier.
- Joji “adult swim in the app pool” Oshima
It’s been four years and 591 posts since AskDS reached critical mass. You’d hope our party would look like this:
But it’s more likely to be:
Without you, we’d be another of those sites that glow red hot, go supernova, then collapse into a white dwarf. We really appreciate your comments, questions, and occasional attaboys. Hopefully we’re good for another year of insightful commentary.
Thanks readers.
The AskDS Contributors
Hiya folks, Ned here again. This week we talk:
Start the word punching!
We are interested in removing the A records that are created by Domain Controllers in our Windows 2008 R2 environment so that we can have web servers respond to the FQDN without needing WWW, from our users on the internal network. So for example, if our AD forest name is contoso.com, we want to add the contoso.com FQDN to a web server, but can't because the DC A records are currently claimed. Is this possible to do without affecting normal client operations?
Removing the “same as parent folder” A Records from DCs and blocking their further creation using Group Policy is going to cause issues.
For example, you cannot create domain DFS namespaces, as it will explode trying to use the A records to find the domain namespace, with the oh-so-helpful “RPC server is unavailable” error:
Any applications that use generic A records as part of a domain controller lookup, instead of SRV records, will fail. Any apps that “ping” - not necessarily with ICMP - the domain to locate a DC will fail also. Some of these apps are Microsoft: ADMT has that problem too and there are likely others. Mostly though, they will be third party or homegrown apps and therefore unknowable to me. You will need to inventory all your application in the entire environment and try them all out in a test lab. That sounds like fun!
This is the problem with using a public facing domain as the root of your AD forest, rather than building a new root under the FQDN. For example, Microsoft’s main AD forest root is corp.microsoft.com.
The options:
Is it possible to use forwarded event log subscriptions with the DC’s Security event logs? It’s working for other logs, so I know I am doing it correctly in general, but the Security event log specifically never forwards from my DCs to my collector computer.
By default, the Security logs cannot be forwarded due to permissions ACL’ing the log – the service that does the event collection has no rights to it. Being a DC is not relevant, even member servers have slightly more restrictive access to that log. On the servers you want to collect security event logs from (or in your case, on any DC in that domain), run:
net localgroup "Event Log Readers" "NT Authority\Network Service" /add
Let that replicate to all other DCs in the domain. Then restart those DCs. Now you can configure your subscription-collector… goo. And if you set up all the subscriptions and service correctly, will work. Here’s my 01 DC forwarding security events to my 05 member server:
The steps for doing all this event log subscription stuff are here:
Our Mainframe requires that user passwords be no longer than 8 characters and can only use a few special characters. Can Windows AD password policy enforce this type of limitation also, so our users don’t have to remember two passwords?
No, you must create or purchase a password filter DLL to run on your DCs. We talked about the password rules on AD here previously. Our only limit to the maximum password length is the actual max – 128 characters, it’s not configurable. We’re mainly concerned with providing more avenues to complexity, not fewer. As always, I recommend two-factor auth when possible; passwords alone are not safe enough, and third party front-end tools that make the user pick words resistant to dictionary and PII attack are just encouraging users to write them down and tape it to their monitor.
I highly discourage anyone from trying to write their own password filter DLL, by the way, and you should carefully test any third party ones before purchasing. There are a lot of filter vendors, so use that to your advantage at the negotiating table. The DLL has to run in LSASS.EXE on all your DCs. We have worked many a CritSit here where a custom password filter would cause LSASS to crash, which means no more DCs. Not to mention that you need to trust your vendor enough that they are correctly vetting their code, making sure there are no buffer overruns, injection attacks, etc. – you are giving them the highest possible privilege in your entire company. That vendor is effectively running as the DC itself, so they’d better be careful – nor should they like leaving little backdoors in their code. You know, like Siemens did with their nuclear control software.
Some of these vendors also sell GINA or Credential Provider components. Beware any vendor that wants to sell you just those front-end pieces and not a DC password filter DLL. While helpful to the user, those clients are easily bypassed (often by accident, like when going through an Outlook Web Access page) and should not be the only way that passwords are restricted. The DC is the final password arbiter, so that’s where you need to enforce things.
Just toss the Mainframe, this all sounds like too much work. :-P
Does Windows Server 2003 auditing differentiate between NTLM and NTLMv2 as the authentication package recorded in the 528/529 events? I already know about event ID 4624 in Advanced auditing.
No, it will always just say "ntlm". Because that auditing dates back to NT 3 and is exceptionally gross.
I would like to programmatically detect if a given UNC path contains a DFS root or not – is that possible?
NetShareGetInfo is one way, as it’s can return DFS structure SHARE_INFO_1005 if asked. Alternatively, you can also use: NetDfsGetInfo with \\server_or_domain\share and level 1 should tell you if the path is DFS. If success, the path is DFS. Unfortunately, almost any error returned does not necessarily mean that it is or isn’t DFS, just that something is broken. Also, the API is a blocking call and there is no timeout mechanism.
Is it possible to use Excel Shared workbooks with DFSR on Windows Server 2008 R2?
Yes, with the caveats that:
From my long understanding, when you host your DFS Namespace on Domain Controllers, you must be member of the Domain Admin Group in order to administer it; you can’t delegate the administration to a standard user. It talks about this in KB258992 and elsewhere. But I just tried delegating a user for a namespace that is hosted on DCs, and they were able to create links, delete them, and even delete the namespace root servers and the namespace itself! He’s not a member of any admin groups.
If I delegate a user, I can modify and delete all aspects of a namespace except share removal. I cannot create new namespaces though, even if the share I want to use already exists and was created for me by an admin. If I try, “service control manager cannot be opened: access is denied” and kaboom:
This is the case with both DCs and non-DCs - it makes no difference. The nugget here is that the KB only states the limitation once, and too loosely:
When you delegate to users the ability to create DFS shares, the configuration of the DFS dictates how delegation must occur. When you configure a stand-alone DFS server, the delegation process involves adding the user who is delegated to the local Administrators group on the DFS server. When you configure a domain DFS, the user who is delegated must be added to the local Administrators group on each of the Root DFS server replicas. If the DFS root is on a domain controller, the user must be added to the Domain Admins group; otherwise, the user will receive an "access denied" error message.
The UI states “Delegate Management Permissions” so it’s a semantic argument over what that means. The fact that you cannot connect to Service Control Manager without admin permissions is not DFSN’s fault, though. And that’s why you need to be a member of the Administrators or Domain Admins group on DCs to fully manage DFS. If you were to do some unsupported hackery that let some delegated user operate the service control manager, you might as well make them be an admin – they can kill all your DCs now by shutting off all the services!
Black Hat USA is this week. When they start posting briefings I’ll do my usual analysis.
A list of amusing units of measurement. Mention of measure usually drives a European to show up complaining that we still don’t use the metric system in the US. Which is incorrect, but regardless, here’s my offer: we’ll fully mandate the metric system in the US when you abolish the hundreds of languages of Europe and use only English, the language of science, information technology, business, seafaring, aviation, entertainment, radio and diplomacy. Then you will be efficient in a way far more meaningful than hectares and grams. Bwaamp!
Odd, I usually find that swearing makes me feel better. #%@$@&^*!
The Car Show is better than Top Gear USA, as long as you start with Episode 3 of TCS.. Neither is fit to hold proper Top Gear’s sweaty Stig helmet.
Any playlist made up songs from the movie soundtracks of Inception, Blade Runner, and The Abyss is hypnotically awesome. I cannot stop listening to these.
Finally, my favorite new t-shirt from comic-con 2011…
… and my favorite new t-shirt vendor, thanks to their booth packing two of the best games of all time, Defender and Battlezone. Now I just need Robots and Spaceships.
Have a great weekend folks.
Ned “bring back vector graphics” Pyle
Ned here. We rarely release USMT KB articles, so this post is to spread the word on a scenario that is easy to run into: do not allow calling of the Microsoft-Windows-COM-ComPlus-Setup-DL or Windows-COM-ComPlus-Setup manifests if migrating from x86 to x64. Bad things will happen otherwise, and while fixing it is easy on one machine, fixing it on 10,000 is not. For steps on preventing the issue and remediation, see:
USMT 4.0 migration from x86 to x64 results in corrupted COM+ components - http://support.microsoft.com/kb/2481190
This effectively means that CONFIG.XML is now a required option for SCANSTATE, if you are moving from 32-bit to 64-bit OS. If going from 32-bit to 32-bit, or 64-bit to 64-bit, you have nothing to worry about.
Until next time.
Ned “Com Minus” Pyle
Heya folks, Ned here again. Microsoft is legendary for its backwards compatibility. No other operating system family can claim to support as much older software and settings as Windows - heck, companies like Apple seem to proudly cut "legacy" support after a few years and spin it like it's a positive.
Man, that is an old app
We maintain legacy protocols for decades. We update our OSes for 10+ years free of charge, and then do best effort support forever. In the past week alone, I worked on two different NT 4.0 issues. I'm not sure how our recent college hires are going to handle those when I'm gone, since they were seven when that OS shipped o_O. We're it for the long haul because we're a software company, not a hardware company pretending to be otherwise.
Every blue moon though, we make changes to an existing component in order to fix a problem or get it in line with modern coding practices, and you’re left holding the bag when migrating between operating systems. Today I talk about one of those scenarios and how USMT can convert a registry data type on the fly in order to preserve your user's customized experience. If you’re instead looking to create a registry setting on the fly, go here.
Windows allows users to choose how to click - double or single, with or without an underline. Any Windows version allows the same behavior and the Folder Options UI is the same:
However, XP and later operating systems differ in the storage method. Both values are in the following location, per user:
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer ShellState IconUnderline
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
ShellState
IconUnderline
ShellState is stored in both OSes as a REG_BINARY value. However, IconUnderline is stored on XP as a REG_NONE and on Vista or Windows 7 as a REG_DWORD.
That means when you migrate from XP to Windows 7, your users keep their click preference, but lose their underline preference and instead get the OS default - which is not to show them underlines except on hover. That's the opposite of XP's behavior.
The Shell development team wrote two included manifests that control this behavior:
C:\usmt\X86\DLMANIFESTS>findstr /i "shellstate" *.man
EXPLORER-DL.MAN: <pattern type="Registry">HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer [ShellState]</pattern>
<rules context="User">
<include>
<objectSet>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Streams\Desktop [Taskbar]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Streams\Desktop [TaskbarWinXP]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects [Settings]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects2 [Settings]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\* [*]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [EnableAutoTray]</pattern>
<pattern type="Registry">HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer [ShellState]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\StartPage\* [*]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify\* [*]</pattern>
</objectSet>
</include>
C:\usmt\X86\DLMANIFESTS>findstr /i "iconunderline" *.man
SHELL32-DL.MAN: <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [IconUnderline]</pattern>
<rules context="user">
<!-- Advanced Folder Option Settings -->
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState [*]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [IconUnderline]</pattern>
</rules>
All of this behavior is expected and by design, although not an optimal one. That little REG_NONE beauty dates back to Windows 95 and Internet Explorer 4.0. When we were writing Vista, we decided enough was enough and to switched to a normal data type. It wasn't intentional that the manifests fail to convert the setting; that just slipped through the cracks.
So what can you do about it?
In its large bag of tricks, USMT includes an element named <contentModify> . When used during loadstate, it allows you to change the data before writing to the destination computer. This includes changing types or even writing new values.
In this case, I need the XP type to change to the Windows 7 type, so I use ConvertToDWORD:
<!-- Converts XP's REG_NONE setting to REG_DWORD --> <contentModify script="MigXmlHelper.ConvertToDWORD('3')"> <objectSet> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [iconunderline]</pattern> </objectSet> </contentModify>
<include> <objectSet> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [iconunderline]</pattern>
</objectSet> </include>
ConvertToDWORD('3') means change the data type from whatever it is currently to a DWORD registry value. If there is any problem converting, set the new DWORD value to 0x3. I chose 3 here because that is the default single-click behavior on XP.
Returning to the example scenario, I test my new XML and it's still not working: the destination Windows 7 computer is receiving the REG_NONE value. Can you guess why?
It's because, even though I am changing the migration behavior, I am doing it in the context of some new XML. I am not unconditionally excluding data, so the other guy copying this data - the included manifests - are overriding my decisions.
There are two ways to fix this:
You could modify SHELL32-DL.MAN to include your new XML settings within its context. This version control nightmare is not recommended (bordering on not supported). We provide override mechanisms so that you don't need to modify the included down level and replacement manifests.
1. Generate a CONFIG.XML on a test XP source computer using scanstate /genconfig config.xml
2. Set the following element to NO in the config.xml and save that file. Copy it to your USMT folder for use on all subsequent XP source computers:
<component displayname="Microsoft-Windows-shell32-DL" migrate="no" ID="http://www.microsoft.com/migration/1.0/migxmlext/cmi/microsoft-windows-shell32-dl/microsoft-windows-shell32-dl/settings"/>
3. Use the following sample in a custom XML file called by scanstate and loadstate. It does all the work of the XP downlevel Shell32 manifest, as well as converts the iconunderline to DWORD. Do not use any of these steps if Vista or Win7 are source computers - they have the correct data type already:
<?xml version="1.0" encoding="UTF-8"?> <migration urlid="http://www.microsoft.com/migration/1.0/CustomIconUnderlineAndShell32"> <component context="User" type="Application"> <displayName>CustomIconUnderlineAndShell32</displayName> <role role="Settings"> <!-- Used only when migrating from XP, in conjunction with CONFIG.XML where Shell32 is set to NO --> <rules context="user"> <!-- Converts XP's REG_NONE setting to REG_DWORD --> <contentModify script="MigXmlHelper.ConvertToDWORD('3')"> <objectSet> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [iconunderline]</pattern> </objectSet> </contentModify> <include> <objectSet> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [iconunderline]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState [*]</pattern> <pattern type="File">%CSIDL_APPDATA%\Microsoft\Windows\Recent [*]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs\* [*]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\ShellNoRoam\BagMRU\* [*]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\ShellNoRoam\Bags\* [*]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\Shell\BagMRU\* [*]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\Shell\Bags\* [*]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu [{450D8FBA-AD25-11D0-98A8-0800361B1103}]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel [{450D8FBA-AD25-11D0-98A8-0800361B1103}]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu [{20D04FE0-3AEA-1069-A2D8-08002B30309D}]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel [{20D04FE0-3AEA-1069-A2D8-08002B30309D}]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu [{208D2C60-3AEA-1069-A2D7-08002B30309D}]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel [{208D2C60-3AEA-1069-A2D7-08002B30309D}]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu [{871C5380-42A0-1069-A2EA-08002B30309D}]</pattern> <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel [{871C5380-42A0-1069-A2EA-08002B30309D}]</pattern> </objectSet> </include> </rules> </role> </component> </migration>
4. Fire it up. Example, where I called my new custom code icon.xml:
Simple as that. Hopefully you find this this technique useful for other registry type issues that crop up.
Ned "get your money back" Pyle