Legrandin / PyAuthenNTLM2

PyAuthenNTLM2 is an authentication module for Apache. It validates a user by means of the NTLM protocol and a separate Domain Controller (or Active Directory server).
Other
57 stars 42 forks source link

PyAuthenNTLM2 is an authentication module for Apache.

It validates a user by means of the NTLM protocol and a separate Domain Controller (or Active Directory server).

Introduction

The specific use case of PyAuthenNTLM2 is the following:

PyAuthenNTLM2 allows clients to authenticate via two schemes: NTLM or Basic.

As for several other authorization modules, PyAuthenNTLM2 will pass the username to the underlying CGI application or webservice via the REMOTE_USER variable. The user name is the Windows logon identifier, without the domain part (that is, jdoe and not DOMAIN\jdoe or John Doe).

Security

Although Kerberos (including its Microsoft variant "Integrated Windows Authentication") is the best option in terms of security for HTTP authentication, the venerable NTLM protocol is still a good compromise, much better than the widespread Basic protocol and marginally better than Digest. With Basic, anybody can pick up your password from the messages sent to the server (unless you use TLS), whereas with Digest the web server needs local access to the actual password. With NTLM, the webserver can relay every authorization requests to the (Domain Controller or Active Directory server): it never has to neither see nor store the real passwords.

A typical message flow is the following. First, the server (Apache) refuses any request on a new connection: ::

Client ----[GET]---> Apache Client <---[401]---- Apache , WWW-Authenticate: NTLM

The client crafts a first NTLM message to negotiate the authentication parameters. Such message (Type 1) is relayed straight to the Domain Controller: ::

Client ----[GET]---> Apache , Authorization: TlRMT... (Type 1 message) Apache ----[Type 1]---> DC

The Domain Controller generates a random challenge, completes the negotiation, and sends back the message. The message (Type 2) is relayed to the client: ::

                  Apache <---[Type 2]---- DC

Client <---[401]---- Apache , WWW-Authenticate: NTLM TlRMT... (Type 2 message)

The client presents the popup dialog to the user to acquire the credentials. The password is only used to encrypt the challenge. The resulting message (Type 3) is relayed to the Domain Controller, which will communicate to the server if the user is authentic or not: ::

Client ----[GET]---> Apache , Authorization: TlRMT... (Type 3 message) Apache ----[Type 3]---> DC Apache <---[Result]---- DC Client <---[200]---- Apache

The password is never disclosed by the client. However, several versions of NTLM exist. NTLMv1 is based on cryptography that by today standards is very weak. That means that the password can be still brute forced from the encrypted challenge. In order to avoid that, ensure that your clients always use NTLMv2 [1]_.

PyAuthenNTLM2 handles equally well all the various NTLM variants (such as NTLMv2 Session, and NTLMv2).

.. _[1]: http://support.microsoft.com/kb/239869

Requirements

.. _[2]: http://www.modpython.org

Tests were carried out with:

Installation

::

python setup.py install -f

Usage

Usage is best shown by an example of Apache configuration: ::

<Directory /var/lib/some_directory>

AuthType NTLM
AuthName WDOMAIN
require valid-user

PythonAuthenHandler pyntlm
PythonOption Domain WDOMAIN
PythonOption PDC 192.1.2.45
PythonOption BDC 192.1.2.46

# Bypass authentication for local clients.
# Comment these lines if they should authenticate too.
Order deny,allow
Deny  from all
Allow from 127.0.0.1
Satify any

All non-local clients trying to access a URI mapped under the directory /var/lib/some_directory will be asked for credentials valid in the Windows Domain WDOMAIN. The user name to enter need to be in the format: wdomain\useridentifier (for instance windom\jbrown).

Local clients (that is, those connecting from 127.0.0.1) will not be presented with any request for authentication.

The following options exist:

