Michel Barneveld
To unpathed waters, undreamed shores
The reason why KB911149 and KB908209 are not the solution!

 

"Do not use CNAME dns records and non default web ports when using Kerberos!"

The last 2 years I have done quite some Kerberos review and troubleshooting sessions (usually in combination with SharePoint) for big customers of Imtech but also for some Microsoft customers. And quite often I tell them the above sentence to not use CNAME dns records and non default web ports when doing Kerberos authentication. So, does that mean that Kerberos doesn't work with CNAME dns records and non default web ports? No, Kerberos can work with that ... in some cases. But usually it complexes the setup and introduces different behaviour for different versions of Windows, Internet Explorer and other client.
And that is the key take away of this blog entry:

If you use HOST A dns records and default web ports (80 and 443) than all version of the Windows OS, Internet Explorer and other Web Clients will show the same consistent behaviour. When you introduce CNAME records or non default ports than different applications or versions will show different behaviour.

 A lot of my customers are unaware of the different behaviour, but some are and give a response like:
Customer: "Yeah, we know that. But we have implemented KB911149, KB938305 and/or KB908209 (and maybe even some others) on all our desktops. So we shouldn't have a problem."


So what are these KB articles?

KB911149 and KB938305

KB911149 and KB938305 are fixes for Internet Explorer to use CNAME records with Kerberos authentication. On some versions you need to apply a hotfix, but you always need to enable the feature by setting a registry key.

So what is the problem with CNAME dns records and Kerberos?
A CNAME dns record is an alias to another dns record. So it doesn't point to an IP address but to another record. 
Let's say vanity.domain.com is a CNAME for server123.domain.com which is a HOST A record for 1.2.3.4.
Something like: vanity.domain.com -> server123.domain.com -> 1.2.3.4

When you go to the url http://vanity.domain.com you would expect you will request a Kerberos ticket for http/vanity.domain.com, but because it's a CNAME most applications (like IE) will try to get a ticket for http/server123.domain.com.
So if you didn't have the spn http/server123.domain.com registered to the application pool identity it will fail the authentication.

Register the spn to the machinename and finished right?
Well most of the time it's not that simple. If you have multiple websites with each have it's own CNAME dns name pointing to the same hostname and they are using different application pool identities than this will not work. A SPN must be registered to one and only one account. If you have the SPN registered to Account A and request a ticket for that SPN, it will be encrypted by the password hash of Account A. So when your application pool identity is Account B it will receive the ticket from the client, but it can't decrypt it, because it is encrypted with the password hash of Account A and not of Account B.

The KB articles mentioned above will change this behaviour for Internet Explorer. So when you have a CNAME it will request a SPN for that CNAME.
This is a client fix, you need to deploy this to all your clients within the organisation. And note that it will only fix Internet Explorer! Other webclients might not pick this up
Also does this fix not work anymore on Windows 7 with IE8. So IE8 shows the original behaviour. (Microsoft might have changed the way to turn this on. To be honest I haven't looked for a new way. But I did confirm that the way mentioned in the KB articles doesn't work anymore.)

 

KB908209

This KB908209 article is about fixing Wininet to include the port number when requesting a Kerberos ticket. This is also a client fix and you need to specify in the registry which application should get the new behaviour.
An SPN consists of 3 parts: a service class (http, mssqlsvc, host, etc.) part, a hostname part and an optional port part. If you are using default ports, you don't specify the port.

So if you are running an application on a non default port, for example: http://intranet.domain.local:81 which runs on port 81, you would expect you to register the SPN http/intranet.domain.local:81, which is how you should do it according to the specifications, however Internet Explorer will not request a ticket for that SPN. It ignores the port part and requests it for http/intranet.domain.local which is a different spn and will lead to failed Kerberos authentication.

Then why not register it also without the port part?
This will not work when you have multiple websites running on the same hostname but with different port numbers and using different application pool identities. Because of the same reasons mentioned in the other KB articles above. (See section: Register the spn to the machinename and finished right?)

 

