#!/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)
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)