Celé situaci jsem se nevěnoval úplně detailně. Našel jsem příčinu problémů a možná řešení, která jsem využil. Takže tyto informace zde zmíním, pro detailnější informace uvedu nějaké odkazy.
Privilege Attribute Certificate (PAC)
Důležitou informací na počátku je to, že Microsoft rozšířil autentizační protokol Kerberos o autorizační údaje. Ty jsou obsaženy v Privilege Attribute Certificate (PAC) Data Structure [MS-PAC], což je standardní Kerberos Protocol Extensions [MS-KILE]. Klientské Kerberos tickety pak obsahují údaje o členství ve skupinách (seznam skupin, jejichž je uživatel členem), bezpečnostní metadata, informace o politikách, apod.
Popis je u MS v článcích [MS-PAC] a [MS-KILE].
Problém se SSO na webovém serveru
Ozval se mi uživatel, že mu najednou přestalo fungovat Single Sign-On (SSO) na některé webové aplikace. Tyto aplikace běžely na serveru Apache Tomcat nebo Apache HTTP Server. Když se chtěl uživatel přihlásit, tak dostal prázdnou stránku. To bylo proto, že bylo vypnuto zobrazení chybových zpráv na serveru. Když se zobrazení povolilo, tak se zobrazila chyba:
Bad Request Your browser sent a request that this server could not understand. Size of a request header field exceeds server limit. Authorization: Negotiate
Proč k chybě došlo
Když je na webovém serveru pro přístup nastavena Kerberos autentizace, tak server odešle klientovi v http hlavičce tyto údaje (HTTP/1.1 401 Authorization Required, WWW-Authenticate: Negotiate, apod.). Klient získá potřebná data a opět v hlavičce je odesílá na server. Data obsahují Kerberos ticket, který obsahuje údaje o uživateli, což díky [MS-PAC] je také seznam všech skupin, jejichž je uživatel členem. Kerberos ticket je šifrovaný a odesílá se v hlavičce, například Authorization: Negotiate YIIJvwYGKwYBBQUCoIIJszCCCa
(řetězec znaků je v praxi velice dlouhý).
Na aplikačních serverech je defaultně nastavena určitá maximální hodnota, jak může být http request hlavička velká. Pokud klient odesílá více dat (můj uživatel byl členem cca 60 skupin), tak server data nezpracuje a zobrazí výše uvedenou chybu.
Řešení problému
V konfiguraci aplikačního serveru můžeme defaultní hodnotu pro velikost hlavičky změnit. Na Apache HTTP Server je defaultní hodnota 8190 B
. Jinou hodnotu můžeme nastavit v konfiguraci serveru nebo virtual hostu, typicky soubor httpd.conf
, pomocí následující direktivy.
LimitRequestFieldSize 16380
Na Apache Tomcat je defaultní hodnota 8192 B
. Změnit ji můžeme konfigurací na HTTP Connector, tedy elementu Connector
, pomocí atributu maxHttpHeaderSize
. Příklad nastavení:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxHttpHeaderSize="16380" />
Na Internet Information Services (IIS) řeší HTTP požadavky ovladač http.sys
a defaultní hodnota je 16384
. Změnu můžeme provést pomocí registrů, v cestě HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters
vytvoříme DWORD parametry MaxFieldLength
a MaxRequestBytes
, kterým nastavíme požadovanou hodnotu, třeba 48000. Poté je třeba restartovat služby HTTP Service a IIS Admin Service.
Problém s přihlášením na Windows 7
Problémy, s přihlašováním na webové aplikace, se vyřešily dle předchozího popisu. Uběhlo několik měsíců a ozval se znovu ten samý uživatel, že se nemůže dostat na síťové disky. Na jeho stanici jsem zjistil, že dochází k přihlášení ke kešovanému profilu. Můj účet se přihlásil bez problémů a vyzkoušeli jsme jeho účet na jiném počítači, což také prošlo (později se ukázalo, že to bylo díky Windows 8). Usoudil jsem, že je problém v profilu a chtěl jsem vytvořit nový. Zajímavé je, že po smazání původního profilu došlo k přihlášení, ale nový profil se nevytvořil ze síťového (ale z lokálního default), neuplatnili se politiky ani nic dalšího.
Prošel jsem logy událostí a narazil na příčinu. V systémovém logu byl záznam (pouze Warning, očekával bych Error) ze zdroje Security-Kerberos s Event ID 6. Říká, že Kerberos Token je příliš velký a nevejde se do Token Bufferu (který má velikost 12000 B), což je pravděpodobně způsobeno tím, že uživatel je členem příliš mnoha skupin. Dokonce je zde i rada, zmenšit počet skupin nebo změnit velikost bufferu.
Log Name: System Source: Microsoft-Windows-Security-Kerberos Date: 7.1.2014 17:27:14 Event ID: 6 Task Category: None Level: Warning Keywords: Classic User: N/A Computer: POCITAC.firma.local Description: The kerberos SSPI package generated an output token of size 12054 bytes, which was too large to fit in the token buffer of size 12000 bytes, provided by process id 4. The output SSPI token being too large is probably the result of the user uzivatel@FIRMA.LOCAL being a member of a large number of groups. It is recommended to minimize the number of groups a user belongs to. If the problem can not be corrected by reduction of the group memberships of this user, please contact your system administrator to increase the maximum token size, which in term is configured machine-wide via the following registry value: HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\MaxTokenSize.
Řešení problému
Příčina problému je tedy stejná jako v prvním případě, příliš velký Kerberos ticket, protože je uživatel členem příliš mnoha skupin (v tomto případě cca 100). Na OS je jenom trochu větší defaultní velikost (cca 12kB) než na aplikačních serverech (cca 8kB).
V informacích u Windows 7 se uvádí doporučení minimalizovat počet skupin, kterých je uživatel členem. Patrně později MS změnil názor, protože je dnes řada situací, kdy uživatele potřebujeme zařadit do hodně skupin pro autorizaci. Takže limit 12kB, který byl u Windows 7 a předchozích, byl u Windows 8 zvednut na 48kB. Celou situaci pěkně popisuje článek MaxTokenSize and Windows 8 and Windows Server 2012.
Zkusil jsem tedy na stanici přidat do registrů v klíči HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters
položku typu REG_DWORD
s názvem MaxTokenSize
a hodnotou 48000
. Následně je potřeba restartovat stanici.
Ovšem hned po restartu problém u přihlášení přetrvával. Logovaná událost se změnila, ale její znění, že aplikace nepodporuje nastavenou velikost bufferu, mi připadala zvláštní (aplikací jsou Windows).
Log Name: System Source: Microsoft-Windows-Security-Kerberos Date: 10.1.2014 11:09:08 Event ID: 15 Task Category: None Level: Warning Keywords: Classic User: N/A Computer: POCITAC.firma.local Description: The kerberos SSPI package generated an output token of size 13283 bytes, which was too large to fit in the token buffer of size 12000 bytes, provided by process id 4. The application needs to be fixed to supply a token buffer of size at least 48000 bytes.
Po dalším studování informací, například popisu How to use Group Policy to add the MaxTokenSize registry entry to multiple computers, jsem se rozhodl nastavit tuto hodnotu pomocí Group Policy na celou firmu. Po aplikování politiky a restartování již vše začalo fungovat a do logu se žádná chyba nezapsala.
Seznam uživatelů a počty skupin
V souvislosti s popisovaným problémem se může hodit získat výpis uživatelů AD spolu s počtem skupin, kterých jsou členem. Samozřejmě počet skupin není úplně určující, záleží na délce názvů a dalším. To asi nejlépe provedeme pomocí Powershellu.
Get-ADUser -Filter * -SearchBase "OU=Firma,DC=Firma,DC=local" -ResultPageSize 10 | ForEach-Object { $groupc = (Get-ADPrincipalGroupMembership $_.SamAccountName | Measure-Object).Count Write-Host $_.SamAccountName $groupc }
Parametr SearchBase
můžeme využít volitelně, pokud chceme brát uživatele pouze z určitého kontejneru. Parametr ResultPageSize
jsem přidal proto, že jsem při výpisu více uživatelů dostával po zobrazení určitého počtu záznamů následující chybu.
Get-ADUser : The server has returned the following error: invalid enumeration context. At line:1 char:1 + Get-ADUser -Filter * -SearchBase "OU=Firma,DC=Firma,DC=local" | ForEach-Ob ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Get-ADUser], ADException + FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.GetADUser
Zatím zde nejsou žádné komentáře.