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