diff --git a/confluent_server/confluent/auth.py b/confluent_server/confluent/auth.py index d978281e..5d3906b9 100644 --- a/confluent_server/confluent/auth.py +++ b/confluent_server/confluent/auth.py @@ -99,17 +99,6 @@ _deniedbyrole = { } -def _prune_passcache(): - # This function makes sure we don't remember a passphrase in memory more - # than 10 seconds - while True: - curtime = time.time() - for passent in _passcache.iterkeys(): - if passent[2] < curtime - 90: - del _passcache[passent] - eventlet.sleep(90) - - def _get_usertenant(name, tenant=False): """_get_usertenant @@ -269,16 +258,27 @@ def check_user_passphrase(name, passphrase, operation=None, element=None, tenant _passcache[(user, tenant)] = hashlib.sha256(passphrase).digest() return authorize(user, element, tenant, operation) if pam: - pid = os.fork() - if not pid: - os.setuid(0) - pammy = pam.pam() - usergood = pammy.authenticate(user, passphrase, service=_pamservice) - os._exit(0 if usergood else 1) - usergood = os.waitpid(pid, 0)[1] - if usergood == 0: + if os.getuid() != 0: + # confluent is running with reduced privilege, however, pam_unix refuses + # to let a non-0 user check anothers password. + # We will fork and the child will assume elevated privilege to + # get unix_chkpwd helper to enable checking /etc/shadow + pid = os.fork() + if not pid: + usergood = False + try: + os.setuid(0) + usergood = pam.authenticate(user, passphrase, service=_pamservice) + finally: + os._exit(0 if usergood else 1) + usergood = os.waitpid(pid, 0)[1] == 0 + else: + # We are running as root, we don't need to fork in order to authenticate the + # user + usergood = pam.authenticate(user, passphrase, service=_pamservice) + if usergood: _passcache[(user, tenant)] = hashlib.sha256(passphrase).digest() - return authorize(user, element, tenant, operation, skipuserobj=False) + return authorize(user, element, tenant, operation, skipuserobj=False) eventlet.sleep(0.05) # stall even on test for existence of a username return None