Mercurial > templog
annotate web/secure.py @ 303:a99631597f65
don't expire cookies soon
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 23 Jul 2019 22:44:24 +0800 |
parents | f7261dd970da |
children | 87c20b8c5472 |
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)) |
303 | 39 years = 60*60*24*365 |
40 bottle.response.set_cookie(AUTH_COOKIE, c, secure=True, httponly=True, max_age=10*years) | |
291
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
41 return cookie_hash(c) |
189 | 42 |
291
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
43 def check_cookie(allowed_users): |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
44 c = bottle.request.get_cookie(AUTH_COOKIE) |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
45 if not c: |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
46 return False |
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
47 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
|
48 |
185 | 49 def setup_csrf(): |
50 NONCE_SIZE=16 | |
51 global _csrf_fd, _csrf_key | |
226 | 52 _csrf_fd = os.fdopen(os.open('%s/csrf.dat' % config.DATA_PATH, os.O_RDWR | os.O_CREAT, 0600), 'r+') |
185 | 53 |
54 try: | |
55 fcntl.lockf(_csrf_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) | |
56 _csrf_fd.write("%d-%s" % (os.getpid(), binascii.hexlify(os.urandom(NONCE_SIZE)))) | |
57 _csrf_fd.flush() | |
58 _csrf_fd.seek(0) | |
59 except IOError: | |
60 pass | |
61 fcntl.lockf(_csrf_fd, fcntl.LOCK_SH) | |
62 _csrf_key = _csrf_fd.read() | |
63 # keep the lock open until we go away | |
64 | |
65 | |
66 def get_csrf_blob(): | |
67 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
|
68 content = '%s-%s' % (init_cookie(), expiry) |
185 | 69 mac = hmac.new(_csrf_key, content).hexdigest() |
70 return "%s-%s" % (content, mac) | |
71 | |
72 def check_csrf_blob(blob): | |
73 toks = blob.split('-') | |
74 if len(toks) != 3: | |
194 | 75 print>>sys.stderr, "wrong toks" |
185 | 76 return False |
77 | |
78 user, expiry, mac = toks | |
291
f7261dd970da
- replace ssl client certs with cookies
Matt Johnston <matt@ucc.asn.au>
parents:
226
diff
changeset
|
79 if user != init_cookie(): |
194 | 80 print>>sys.stderr, "wrong user" |
185 | 81 return False |
82 | |
83 try: | |
84 exp = int(expiry) | |
85 except ValueError: | |
194 | 86 print>>sys.stderr, "failed exp" |
185 | 87 return False |
88 | |
89 if exp < 1000000000: | |
90 return False | |
91 | |
194 | 92 if exp < time.time(): |
93 print>>sys.stderr, "expired %d %d" % (exp, time.time()) | |
185 | 94 return False |
95 | |
96 check_content = "%s-%s" % (user, expiry) | |
194 | 97 check_mac = hmac.new(_csrf_key, check_content).hexdigest() |
185 | 98 if mac == check_mac: |
194 | 99 print>>sys.stderr, "good hmac" |
185 | 100 return True |
101 | |
194 | 102 print>>sys.stderr, "fail" |
185 | 103 return False |
104 |