#!/usr/bin/python # -*- coding: utf8 -*- import sys, os, cgi appbase = os.path.dirname(os.path.abspath(__file__)) sys.path.append(appbase) import threading import cherrypy from tmpl import expose, render from lxml import etree from lxml.html import formfill from StringIO import StringIO import ldap import mx.DateTime, urllib from accountservice import accountservice import ticket tgt_sites = ['wiki'] class ldapobj(object): def __init__(s, data): if len(data) != 1: raise ValueError, "invalid number of results" dn, fields = data[0] s._keys = fields.keys() for k, v in fields.iteritems(): s.__dict__[k] = v s.dn = dn def __getitem__(s, key): l = s.__dict__[key] if len(l) != 1: raise IndexError, "invalid number of attributes" return l[0] def keys(s): return s._keys class LoginError(Exception): pass class SubdapSite(object): def __init__(s): cherrypy.config.update({'error_page.404': s.http_404}) @expose('error.html') def http_404(s, status, message, **kwargs): return render(details = status + ' - ' + message) @expose('login.html') def index(s): return render(errors = {}) def login_perform(s, username, password): dn = "cn=%s,ou=people,dc=sublab,dc=org" % (username) try: l = ldap.initialize('ldap://oberon.local.sublab.org/') l.start_tls_s() l.simple_bind_s(dn, password) except ldap.INVALID_CREDENTIALS: raise LoginError('Login incorrect') except ldap.LDAPError, e: raise LoginError('Login incorrect') # e.message['info'] return (l, dn) @expose('login.html') def login(s, username = None, password = None): if username == None or password == None: return render(errors = {'password': 'Login incorrect'}) if username == '' or password == '': return render(errors = {'password': 'Login incorrect'}) try: l, dn = s.login_perform(username, password) except LoginError, e: return render(errors = {'password': str(e)}) return s.selectpage(l, dn) def selectpage(s, l, dn, message = {}): user = ldapobj(l.search_s(dn, ldap.SCOPE_BASE, '(objectclass=*)', [])) tgts = {} for site in tgt_sites: tgts[site] = urllib.urlencode(ticket.tgt_create(site, user['cn'])) return render('select.html', user = user, tgts = tgts, message = message) ## x = '' # for r in data: # if r[0] != dn: # continue ## x += '%s\n' % (r[0]) # for k, v in r[1].iteritems(): # for value in v: # details.append([k, value]) ## x += '%s
%s
\n' % (k, "
".join(v)) def newpass_validate(s, username, password, password2, expectstate): errors = {} if username == None or username == '': errors['username'] = 'please specify an user name' elif accountservice.name_valid(username) != expectstate: errors['username'] = 'username invalid' if password == None or len(password) < 6: errors['password'] = 'please specify a password of at least 6 characters' if password2 != password: errors['password2'] = 'passwords did not match' if len(errors) > 0: return errors return None @expose('create.html') def create(s, username = None, password = None, password2 = None): if cherrypy.request.method.upper() == 'GET': return render(errors = {}, username = '') errors = s.newpass_validate(username, password, password2, 'valid') if errors is not None: return render(errors = errors, username = username) accountservice.name_create(username, password) if os.fork() == 0: accountservice.kprop() os._exit(0) return s.login(username, password) @expose('pwchange.html') def pwchange(s, username = None, oldpassword = None, password = None, password2 = None): if cherrypy.request.method.upper() == 'GET': return render(errors = {}, username = username) errors = s.newpass_validate(username, password, password2, 'exists') if errors is not None: return render(errors = errors, username = username) try: l, dn = s.login_perform(username, oldpassword) except LoginError, e: return render(errors = {'oldpassword': str(e)}, username = username) import kerberos try: assert kerberos.changePassword(username + '@SUBLAB.ORG', oldpassword, password) == True except kerberos.PwdChangeError, e: return render(errors = {'password2': str(e[0])}, username = username) if os.fork() == 0: accountservice.kprop() os._exit(0) return s.selectpage(l, dn, {'pwchangeok': True}) @cherrypy.expose def kill(s): import sys sys.exit(0) config = { 'global': { 'server.socket_port': 8080, 'server.socket_host': '0.0.0.0', # 'server.socket_host': '::1', 'tools.staticdir.root': appbase, }, '/': { 'tools.decode.on': True, 'tools.encode.on': True, 'tools.gzip.on': True, 'tools.proxy.on': True, # 'tools.caching.on': False, # 'tools.expires.secs': 0, # 'tools.expires.force': True, }, '/static': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'static', }, } if len(sys.argv) >= 2 and sys.argv[1] == 'standalone': import tmpl tmpl.myurl = lambda x: x cherrypy.quickstart(SubdapSite(), "/", config) else: cherrypy.config.update({'environment': 'embedded'}) application = cherrypy.Application(SubdapSite(), script_name = None, config = config)