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:
parent
b0855f7c88
commit
dd111ffef5
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user