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