MaxTokenSize und seine Freunde

Hallo, hier wieder mal Rol mit einem Beitrag zum Troubleshooting und Verständnis von Kerberos MaxTokensSize.

Hintergrund ist ein relativ aktueller Case, welchen wir in unserem Team arbeitet haben. Ein Sharepoint Kollege hatte uns hinzugezogen, da er für einen Benutzer (in unserem Beispiel ganz zufällig der FABIAN)  beim Kunden kein gültiges Ticket vom KDC bekommen konnte. Für die entsprechenden IIS Webseite konnte der SPN HTTP/SPSite.contoso.com im Tool KerbTray nicht entdeckt werden, andere Tickets waren aber vorhanden. Bei anderen Usern klappte das gleiche aber tadellos.

Ein Netzwerk Trace konnten wir bekommen. Das haben wir uns angesehen, und zwar mit dem Netmon 3.3 unter Verwendung der Menü Funktion “Reassemble” (welche dann eine neues Analyse-Fenster öffnet), damit der Parser alle zusammenhängende Pakete verarbeitet und nicht nur das erste Paket untersucht.
Das ist übrigens generell für viele Protokolle eines wichtiges Vorgehen, wenn der Protokollheader hehr als das erste Paket umfassen kann. Bei Kerberos z.B. wird nur so der angeforderte SPN sichtbar.

Im Trace konnte man den Ticket Request von User FABIAN schon sehen:
Client TGS Request

202 15:40:15 14.05.2010 10.10.10.1 10.20.20.1 KerberosV5 KerberosV5:TGS Request Realm: CONTOSO.COM Sname: HTTP/spsite.contoso.com

KDC TGS Response

204 15:40:15 14.05.2010 10.20.20.1 10.10.10.1 KerberosV5 KerberosV5:TGS Response Cname: FABIAN

Eine Antwort hatte er also bekommen, nur war diese nicht in den Ticket Cache gewandert. Interessant ist noch, daß in der TGS Response die Gesamtlänge der Antwort in Frame 204 schon recht groß ist:

Kerberos: TGS Response Cname: FABIAN
Length: Length = 10699

Vergleicht man das mit den funktionieren Zugriff von Benutzer FLORIAN, dann sieht das bei dem ganz anders aus:

292 15:42:15 14.05.2010 10.10.10.2 10.20.20.1 KerberosV5 KerberosV5:TGS Request Realm: CONTOSO.COM Sname: HTTP/spsite.contoso.com 294 15:42:15 14.05.2010 10.20.20.1 10.10.10.2 KerberosV5 KerberosV5:TGS Response Cname: FLORIAN Length: Length = 2880

Noch interessanter wird es, wenn man sich dann noch den HTTP GET Request des Benutzers FABIAN ansieht. Hier fehlt jeglicher Authorization Teil im HTTP Header in Frame 210:

210 15:40:15 14.05.2010 10.20.20.1 10.30.30.3 HTTP HTTP:Request, GET /
211 15:40:15 14.05.2010 10.30.30.3 10.20.20.1 HTTP HTTP:Response, HTTP/1.1, Status: Unauthorized, URL: / Using Multiple Authentication Methods
StatusCode: 401, Unauthorized

Im Gut-Fall von FLORIAN kann man hingegen beim HTTP GET den Authorization Teil mit Negotiate für Kerberos deutlich sehen:

301 15:42:15 12.05.2010 10.20.20.2 10.30.30.3 HTTP HTTP:Request, GET / , Using GSS-API Authorization Authorization: Negotiate

Das erhaltene Ticket konnte also nicht im Ticket Cache gehalten und somit auch nicht vom Internet Explorer für den Zugriff auf die Webseite verwendet werden. Ausschlaggebend ist offensichtlich die Größe des vom KDC erhaltenen Tickets.

Kerberos Client Setting MaxTokenSize

