Skip to content

Instantly share code, notes, and snippets.

@bollwyvl
Created July 29, 2009 20:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save bollwyvl/158364 to your computer and use it in GitHub Desktop.
Save bollwyvl/158364 to your computer and use it in GitHub Desktop.
A Python port of Perl's Apache::AuthenMSAD
"""
authen_msad
A port of Perl's Apache::AuthenMSAD
Takes advantage of Microsoft Active Directory allowing a user to be verified
with 'user@domain' instead of searching for the distinguished name.
To merge as seamlessly as possible with existing systems (i.e. SharePoint,
etc.) munge the incoming "domain\user" into "user@domain".
Implementations for both mod_wsgi and the deprecated mod_python are included.
"""
import ldap
def authenhandler(req):
"""
This function gets called by mod_python.
Sample httpd.conf entry:
<Location /directory.to.protect/>
AddHandler mod_python .py
PythonHandler authen_msad
PythonAuthenHandler authen_msad
PythonOption authen_msad.ldap_url ldap://<server ip address>:1234/
AuthType Basic
AuthName "This Content is Protected"
require valid-user
</Location>
"""
from mod_python import apache
try:
password = req.get_basic_auth_pw()
domain, user = req.user.split("\\")
ldap_url = req.get_options().get("authen_msad.ldap_url")
except:
return apache.HTTP_UNAUTHORIZED
return msad_check_user(user=user,
domain=domain,
password=password,
ldap_url=ldap_url,
errors={
ldap.INVALID_CREDENTIALS: apache.HTTP_UNAUTHORIZED,
ldap.SERVER_DOWN: apache.HTTP_EXPECTATION_FAILED
})
def check_password(environ, user, password):
import os
"""
This is the handler used by mod_wsgi.
Sample httpd.conf entry:
<Location /directory.to.protect/>
AuthType Basic
AuthName "This Content is Protected"
Require valid-user
AuthBasicProvider wsgi
WSGIAuthUserScript /path/to/authen_msad.py
SetEnv authen_msad.ldap_url ldap://<server ip address>:1234/
</Location>
"""
try:
domain, user = user.split("\\")
ldap_url = os.environ["authen_msad.ldap_url"]
except:
return None
return msad_check_user(user=user,
domain=domain,
password=password,
ldap_url=ldap_url,
errors={
ldap.INVALID_CREDENTIALS: None,
ldap.SERVER_DOWN: None
})
def msad_check_user(user, domain, password, ldap_url, errors={}):
"""
The bit that actually talks to the ActiveDirectory server.
"""
try:
ldap_client = ldap.initialize(ldap_url)
ldap_client.simple_bind_s("%s@%s" % (user, domain), password)
return True
except ldap.INVALID_CREDENTIALS:
return errors.get(ldap.INVALID_CREDENTIALS, None)
except ldap.SERVER_DOWN:
return errors.get(ldap.SERVER_DOWN, None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment