]>
Commit | Line | Data |
---|---|---|
f065bc69 | 1 | from twisted.web import resource, server, static |
85f01e3f CP |
2 | import config, urlparse, urllib, hashlib, re |
3 | import qwebirc.util.rijndael, qwebirc.util.ciphers | |
4 | import qwebirc.util | |
65f2c94c | 5 | import qwebirc.util.qjson as json |
ace37679 | 6 | |
1435dd92 | 7 | authgate = config.AUTHGATEPROVIDER.twisted |
ace37679 | 8 | BLOCK_SIZE = 128/8 |
f065bc69 CP |
9 | |
10 | class 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 | 60 | def 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 |
80 | def getSessionData(request): |
81 | return authgate.get_session_data(request) | |
82 | ||
83 | def login_optional(request): | |
84 | return authgate(request, config.AUTHGATEDOMAIN).login_optional() | |
65f2c94c | 85 |