Spätestens zu diesem Zeitpunkt kommt jetzt das Setting MaxTokenSize ins Spiel. Aber was steckt eigentlich hinter dieser Einstellung?
MaxTokenSize definiert hierbei den Empfangspuffer für die Antworten vom KDC über direkte und vererbte Gruppenmitgliedschaften (SIDs). Aus diesem Puffer wiederum bezieht LSASS über den Kerberos Client die Ticket Informationen für den entsprechenden User oder Computer Kontext. Paßt die KDC Antwort nicht in den Puffer, kann LSASS das entsprechende Ticket dann auch nicht für einen Ressourcenzugriff zur Verfügung stellen. Warum der Registry Wert nicht “MaxTicketSize” heißt, liegt an einer gewollten Entscheidung unserer Entwickler. Der Empfangspuffer hat eine bestimmte Struktur, also kein flacher Speicherbereich, bei dem intern schon von Token gesprochen wird. Diese Struktur ist auch dafür verantwortlich, daß man MaxTokenSize nicht auf das Byte genau berechnen kann. Daher sind die Vorgehen zur Bestimmung von MaxTokenSize, wie sie z.B. sehr gut im Artikel

327825    New resolution for problems with Kerberos authentication when users belong to many groups
https://support.microsoft.com/default.aspx?scid=kb;EN-US;327825

dargestellt werden, nur als grober Richtwert zu verstehen. Ansonsten ist der Artikel aber mit die beste Referenz zu MaxTokenSize.
In unserem Beispiel hatten jedenfalls die erhalten Gruppenmitgliedschaften (über SID Informationen) in der 10699 Bytes KDC Antwort nicht in den Default Puffer von 12000 Bytes gepaßt.
Im Anschluß haben wir dann auf dem Client MaxTokenSize auf den empfohlenen Maximalwert von 65535 gesetzt:

HKLM\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters, MaxTokenSize (REG_DWORD) = 65535 (dezimal)

Und siehe da, nach dem Neustarten des Clients - ging’s immer noch nicht! Hmm…

Serverseitige Anpassung an MaxTokenSize

Warum jetzt das? Nun, ein Blick in ein neues Netmon Trace hat es gezeigt! Diesmal ist im HTTP GET “Authorization: Negotiate enthalten, jedoch kommt nun der IIS nicht damit zurecht:

314 13:14:37 18.05.2010 10.10.10.1 10.20.20.1 HTTP HTTP:Request, GET / , Using GSS-API Authorization PayloadHeader: Reassembled Protocol=TCP, FrameCount=12,Length=17343 318 13:14:37 18.05.2010 10.20.20.1 10.10.10.1 HTTP HTTP:Response, HTTP/1.1, Status: Bad request, URL: /
HtmlElement: Bad Request (Request Header Too Long)

Hier ist die IIS Antwort nun relativ aussagekräftig. Der GET Request Header ist dem IIS mit 17343 Bytes zu groß. Er kann per Default nur 16k annehmen.
Nach Rücksprache mit unseren IIS Kollegen und der Referenz aus Artikel
920862  Error message when an Outlook Web Access user tries to access a mailbox in Exchange Server 2003: “HTTP 400 Bad Request (Request header too long)”
https://support.microsoft.com/default.aspx?scid=kb;EN-US;920862

For IIS 6.0 (Microsoft Windows Server 2003), the MaxFieldLength entry and the MaxRequestBytes entry are found under the following registry subkey. Configure them as shown in the following table.
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters]
(DWORD)"MaxFieldLength"= 65534
(DWORD )"MaxRequestBytes"=500000
 

haben wir dann die Anpassung für IIS vorgenommen. Nach dem Stoppen und Starten des IIS Dienstes konnte nun der IIS den großen Ticket Blob aus FABIANs HTTP GET Request erst verarbeiten und ein valides Token für den Zugriff bilden.

MaxTokenSize sollte im übrigen immer konsistent auf allen potentiellen Kerberos Clients im Forest gesetzt werden, also auch auf Servern und DCs. Der optimale Weg ist über Policies, gemäß
938118    How to use Group Policy to add the MaxTokenSize registry entry to multiple computers
https://support.microsoft.com/default.aspx?scid=kb;EN-US;938118

 

Ich hoffe der Blog macht deutlich wie Kerberos mit MaxTokenSize auf der Clientseite funktioniert, aber auch wie es sein kann, daß auch die Serverseite angepaßt werden muß. IIS ist hier meines Wissens schon fast eine Ausnahme. Andere Server Applikationen können per Default problemlos mit dem empfohlenen Maximalwert von 65535 Bytes umgehen. Sollten Applikationen nicht damit zurechtkommen, so wird dies Microsoft intern als Design Problem angesehen.

Damit einen guten Start in den hoffentlich deutlich sonnigeren Juni!
Euer Rol