2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-02-16 10:39:23 +00:00

Flesh out auth to the point where set and check of password is plausible

This commit is contained in:
Jarrod Johnson 2013-10-08 18:25:59 -04:00
parent b0855f7c88
commit dd111ffef5

View File

@ -6,10 +6,24 @@ import confluent.config as config
import eventlet
import Crypto.Protocol.KDF as kdf
import Crypto.Hash as hash
import os
import time
_passcache = {}
_passchecking = {}
def _prune_passcache():
# This function makes sure we don't remember a passphrase in memory more
# than 10 seconds
while (1):
curtime = time.time()
for passent in _passcache.iterkeys():
if passent[2] < curtime - 10:
del _passcache[passent]
eventlet.sleep(10)
def _get_usertenant(name, tenant=False):
"""_get_usertenant
@ -32,6 +46,8 @@ def _get_usertenant(name, tenant=False):
else:
user = name
tenant = None
yield user
yield tenant
def authorize(name, element, tenant=False, access='rw'):
#TODO: actually use the element to ascertain if this user is good enough
@ -57,18 +73,18 @@ def authorize(name, element, tenant=False, access='rw'):
return None
def set_user_password(name, password, tenant=None):
"""Set user password
def set_user_password(name, passphrase, tenant=None):
"""Set user passphrase
:param name: The unique shortname of the user
:param password: The password to set for given user
:param passphrase: The passphrase to set for given user
:param tenant: The tenant to which the user belongs.
"""
# TODO(jbjohnso): WORKERPOOL
# When worker pool implemented, hand off the
# PBKDF2 to a worker instead of blocking
user, tenant = _get_usertenant(name, tenant)
_passcache[(user, tenant)] = password
_passcache[(user, tenant)] = passphrase
salt = os.urandom(8)
crypted = kdf.PBKDF2(passphrase, salt, 32, 10000,
lambda p, s: hash.HMAC.new(p, s, hash.SHA256).digest())
@ -78,22 +94,22 @@ def set_user_password(name, password, tenant=None):
def check_user_passphrase(name, passphrase, tenant=None):
user, tenant = _get_usertenant(name, tenant)
if (user,tenant) in _passcache:
if passphrase == passcache[(user,tenant)]:
return True
else:
# In case of someone trying to guess,
# while someone is legitimately logged in
# invalidate cache and force the slower check
del _passchache[(user, tenant)]
return False
eventlet.sleep(0.1) # limit throughput of remote guessing
while (user,tenant) in _passchecking:
# Want to serialize passphrase checking activity
# by a user, which might be malicious
# would normally make an event and wait
# but here there's no need for that
eventlet.sleep(0.5)
if (user,tenant) in _passcache:
if passphrase == _passcache[(user,tenant)]:
return True
else:
# In case of someone trying to guess,
# while someone is legitimately logged in
# invalidate cache and force the slower check
del _passcache[(user, tenant)]
return False
eventlet.sleep(0.1) # limit throughput of remote guessing
cfm = config.ConfigManager(tenant)
ucfg = cfm.get_user(user)
if ucfg is None or 'cryptpass' not in ucfg:
@ -105,3 +121,9 @@ def check_user_passphrase(name, passphrase, tenant=None):
salt, crypt = ucfg['cryptpass']
crypted = kdf.PBKDF2(passphrase, salt, 32, 10000,
lambda p, s: hash.HMAC.new(p, s, hash.SHA256).digest())
del _passchecking[(user, tenant)]
if crypt == crypted:
_passcache[(user, tenant)] = passphrase
return True
return False