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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2 import os
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3 import time
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4 import fcntl
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5 import hmac
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6 import binascii
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7 import sys
189
101c66da848d watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 185
diff changeset
8 import hashlib
101c66da848d watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 185
diff changeset
9
101c66da848d watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 185
diff changeset
10 import bottle
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
11
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
12 import config
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
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
101c66da848d watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 185
diff changeset
24
101c66da848d watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 185
diff changeset
25 HASH=hashlib.sha1
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
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
a99631597f65 don't expire cookies soon
Matt Johnston <matt@ucc.asn.au>
parents: 291
diff changeset
39 years = 60*60*24*365
a99631597f65 don't expire cookies soon
Matt Johnston <matt@ucc.asn.au>
parents: 291
diff changeset
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
101c66da848d watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 185
diff changeset
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
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
49 def setup_csrf():
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
50 NONCE_SIZE=16
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
51 global _csrf_fd, _csrf_key
226
da769023bf08 Fix race setting umask
Matt Johnston <matt@ucc.asn.au>
parents: 211
diff changeset
52 _csrf_fd = os.fdopen(os.open('%s/csrf.dat' % config.DATA_PATH, os.O_RDWR | os.O_CREAT, 0600), 'r+')
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
53
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
54 try:
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
55 fcntl.lockf(_csrf_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
56 _csrf_fd.write("%d-%s" % (os.getpid(), binascii.hexlify(os.urandom(NONCE_SIZE))))
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
57 _csrf_fd.flush()
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
58 _csrf_fd.seek(0)
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
59 except IOError:
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
60 pass
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
61 fcntl.lockf(_csrf_fd, fcntl.LOCK_SH)
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
62 _csrf_key = _csrf_fd.read()
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
63 # keep the lock open until we go away
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
64
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
65
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
66 def get_csrf_blob():
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
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
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
69 mac = hmac.new(_csrf_key, content).hexdigest()
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
70 return "%s-%s" % (content, mac)
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
71
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
72 def check_csrf_blob(blob):
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
73 toks = blob.split('-')
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
74 if len(toks) != 3:
194
4fa8cbf31065 working kinda
Matt Johnston <matt@ucc.asn.au>
parents: 191
diff changeset
75 print>>sys.stderr, "wrong toks"
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
76 return False
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
77
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
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
4fa8cbf31065 working kinda
Matt Johnston <matt@ucc.asn.au>
parents: 191
diff changeset
80 print>>sys.stderr, "wrong user"
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
81 return False
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
82
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
83 try:
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
84 exp = int(expiry)
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
85 except ValueError:
194
4fa8cbf31065 working kinda
Matt Johnston <matt@ucc.asn.au>
parents: 191
diff changeset
86 print>>sys.stderr, "failed exp"
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
87 return False
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
88
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
89 if exp < 1000000000:
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
90 return False
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
91
194
4fa8cbf31065 working kinda
Matt Johnston <matt@ucc.asn.au>
parents: 191
diff changeset
92 if exp < time.time():
4fa8cbf31065 working kinda
Matt Johnston <matt@ucc.asn.au>
parents: 191
diff changeset
93 print>>sys.stderr, "expired %d %d" % (exp, time.time())
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
94 return False
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
95
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
96 check_content = "%s-%s" % (user, expiry)
194
4fa8cbf31065 working kinda
Matt Johnston <matt@ucc.asn.au>
parents: 191
diff changeset
97 check_mac = hmac.new(_csrf_key, check_content).hexdigest()
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
98 if mac == check_mac:
194
4fa8cbf31065 working kinda
Matt Johnston <matt@ucc.asn.au>
parents: 191
diff changeset
99 print>>sys.stderr, "good hmac"
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
100 return True
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
101
194
4fa8cbf31065 working kinda
Matt Johnston <matt@ucc.asn.au>
parents: 191
diff changeset
102 print>>sys.stderr, "fail"
185
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
103 return False
adbf70d1449f working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
104