Why aren't these KB articles the solution?

 Let's go back to my dicussion with my customer:

Me: "Do not use CNAME dns records and non default web ports when using Kerberos!"
Customer: "Yeah, we know that. But we have implemented KB911149, KB938305 and/or KB908209 (and maybe even some others) on all our desktops. So we shouldn't have a problem."
Me: "First: You have to deploy that to all your desktops. I rather have a server side fix. But second: it will only fix Internet Explorer (CNAME issue) and some WinInet applications (non default ports issue) including IE."
Customer: "We only use Internet Explorer and no other browsers and everyone is using the same version. So what's the problem?"
Me: "The problem is that you think that Internet Explorer is your only client!"

Be aware here that I usually operate in SharePoint environments. It might be different when dealing in other ecosystems.
With SharePoint we are not dealing with Internet Explorer only. But also with Office Applications, SharePoint designer, WebDAV Redirector, etc. Some of these applications will not be fixed with above articles. But there is even another very import framework that doesn't get fixed by this: The .NET Framework!!!

Every .NET application that does a webrequest to a Kerberos enabled website will not be influenzed by these KB articles. And the .Net framework has the same problems: In most scenario's it doesn't use CNAME records to request SPN's and it will never use the port numbers in the SPN request.

Customer: "But we don't have 3rd party applications or even custom .Net applications! So we are ok, right?"

SharePoint itself was build on the .NET framework. So when you are using Excel Services,SharePoint integrated Reporting Services (with integrated security), RSS Viewer Webpart to view authenticated RSS feeds from different SharePoint farms or from the same farm in a loadbalanced scenario you will run into these problems. Also scenario's where commercial applications written in .NET are connected to SharePoint like for instance K2 workflow will have these problems. And most customers at one point will use tools that will use the webservices of SharePoint and usually those are build in .NET as well.

 

Are you sure that the .Net Framework are not effected by these KB articles?

Yep. All web requests in .NET will use the System.Net.WebRequest class or descendant classes eventually. This class will not use the WinInet functions to request a Kerberos ticket, but will call the InitializeSecurityContext function and related functions from secur32.dll directly. One of the parameters of that function is pszTargetName. When Kerberos is used that parameter is used to pass the SPN to the function.

So where does the .Net Framework get the SPN from? 
It will get that from the method GetComputeSPN(HttpWebRequest httpWebRequest)  of the class System.Net.AuthenticationState, which is an internal class. That method will build the SPN based on the HttpWebRequest. There are however 3 distinct code paths that will return different SPN's based on input like: is the url a CNAME or HOST A, do we use a proxy server and is the url a Fully Qualified Domain Name (FQDN).

