Mercurial > templog
annotate web/secure.py @ 301:47c259458160
merge
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sat, 06 Jul 2019 19:17:21 +0800 |
parents | f7261dd970da |
children | a99631597f65 |
rev | line source |
---|---|
211
59379b2bd056
key fingerprints are case- and whitespace-insensitive.
Matt Johnston <matt@ucc.asn.au>
parents:
194
diff
changeset
|
1 import re |
185 | 2 import os |
3 import time | |
4 import fcntl | |
5 import hmac | |
6 import binascii | |
7 import sys | |
189 | 8 import hashlib |
9 | |
10 import bottle | |
185 | 11 |
12 import config | |
13 | |
291
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
14 __all__ = [ |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
15 "get_csrf_blob", |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
16 "check_csrf_blob", |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
17 "setup_csrf", |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
18 "check_cookie", |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
19 "init_cookie", |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
20 ] |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
21 |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
22 AUTH_COOKIE = 'templogauth' |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
23 AUTH_COOKIE_LEN = 16 |
189 | 24 |
25 HASH=hashlib.sha1 | |
185 | 26 |
211
59379b2bd056
key fingerprints are case- and whitespace-insensitive.
Matt Johnston <matt@ucc.asn.au>
parents:
194
diff
changeset
|
27 CLEAN_RE = re.compile('[^a-z0-9A-Z]') |
59379b2bd056
key fingerprints are case- and whitespace-insensitive.
Matt Johnston <matt@ucc.asn.au>
parents:
194
diff
changeset
|
28 |
291
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
29 def cookie_hash(c): |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
30 return hashlib.sha256(c).hexdigest() |
211
59379b2bd056
key fingerprints are case- and whitespace-insensitive.
Matt Johnston <matt@ucc.asn.au>
parents:
194
diff
changeset
|
31 |
291
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
32 def init_cookie(): |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
33 """ Generates a new httponly auth cookie if required. |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
34 Returns the hash of the cookie (new or existing) |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
35 """ |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
36 c = bottle.request.get_cookie(AUTH_COOKIE) |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
37 if not c: |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
38 c = binascii.hexlify(os.urandom(AUTH_COOKIE_LEN)) |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
39 bottle.response.set_cookie(AUTH_COOKIE, c, secure=True, httponly=True) |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
40 return cookie_hash(c) |
189 | 41 |
291
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
42 def check_cookie(allowed_users): |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
43 c = bottle.request.get_cookie(AUTH_COOKIE) |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
44 if not c: |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
45 return False |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
46 return cookie_hash(c) in allowed_users |
211
59379b2bd056
key fingerprints are case- and whitespace-insensitive.
Matt Johnston <matt@ucc.asn.au>
parents:
194
diff
changeset
|
47 |
185 | 48 def setup_csrf(): |
49 NONCE_SIZE=16 | |
50 global _csrf_fd, _csrf_key | |
226 | 51 _csrf_fd = os.fdopen(os.open('%s/csrf.dat' % config.DATA_PATH, os.O_RDWR | os.O_CREAT, 0600), 'r+') |
185 | 52 |
53 try: | |
54 fcntl.lockf(_csrf_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) | |
55 _csrf_fd.write("%d-%s" % (os.getpid(), binascii.hexlify(os.urandom(NONCE_SIZE)))) | |
56 _csrf_fd.flush() | |
57 _csrf_fd.seek(0) | |
58 except IOError: | |
59 pass | |
60 fcntl.lockf(_csrf_fd, fcntl.LOCK_SH) | |
61 _csrf_key = _csrf_fd.read() | |
62 # keep the lock open until we go away | |
63 | |
64 | |
65 def get_csrf_blob(): | |
66 expiry = int(config.CSRF_TIMEOUT + time.time()) | |
291
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
67 content = '%s-%s' % (init_cookie(), expiry) |
185 | 68 mac = hmac.new(_csrf_key, content).hexdigest() |
69 return "%s-%s" % (content, mac) | |
70 | |
71 def check_csrf_blob(blob): | |
72 toks = blob.split('-') | |
73 if len(toks) != 3: | |
194 | 74 print>>sys.stderr, "wrong toks" |
185 | 75 return False |
76 | |
77 user, expiry, mac = toks | |
291
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
78 if user != init_cookie(): |
194 | 79 print>>sys.stderr, "wrong user" |
185 | 80 return False |
81 | |
82 try: | |
83 exp = int(expiry) | |
84 except ValueError: | |
194 | 85 print>>sys.stderr, "failed exp" |
185 | 86 return False |
87 | |
88 if exp < 1000000000: | |
89 return False | |
90 | |
194 | 91 if exp < time.time(): |
92 print>>sys.stderr, "expired %d %d" % (exp, time.time()) | |
185 | 93 return False |
94 | |
95 check_content = "%s-%s" % (user, expiry) | |
194 | 96 check_mac = hmac.new(_csrf_key, check_content).hexdigest() |
185 | 97 if mac == check_mac: |
194 | 98 print>>sys.stderr, "good hmac" |
185 | 99 return True |
100 | |
194 | 101 print>>sys.stderr, "fail" |
185 | 102 return False |
103 |