#!/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, ldap.filter ldapf = ldap.filter.filter_format 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 = {}) @expose('8021x.html') def cfg8021x(s, username = "username"): return render(errors = {}, username = username) @expose('calendar.html') def calendar(s): return render(errors = {}) def login_perform(s, username, password): dn = ldapf("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 cherrypy.request.method.upper() == 'GET': return render(errors = {}) 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': unicode(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) accountservice.kprop() 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': unicode(e)}, username = username) import kerberos try: assert kerberos.changePassword(username + '@SUBLAB.ORG', oldpassword, password) == True except kerberos.PwdChangeError, e: return render(errors = {'password2': unicode(e[0])}, username = username) accountservice.kprop() 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.encode.encoding': 'utf-8', 'tools.encode.add_charset': True, 'tools.gzip.on': True, 'tools.proxy.on': True, }, '/static': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'static', 'tools.caching.on': True, 'tools.expires.secs': 3600, # 'tools.expires.force': True, }, } 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)