Below is the source code of this function in version 3.5 of .NET (latest version) to show the different paths. (Thanks to source code tracing of .Net Framework code in Visual Studio Big Smile)
The 3 paths are:

  1. Not using a proxy server.
  2. Using a proxy server and the Url of the request is an IP Address (e.g.: http://1.2.3.4) or  a FQDN (e.g.: http://portal.mb.local)
  3. Using a proxy server and the Url of the request is a short name (e.g.: http://portal)
     

 

Each of these 3 code path's uses a different assignment of the returning spn value:

1 (red): spn = httpWebRequest.ServicePoint.Hostname;
2 (blue): spn = httpWebRequest.ChallengedUri.Host;
3 (yellow): spn = Dns.InternalGetHostByName(spn).HostName;

Path 1 and 3 will NOT USE the CNAME. They do a GetHostByName to get the name the CNAME is pointing at. (You can't see it here that path 1 is using a GetHostByName, but this is done in another function)
Path 2 however DOES USE the CNAME.

So below table will summarize which SPN's are created based on the parameters: FQDN, Proxy, CNAME

Url

DNS Type

Using Proxy

Code Path

SPN

http://portal.mb.local

HOST A

No

1

http/portal.mb.local

http://portal.mb.local

HOST A

Yes

2

http/portal.mb.local

http://portal.mb.local

CNAME

No

1

http/hostname.mb.local

http://portal.mb.local

CNAME

Yes

2

http/portal.mb.local

http://portal

HOST A

No

1

http/portal.mb.local

http://portal

HOST A

Yes

3

http/portal.mb.local

http://portal

CNAME

No

1

http/hostname.mb.local

http://portal

CNAME

Yes

3

http/hostname.mb.local

 

So from above code and table we can at least conclude a few things for the .Net framework:

  • Ports are never used to generate the SPN! Always uses default ports.
  • Short names in URL's lead to FQDN names in the SPN!
  • If you are using a CNAME it will create a SPN for the hostname, unless you are using a FQDN and a proxy server, than it will use the CNAME!

The last point from above list is also the reason why CNAMES sometimes work when they have a proxy server configured, Internet Explorer has the same behaviour! That's also the reason why you shouldn't use Fiddler to debug Kerberos problems, cause it changes the behavour, since Fiddler register itself as a Proxy Server within WinInet. Use a network sniffing tool like the great Network Monitor from Microsoft.


Conclusion

If you use CNAMES and non default ports for web applications you have to be aware of the different behaviours of the different applications. You usually end up doing a lot more configuration and patching clients and servers and having more complex environment. And still it can go *boom* when you introduce new versions or new applications.

When you use HOST A records and default ports all the applications have the same behaviour and your life as administrator just became easier.


Posted 11-14-2009 10:26 PM by Michel Barneveld

Comments

Donald wrote re: The reason why KB911149 and KB908209 are not the solution!
on 04-05-2010 11:27 PM

Nice article! I agree on not using non default ports, although it should be fixed in .Net Framework 3.5 SP1. See blog of spencer www.harbar.net/.../crawling-kerberos-web-applications-on-non-default-ports.aspx

Michel Barneveld wrote re: The reason why KB911149 and KB908209 are not the solution!
on 04-06-2010 10:06 PM

Hi Donald,

thanks for pointing me to that information. I took a look on how it was implemented and unfortunately Microsoft didn’t fix the .Net framework on SPN generation. The default implementation is still not using high ports. So everything that uses the System.Net.WebRequest (like the RSS Viewer webpart, old style asmx webservice proxies, custom .net code to fetch web data, etc.) by default will not use ports in the spn generation. However there is a way to work around this: the System.Net.AuthenticationManager has a CustomTargetNameDictonary that is used to map URIs to SPNs. The GetComputeSpn method of System.Net.AuthenticationManager will first check the dictionary for an entry and use that spn, before it computes a spn (without port number). So the work around is to fill that dictionary with your custom SPN (for instance with a different service class or using a high port) for a specific URI, before doing a webrequest to that URI.

SharePoints Shared Services (SSP) like Excel Services, Search, etc. uses above work around mechanism combined with a new SPN Service Class: MSSP (format: MSSP/<host:port>/<SSP name>), to be able to use SSPs on high ports with Kerberos. (See also technet.microsoft.com/.../cc263449.aspx for more information on this MSSP spns)

So yes, it is fixed for SharePoint to use Kerberos with SSPs on high ports. (SSP only, this doesn’t fix normal web apps on high ports using Kerberos). But this isn’t fixed for the whole .Net framework. The only possible exception I haven’t tested yet is WCF. From reflection it looks like certain WCF scenario’s are also using this workaround. Looks like a nice investigation opportunity for a next blog posting ;-)

Peter wrote re: The reason why KB911149 and KB908209 are not the solution!
on 10-21-2011 6:22 PM

Do you know if this is fixed in .NET Framework 4.0?

Is it in the fix for .NET Framework 4.5?

youtube html5 player wrote re: The reason why KB911149 and KB908209 are not the solution!
on 05-09-2012 1:13 PM

Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again.

Eric Lawrence wrote re: The reason why KB911149 and KB908209 are not the solution!
on 04-25-2013 12:32 AM

Great post, thanks for sharing your findings and explaining the status so clearly.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

  Enter code:
Copyright © 2003 - 2009 Michel Barneveld
Powered by Community Server (Non-Commercial Edition), by Telligent Systems