Errores 401 en IIS al habilitar la autenticación de Windows integrada

Hoy quería escribir sobre caso en el que trabajé hace unas semanas, no por la complejidad del problema, si no por mostrar un ejemplo de cómo abordar un problema y qué herramientas utilizar cuando no tienes ni idea de por dónde van los tiros. Los datos iniciales que tenía del problema era que el cliente tenía un portal de SharePoint en el que todas las páginas le daban errores HTTP 401 si habilitaba la autenticación de Windows integrada. Si configuraba autenticación básica o acceso anónimo los portales funcionaban correctamente.

Mi primera hipótesis fue que probablemente los errores se debían a un problema en la configuración de Kerberos, pero pronto descubrí que tenían configurada únicamente la autenticación por NTLM. Kerberos estaba deshabilitado en la configuración de IIS:

C:\Inetpub\AdminScripts>cscript adsutil.vbs get W3SVC/1/NTAuthenticationProviders

Microsoft (R) Windows Script Host Version 5.6

Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

NTAuthenticationProviders : (STRING) "NTLM"

Puesto que no tenía ni idea de cuál podría ser la causa de este comportamiento, le pedí los siguientes logs al cliente:

· La metabase de IIS (en Windows Server 2003 se encuentra en la siguiente ruta: %WINDIR%\system32\inetsrv\metabase.xml).

· Los logs de IIS.

· Unas trazas de red capturadas mientras reproducían el error.

Examinando los logs de IIS veíamos los errores HTTP 401, pero no arrojaban luz sobre el origen del problema:

#Fields: date time s-sitename … sc-status sc-substatus sc-win32-status

2009-09-16 14:37:46 W3SVC1 … 401 2 2148074254

2009-09-16 14:37:46 W3SVC1 … 401 1 0

Yo esperaba encontrar alguna pista al menos a partir del estado win32, pero el estado 2148074254 (No credentials are available in the security package) en la primera petición es esperado (ver el siguiente post para más detalles), y en la segunda petición el resultado era 0 (The operation completed successfully). Y lo más extraño de todo, es que no se registraba una tercera y última petición para finalizar la secuencia de autenticación como sería lo normal (de nuevo, ver el post al que hacía referencia antes).

Analizando las trazas de red veíamos la secuencia de peticiones habitual durante el handshake NTLM, pero cuando el cliente hace la petición final autenticada (en el frame TCP 5004), en el siguiente frame TCP el cliente cierra la conexión TCP deliberadamente ([FIN, ACK]) y por tanto la respuesta del IIS nunca llega.

No. Time Source Dest. Prot. Info

---- --------------- -------- -------- ----- --------------------------------------------------

4503 16:09:05.973298 [CLIENT] [SERVER] TCP timeflies > 8010 [SYN] Seq=0 Win=65535 Len=0 MSS…

4504 16:09:05.973298 [SERVER] [CLIENT] TCP 8010 > timeflies [SYN, ACK] Seq=0 Ack=1 Win=1638…

4505 16:09:05.973298 [CLIENT] [SERVER] TCP timeflies > 8010 [ACK] Seq=1 Ack=1 Win=65535 Len…

4506 16:09:05.973298 [CLIENT] [SERVER] HTTP GET / HTTP/1.1

4507 16:09:05.983312 [SERVER] [CLIENT] TCP [TCP segment of a reassembled PDU]

4508 16:09:05.983312 [SERVER] [CLIENT] HTTP HTTP/1.1 401 Unauthorized (text/html)

4509 16:09:05.983312 [CLIENT] [SERVER] TCP timeflies > 8010 [ACK] Seq=441 Ack=1910 Win=6553…

4995 16:09:18.230923 [CLIENT] [SERVER] TCP timeflies > 8010 [FIN, ACK] Seq=441 Ack=1910 Win…

4996 16:09:18.230923 [CLIENT] [SERVER] TCP ndm-requester > 8010 [SYN] Seq=0 Win=65535 Len=0…

4997 16:09:18.230923 [SERVER] [CLIENT] TCP 8010 > timeflies [ACK] Seq=1910 Ack=442 Win=6509…

4998 16:09:18.230923 [SERVER] [CLIENT] TCP 8010 > ndm-requester [SYN, ACK] Seq=0 Ack=1 Win=…

4999 16:09:18.230923 [CLIENT] [SERVER] TCP ndm-requester > 8010 [ACK] Seq=1 Ack=1 Win=65535…

5000 16:09:18.230923 [CLIENT] [SERVER] HTTP GET / HTTP/1.1 , NTLMSSP_NEGOTIATE

5001 16:09:18.240938 [SERVER] [CLIENT] TCP [TCP segment of a reassembled PDU]

5002 16:09:18.240938 [SERVER] [CLIENT] HTTP HTTP/1.1 401 Unauthorized , NTLMSSP_CHALLENGE (t

5003 16:09:18.240938 [CLIENT] [SERVER] TCP ndm-requester > 8010 [ACK] Seq=519 Ack=2082 Win=…

5004 16:09:18.240938 [CLIENT] [SERVER] HTTP GET / HTTP/1.1 , NTLMSSP_AUTH, User: EMEA\daniem

5005 16:09:18.240938 [CLIENT] [SERVER] TCP ndm-requester > 8010 [FIN, ACK] Seq=1221 Ack=208

5006 16:09:18.240938 [SERVER] [CLIENT] TCP 8010 > ndm-requester [ACK] Seq=2082 Ack=1222 Win…

Las trazas de red explicaban el comportamiento, pero seguía sin saber porqué el cliente finalizaba la conexión TCP. Examinando más detenidamente el tráfico HTTP, descubrí que en las respuestas HTTP que devolvía IIS, se estaba incluyendo consistentemente el encabezado "Connection: close”:

HTTP/1.1 401 Unauthorized\r\n

Content-Length: 1539\r\n

Content-Type: text/html\r\n

Server: Microsoft-IIS/6.0\r\n

[truncated] WWW-Authenticate: NTLM TlRMTVNTUAACAAAACAAIADgAAA…

X-Powered-By: ASP.NET\r\n

MicrosoftSharePointTeamServices: 12.0.0.6007\r\n

Date: Wed, 24 Jun 2009 16:09:18 GMT\r\n

Connection: close\r\n

Revisando de nuevo la configuración de IIS (en el fichero metabase.xml), pude confirmar que los Keep-Alives estaban deshabilitados para todo el IIS:

<IIsWebService Location="/LM/W3SVC" AllowKeepAlive="FALSE" ... />

Habilitándolo de nuevo el problema quedaba resuelto y la autenticación NTLM comenzó a funcionar correctamente.

clip_image002

Nota: Esta dependencia de los HTTP Keep-Alives es específica de NTLM y no de la autenticación de Windows integrada en general. La autenticación Kerberos puede funcionar al margen de que se habiliten los Keep-Alives o no.

Para más información, leer el siguiente artículo de TechNet:

401.1 and 401.2-Authentication Problems (IIS 6.0)

https://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/8feeaa51-c634-4de3-bfdc-e922d195a45e.mspx?mfr=true

Espero que os haya sido de utilidad

- Daniel Mossberg