#!/usr/bin/env python # allows ldap authentication for ucsc local mirror configurations # this started out as trivial cookie games for local ucsc sessions # ross lazarus me fecit March 15 2007 # TODO: extend to provide public and private sessions # need an authentication scheme # ldap implemented here - YMMV # python login cgi modified from http://webpython.codepoint.net/safer_cgi_shell import os, Cookie, cgi, ldap form = cgi.FieldStorage() # only once! # adjust these to suit your ldap settings AUTH_LDAP_SERVER = 'rockport.bwh.harvard.edu' AUTH_LDAP_BASE_USER = "" # if you need a userid/password to bind AUTH_LDAP_BASE_PASS = "" AUTH_LDAP_BASE = "dc=channing,dc=harvard,dc=edu" AUTH_LDAP_SCOPE = ldap.SCOPE_SUBTREE AUTH_LDAP_FILTER = "(&(objectclass=person) (cn=%s))" # adjust these to suit your hg.conf session settings idCookie = 'MemeUserName' userCookie = 'MemeUserId' debug = 0 # show cookies def getCookies(): ccookies = {} if 'HTTP_COOKIE' in os.environ: hc = os.environ['HTTP_COOKIE'] hcs = hc.split('; ') for c in hcs: cookie = c.split('=') ccookies[cookie[0]] = cookie[1] return ccookies class LDAPBackend: """simple ldap authenticator will fail silently if there are problems with your ldap configuration hard to get a cgi to raise useful errors """ def authenticate(self, username=None, password=None): emessage = '' if username == None: username = '' base = AUTH_LDAP_BASE scope = AUTH_LDAP_SCOPE filter = AUTH_LDAP_FILTER % username if password == '': # don't ever allow empty password strings emessage = 'Empty LDAP passwords are not permitted...' return None,None,emessage # particularly if your ldap server allows anon binds!! try: l = ldap.open(AUTH_LDAP_SERVER) l.simple_bind_s(AUTH_LDAP_BASE_USER,AUTH_LDAP_BASE_PASS) except ldap.LDAPError: emessage = 'Unidentifiable LDAP bind error - bad configuration or LDAP server missing?' return None,None,emessage try: l.search(base, scope, filter) except: return None,None,'Not a known user or bad password (not telling which!)' try: # If the user does not exist in LDAP, Fail. r = l.result()[1] if (len(r) < 1): return None,None # Attempt to bind to the user's DN l.simple_bind_s(r[0][0],password) # since password > '', this will raise INVALID_CREDENTIALS if wrong password uid = r[0][1]['uidNumber'][0] # this will depend on your ldap setup but works for me uname = r[0][1]['uid'][0] return uid,uname,'Login ok' except ldap.INVALID_CREDENTIALS: # Name or password were bad. Fail. return None,None,'Not a known user or bad password (not telling which!)' def header(cookies={}, onload=''): print """\ %s Content-Type: text/html\n \nChanning Local UCSC browser Login \n

Channing Private UCSC Browser Sessions Login

""" % (cookies, onload) def login(form=None,cookies={},dest='/'): """ """ script = os.environ.get('SCRIPT_NAME','/') uname='not defined yet' u = form.getfirst('username', '') p = form.getfirst('password', '') message = 'Enter a valid Channing LDAP user name and password to log in please' if u > '': l = LDAPBackend() uid,uname,emessage = l.authenticate(username=u,password=p) if uid: return uid,uname else: message = emessage onload = """var el = document.getElementById('un'); el.focus(); el.select()""" header(cookies, onload) print """\

%s

Username:

Password:

""" % (message, script, dest, u) return None,None def resume(uname=None,uid=None,dest='/'): """set cookies and return """ # if The user existed and authenticated. set the user cookies for meme hg18 cookies = Cookie.SimpleCookie() cookies[userCookie] = uname cookies[idCookie] = uid print cookies # this creates the cookies ! print 'Content-Type: text/html\n' print '' print '' % dest print '' if debug: print 'Your cookies are now:', getCookies() print 'You are now logged in as %s' % uid print 'Please wait, breathe slowly, deeply, in and out and think calming thoughts' print 'and you will be redirected back to our usual program within a few seconds....' print '' print '\r\n\r\n' if __name__ == '__main__': """ main cgi entry """ ccookies = getCookies() dest = form.getfirst('realdest') # save this for redirection if not dest: dest = '/' if 'HTTP_REFERER' in os.environ: # original destination dest = os.environ['HTTP_REFERER'] u,i = login(form, ccookies, dest) if form.getfirst('submit') == 'Logout': resume(uname=None,uid=None,dest=dest) # resume without session if u <> None: resume(uname=u,uid=i,dest=dest)