annotate web/secure.py @ 194:4fa8cbf31065

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