Mercurial > templog
diff web/secure.py @ 293:d15dda1b1f76
merge
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sat, 06 Jul 2019 18:29:45 +0800 |
parents | f7261dd970da |
children | a99631597f65 |
line wrap: on
line diff
--- a/web/secure.py Thu Mar 19 21:50:52 2015 +0800 +++ b/web/secure.py Sat Jul 06 18:29:45 2019 +0800 @@ -11,56 +11,47 @@ import config -__all__ = ["get_csrf_blob", "check_csrf_blob", "setup_csrf", "get_user_hash", -"check_user_hash"] +__all__ = [ + "get_csrf_blob", + "check_csrf_blob", + "setup_csrf", + "check_cookie", + "init_cookie", +] + +AUTH_COOKIE = 'templogauth' +AUTH_COOKIE_LEN = 16 HASH=hashlib.sha1 CLEAN_RE = re.compile('[^a-z0-9A-Z]') -def clean_hash(h): - return CLEAN_RE.sub('', h.lower()) - -def get_user_hash(): - """ - Uses the following apache config. - Needs a separate port or IP to no-certificate SSL, SNI isn't good enough. - - <location /~matt/templog/set> - Require all granted - SSLVerifyClient optional_no_ca - SSLVerifyDepth 1 - SSLOptions +StdEnvVars +ExportCertData +OptRenegotiate - </location> - """ +def cookie_hash(c): + return hashlib.sha256(c).hexdigest() - verify = bottle.request.environ.get('SSL_CLIENT_VERIFY', '') - if not (verify == 'GENEROUS' or verify == 'SUCCESS'): - return 'FAILVERIFY' - blob = bottle.request.environ.get('SSL_CLIENT_CERT') - if not blob: - return 'NOCERT' +def init_cookie(): + """ Generates a new httponly auth cookie if required. + Returns the hash of the cookie (new or existing) + """ + c = bottle.request.get_cookie(AUTH_COOKIE) + if not c: + c = binascii.hexlify(os.urandom(AUTH_COOKIE_LEN)) + bottle.response.set_cookie(AUTH_COOKIE, c, secure=True, httponly=True) + return cookie_hash(c) - b64 = ''.join(l for l in blob.split('\n') - if not l.startswith('-')) - - return HASH(binascii.a2b_base64(b64)).hexdigest() - -def check_user_hash(allowed_users): - current_hash = clean_hash(get_user_hash()) - for a in allowed_users: - if current_hash == clean_hash(a): - return True - return False +def check_cookie(allowed_users): + c = bottle.request.get_cookie(AUTH_COOKIE) + if not c: + return False + return cookie_hash(c) in allowed_users def setup_csrf(): NONCE_SIZE=16 global _csrf_fd, _csrf_key - _csrf_fd = open('%s/csrf.dat' % config.DATA_PATH, 'r+') + _csrf_fd = os.fdopen(os.open('%s/csrf.dat' % config.DATA_PATH, os.O_RDWR | os.O_CREAT, 0600), 'r+') try: fcntl.lockf(_csrf_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) - os.fchmod(_csrf_fd.fileno(), 0600) _csrf_fd.write("%d-%s" % (os.getpid(), binascii.hexlify(os.urandom(NONCE_SIZE)))) _csrf_fd.flush() _csrf_fd.seek(0) @@ -73,7 +64,7 @@ def get_csrf_blob(): expiry = int(config.CSRF_TIMEOUT + time.time()) - content = '%s-%s' % (get_user_hash(), expiry) + content = '%s-%s' % (init_cookie(), expiry) mac = hmac.new(_csrf_key, content).hexdigest() return "%s-%s" % (content, mac) @@ -84,7 +75,7 @@ return False user, expiry, mac = toks - if user != get_user_hash(): + if user != init_cookie(): print>>sys.stderr, "wrong user" return False