]> jfr.im git - irc/quakenet/qwebirc.git/blame - qwebirc/engines/authgateengine.py
add dynamic configuration support
[irc/quakenet/qwebirc.git] / qwebirc / engines / authgateengine.py
CommitLineData
f065bc69 1from twisted.web import resource, server, static
85f01e3f
CP
2import config, urlparse, urllib, hashlib, re
3import qwebirc.util.rijndael, qwebirc.util.ciphers
4import qwebirc.util
65f2c94c 5import qwebirc.util.qjson as json
ace37679 6
1435dd92 7authgate = config.AUTHGATEPROVIDER.twisted
ace37679 8BLOCK_SIZE = 128/8
f065bc69
CP
9
10class AuthgateEngine(resource.Resource):
11 isLeaf = True
12
13 def __init__(self, prefix):
14 self.__prefix = prefix
85f01e3f 15 self.__hit = qwebirc.util.HitCounter()
f065bc69
CP
16
17 def deleteCookie(self, request, key):
18 request.addCookie(key, "", path="/", expires="Sat, 29 Jun 1996 01:44:48 GMT")
19
20 def render_GET(self, request):
21 if request.args.get("logout"):
22 self.deleteCookie(request, "user")
23
24 a = authgate(request, config.AUTHGATEDOMAIN)
25 try:
26 ticket = a.login_required(accepting=lambda x: True)
27 except a.redirect_exception, e:
28 pass
29 else:
30 # only used for informational purposes, the backend stores this seperately
31 # so if the user changes it just their front end will be messed up!
32 request.addCookie("user", ticket.username, path="/")
ace37679
CP
33
34 qt = ticket.get("qticket")
35 if not qt is None:
36 getSessionData(request)["qticket"] = decodeQTicket(qt)
f065bc69 37
85f01e3f 38 self.__hit()
65f2c94c
CP
39 if request.getCookie("jslogin"):
40 self.deleteCookie(request, "jslogin")
41 return """<html><head><script>window.opener.__qwebircAuthCallback(%s);</script></head></html>""" % json.dumps(ticket.username)
42
f065bc69
CP
43 location = request.getCookie("redirect")
44 if location is None:
45 location = "/"
46 else:
47 self.deleteCookie(request, "redirect")
48 _, _, path, params, query, _ = urlparse.urlparse(urllib.unquote(location))
49 location = urlparse.urlunparse(("", "", path, params, query, ""))
50
51 request.redirect(location)
52 request.finish()
53
54 return server.NOT_DONE_YET
85f01e3f
CP
55
56 @property
57 def adminEngine(self):
58 return dict(Logins=((self.__hit,),))
f065bc69 59
85f01e3f 60def decodeQTicket(qticket, p=re.compile("\x00*$"), cipher=qwebirc.util.rijndael.rijndael(hashlib.sha256(config.QTICKETKEY).digest()[:16])):
ace37679
CP
61 def decrypt(data):
62 l = len(data)
63 if l < BLOCK_SIZE * 2 or l % BLOCK_SIZE != 0:
64 raise Exception("Bad qticket.")
65
66 iv, data = data[:16], data[16:]
85f01e3f 67 cbc = qwebirc.util.ciphers.CBC(cipher, iv)
ace37679
CP
68
69 # technically this is a flawed padding algorithm as it allows chopping at BLOCK_SIZE, we don't
70 # care about that though!
71 b = range(0, l-BLOCK_SIZE, BLOCK_SIZE)
72 for i, v in enumerate(b):
73 q = cbc.decrypt(data[v:v+BLOCK_SIZE])
74 if i == len(b) - 1:
ace37679
CP
75 yield re.sub(p, "", q)
76 else:
ace37679
CP
77 yield q
78 return "".join(decrypt(qticket))
79
f065bc69
CP
80def getSessionData(request):
81 return authgate.get_session_data(request)
82
83def login_optional(request):
84 return authgate(request, config.AUTHGATEDOMAIN).login_optional()
65f2c94c 85