comparison web/secure.py @ 505:ad846b9bdd10

key fingerprints are case- and whitespace-insensitive. add some comments
author Matt Johnston <matt@ucc.asn.au>
date Thu, 26 Jun 2014 23:02:23 +0800
parents 23c6cf01d237
children da769023bf08
comparison
equal deleted inserted replaced
504:028cf9bc3ee8 505:ad846b9bdd10
1 import re
1 import os 2 import os
2 import time 3 import time
3 import fcntl 4 import fcntl
4 import hmac 5 import hmac
5 import binascii 6 import binascii
8 9
9 import bottle 10 import bottle
10 11
11 import config 12 import config
12 13
13 __all__ = ["get_csrf_blob", "check_csrf_blob", "setup_csrf", "get_user_hash"] 14 __all__ = ["get_csrf_blob", "check_csrf_blob", "setup_csrf", "get_user_hash",
15 "check_user_hash"]
14 16
15 HASH=hashlib.sha1 17 HASH=hashlib.sha1
16 18
19 CLEAN_RE = re.compile('[^a-z0-9A-Z]')
20
21 def clean_hash(h):
22 return CLEAN_RE.sub('', h.lower())
23
17 def get_user_hash(): 24 def get_user_hash():
25 """
26 Uses the following apache config.
27 Needs a separate port or IP to no-certificate SSL, SNI isn't good enough.
28
29 <location /~matt/templog/set>
30 Require all granted
31 SSLVerifyClient optional_no_ca
32 SSLVerifyDepth 1
33 SSLOptions +StdEnvVars +ExportCertData +OptRenegotiate
34 </location>
35 """
36
18 verify = bottle.request.environ.get('SSL_CLIENT_VERIFY', '') 37 verify = bottle.request.environ.get('SSL_CLIENT_VERIFY', '')
19 if not (verify == 'GENEROUS' or verify == 'SUCCESS'): 38 if not (verify == 'GENEROUS' or verify == 'SUCCESS'):
20 return 'FAILVERIFY' 39 return 'FAILVERIFY'
21 blob = bottle.request.environ.get('SSL_CLIENT_CERT') 40 blob = bottle.request.environ.get('SSL_CLIENT_CERT')
22 if not blob: 41 if not blob:
24 43
25 b64 = ''.join(l for l in blob.split('\n') 44 b64 = ''.join(l for l in blob.split('\n')
26 if not l.startswith('-')) 45 if not l.startswith('-'))
27 46
28 return HASH(binascii.a2b_base64(b64)).hexdigest() 47 return HASH(binascii.a2b_base64(b64)).hexdigest()
48
49 def check_user_hash(allowed_users):
50 current_hash = clean_hash(get_user_hash())
51 for a in allowed_users:
52 if current_hash == clean_hash(a):
53 return True
54 return False
29 55
30 def setup_csrf(): 56 def setup_csrf():
31 NONCE_SIZE=16 57 NONCE_SIZE=16
32 global _csrf_fd, _csrf_key 58 global _csrf_fd, _csrf_key
33 _csrf_fd = open('%s/csrf.dat' % config.DATA_PATH, 'r+') 59 _csrf_fd = open('%s/csrf.dat' % config.DATA_PATH, 'r+')