Created
June 2, 2015 19:40
-
-
Save maxicecilia/ab3bb3dcf697f15554e6 to your computer and use it in GitHub Desktop.
LDAP BE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This was modified from the original version posted here: | |
# | |
# http://www.carthage.edu/webdev/?p=12 | |
# | |
# ... retrieved around 1/12/2008. | |
# | |
# Modifications include: | |
# | |
# 1. Using a simple bind for auth instead of a search | |
# 2. Upping the default privileges for users | |
# 3. Modifying the required "constants" and moving them into settings.py | |
# 4. Extending ModelBackend "just in case" | |
# 5. Verifying that the username is all word chars before passing | |
# it off to the LDAP API | |
import ldap, re, logging | |
from django.conf import settings | |
from django.contrib.auth.models import User | |
import django.contrib.auth.backends | |
# Constants | |
# | |
# Load them from settings if you can. Error if you can't. | |
# Sample values are provided for reference. | |
# AUTH_LDAP_SERVER = "localhost" | |
# AUTH_LDAP_USER_DN_FORMAT = "uid=%s, ou=people, dc=nationalgeographic, dc=com" | |
AUTH_LDAP_SERVER = settings.AUTH_LDAP_SERVER | |
AUTH_LDAP_BACKUP_SERVER = settings.AUTH_LDAP_BACKUP_SERVER | |
AUTH_LDAP_USER_DN_FORMAT = settings.AUTH_LDAP_USER_DN_FORMAT | |
AUTH_LDAP_SUPERUSER_BY_DEFAULT = settings.AUTH_LDAP_SUPERUSER_BY_DEFAULT | |
class LDAPBackend(django.contrib.auth.backends.ModelBackend): | |
def authenticate(self, username=None, password=None): | |
# Disallow anonymous logins by require a non-empty password. | |
# | |
# Experimental testing shows that non-empty, all whitespace | |
# passwords fail as expected. | |
if password == "": | |
return None | |
# Do some validation on the username... it should | |
# be all word chars. | |
# | |
# TODO Does django already sanitize this for us? | |
if re.compile("^[-_\w\d]+$").match(username) == None: | |
logging.error("Username isn't valid (not a combination of -, _, numbers and letters)") | |
return None | |
try: | |
l = ldap.open(AUTH_LDAP_SERVER) | |
except ldap.CONNECT_ERROR, e: | |
logging.warning("Connect to main ldap server (%s) failed." % (AUTH_LDAP_SERVER)) | |
try: | |
l = ldap.open(AUTH_LDAP_BACKUP_SERVER) | |
except ldap.CONNECT_ERROR, e: | |
logging.warning("Connect to backup ldap server (%s) failed." % (AUTH_LDAP_BACKUP_SERVER)) | |
return None | |
# Authenticate the base user so we can search | |
try: | |
dn = AUTH_LDAP_USER_DN_FORMAT % username | |
logging.debug("Trying to bind to ldap server as %s" % (dn)) | |
l.protocol_version = ldap.VERSION3 | |
l.simple_bind_s(dn, password) | |
# If we error, we return None and fail to authenticate. | |
except ldap.INVALID_CREDENTIALS: | |
# Name or password were bad. Fail. | |
return None | |
except ldap.LDAPError, e: | |
logging.error("Got an LDAP error on binding %s: %s" % (username, e)) | |
return None | |
# Now use search to get the user's email address | |
try: | |
baseDN = "ou=people,dc=nationalgeographic,dc=com" | |
filter = 'uid=%s' % username | |
attrs = ["uid", "mail"] | |
records = l.search_s(baseDN, ldap.SCOPE_SUBTREE, filter, attrs) | |
except: | |
return None | |
if len(records) != 1: | |
# search failed | |
return None | |
uid_string, uid_attrs = records[0] | |
# logging.debug("Extracting LDAP record: %s, %s" % (uid_string, uid_attrs)) | |
if 'mail' in uid_attrs: | |
email_addr = uid_attrs['mail'][0] | |
else: | |
email_addr = '' | |
l.unbind() | |
### logging.debug( "Trying to fetch or create user..." ) | |
try: | |
# The user existed and authenticated. | |
# Get the user record or else create one. | |
# | |
# Users created here will always need to provide their LDAP | |
# password. Invoking set_unusable_password() ensures that. | |
# | |
# Note that since the user isn't written to the db | |
# until after we set the unusable password, there's | |
# no race condition here where a malicious visitor | |
# could sneak in. | |
user = User.objects.get(username__exact=username) | |
except: | |
user = User.objects.create_user(username, email_addr, "stub password") | |
user.set_unusable_password() | |
# Due to our policy of trusted users, we currently default | |
# new accounts to staff if they are in LDAP. | |
# | |
# This is will eventually be replaced with a permissions | |
# scheme where ldap attribs will control application permissions. | |
user.is_staff = True | |
if AUTH_LDAP_SUPERUSER_BY_DEFAULT: | |
user.is_superuser = True | |
user.save() | |
# Success. | |
return user | |
def get_user(self, user_id): | |
try: | |
return User.objects.get(pk=user_id) | |
except User.DoesNotExist: | |
return None |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment