annotate web/secure.py @ 488:4792e9910cde

watcher script
author Matt Johnston <matt@ucc.asn.au>
date Sun, 09 Feb 2014 11:41:13 +0800
parents d68af9e84485
children 8318d50d766d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
485
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1 import os
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2 import time
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3 import fcntl
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4 import hmac
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5 import binascii
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6 import sys
488
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
7 import hashlib
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
8
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
9 import bottle
485
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
11 import config
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
12
488
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
13 __all__ = ["get_csrf_blob", "check_csrf_blob", "setup_csrf", "get_user_hash"]
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
14
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
15 HASH=hashlib.sha1
485
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
16
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
17 def get_user_hash():
488
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
18 if bottle.request.environ.get('SSL_CLIENT_VERIFY', '') != 'GENEROUS':
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
19 return 'FAILVERIFY'
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
20 blob = bottle.request.environ.get('SSL_CLIENT_CERT')
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
21 if not blob:
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
22 return 'NOCERT'
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
23
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
24 b64 = ''.join(l for l in blob.split('\n')
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
25 if not l.startswith('-'))
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
26
4792e9910cde watcher script
Matt Johnston <matt@ucc.asn.au>
parents: 485
diff changeset
27 return HASH(binascii.a2b_base64(b64)).hexdigest()
485
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
28
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
29 def setup_csrf():
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
30 NONCE_SIZE=16
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
31 global _csrf_fd, _csrf_key
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
32 _csrf_fd = open('%s/csrf.dat' % config.DATA_PATH, 'r+')
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
33
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
34 try:
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
35 fcntl.lockf(_csrf_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
36 os.fchmod(_csrf_fd.fileno(), 0600)
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
37 _csrf_fd.write("%d-%s" % (os.getpid(), binascii.hexlify(os.urandom(NONCE_SIZE))))
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
38 _csrf_fd.flush()
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
39 _csrf_fd.seek(0)
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
40 except IOError:
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
41 pass
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
42 fcntl.lockf(_csrf_fd, fcntl.LOCK_SH)
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
43 _csrf_key = _csrf_fd.read()
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
44 # keep the lock open until we go away
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
45
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
46
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
47 def get_csrf_blob():
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
48 expiry = int(config.CSRF_TIMEOUT + time.time())
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
49 content = '%s-%s' % (get_user_hash(), expiry)
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
50 mac = hmac.new(_csrf_key, content).hexdigest()
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
51 return "%s-%s" % (content, mac)
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
52
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
53 def check_csrf_blob(blob):
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
54 toks = blob.split('-')
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
55 if len(toks) != 3:
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
56 return False
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
57
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
58 user, expiry, mac = toks
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
59 if user != get_user_hash():
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
60 return False
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
61
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
62 try:
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
63 exp = int(expiry)
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
64 except ValueError:
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
65 return False
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
66
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
67 if exp < 1000000000:
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
68 return False
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
69
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
70 if exp > time.time():
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
71 return False
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
72
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
73 check_content = "%s-%s" % (user, expiry)
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
74 check_mac = hmac.new(_csrf_key, content).hexdigest()
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
75 if mac == check_mac:
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
76 return True
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
77
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
78 return False
d68af9e84485 working
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
79