===================================== ====== Apache option Description ===================================== ====== AuthType NTLM Always specify it like this.
Require valid-user Always specify it like this. Require user XYZ,WTY | Grants access only to users named XYZ or WTY. | Multiple "Require user" option lines can be specified. AuthName domain Replace domain with the domain name to present to users in the pop-up dialog. PythonAuthenHandler pyntlm|path Use simply pyntlm, unless the actual pyntlm.py script is not in the search path for python for the mod-python interpreter. In that case, specify the complete file name (with absolute path) to the script. PythonOption Domain domain Replace domain with the Windows domain name (uppercase). PythonOption PDC pdc Replace pdc with the address of the Primary Domain Controller (either IP or DNS name). PythonOption BDC bdc Replace bdc with the address of the Backup Domain Controller (either IP or DNS name). This entry is optional. PythonOption NameFmt SAM|LogOn Set REMOTE_USER to the user name only (SAM) or to the legacy Logon format (domain\username). This entry is optional. SAM is the default. ===================================== ======

Apache needs to be configured to send keep alives (directive KeepAlive On).

For SSL-protected sites, comment out the statement: ::

SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

from the default Apache virtual host, or Internet Explorer will not manage to make use of NTLM.

Experimental

The [pdc]/[bdc] settings may also refer to an Active Directory server. The syntax becomes slightly more complex:

ldap://server[/baseDN]

where server is the IP or DNS name of the Active Directory server, and the optional baseDN is the base Distinguished Name for the queries (only needed for authorization, see below). For instance:

ldap://10.12.13.1/DC=nasa,DC=gov

or equivalently (but more in compliance to RFC4516):

ldap://10.12.13.1/DC%3Dnasa%2CDC%3Dgov

When using an Active Directory server, it is also possible to check if the user is authorized to access page. More precisely, it is possible to grant access only if the user is member of one group.

The option Require group can be used to pass the comma-separated list of groups the user must belong to. The group identifier is the logon name, that is, the sAMAccountName attribute in Active Directory.

The check is performed iteratively. In other words, the check is successful if the user belongs to a group with the given name, or to a sub-group (of any order, up the hierarchy) who belongs to the sought group.

For instance, if you specified: ::

<Directory /var/lib/some_directory> [ ... ] Require group Administrators,Power Users [ ... ]

Only users that belong to Administrators or Power Users will be granted access. If the user belonged to a sub-group of Power Users called Super Power Users, they would pass the check too. A user that does not belong to any of such groups is denied access, even if its credentials were correct, unless its name is included in a Require user option.

Caching

NTLM is a protocol that authenticates TCP connections, not the individual request like Basic or Digest.

PyAuthenNTLM2 does not cache successful autentications. Every time a new connection is established, you will see a query to the Domain Controller or Active Directory from Apache. Browsers will typically open several connections in parallel. Additionally, some browsers may also trigger re-autentication within an established connection (e.g. Internet Explorer for POST requests).

However, at the client side, browsers will do cache NTLM credentials, which won't be asked again to ther user after the first time (which is the whole point of Single Sign On!).

PyAuthenNTLM2 will cache positive group membership for 3 hours. That means that if you remove a user from a group, such user will still be able to access for up to 3 hours, unless you restart Apache. On the other hand, if you add the user to a group, access should be granted immediately.

Logging

All logs will show up in the Apache log file.

Troubleshooting

Check list:

.. _[3]: http://roadzy.blogspot.com/2011/02/finding-your-base-dn-in-active.html

Thanks

| Microsoft for the large amount of technical specifications about NTLM and SMB it disclosed [4] . See also [5]. | Eric Glass for his long article about NTLM [6] . In several ways, it is more complete and precise than [4] . | Gerald Ritcher and Shannon Eric Peevey for AuthenNTLM [7]_ , which inspired this module.

.. [4]: http://msdn.microsoft.com/en-us/library/gg258393%28v=PROT.13%29.aspx .. [5]: http://technet.microsoft.com/en-us/magazine/2006.08.securitywatch.aspx .. [6]: http://davenport.sourceforge.net/ntlm.html .. [7]: http://search.cpan.org/~speeves/Apache2-AuthenNTLM-0.02/AuthenNTLM.pm

Contacts

Send an email to Legrandin helderijs@gmail.com or drop a message at https://github.com/Legrandin/PyAuthenNTLM2.