2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-11-29 04:50:21 +00:00

Tighten up new PAM check

For one, remove the password cache cleaning, as it no longer is run.

For another, skip the fork if uid is already 0.

Finally, wrap the check in a try/finally to keep the privileged process
more certain in exiting.
This commit is contained in:
Jarrod Johnson 2020-02-06 10:05:57 -05:00
parent 49c00bfbb7
commit 7480494432

View File

@ -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