mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-21 17:11:58 +00:00
Implement support for additional pam prompts
For example, if PAM has OTP, then support it.
This commit is contained in:
parent
f2eba22b9b
commit
f830514d10
@ -221,11 +221,14 @@ def check_user_passphrase(name, passphrase, operation=None, element=None, tenant
|
||||
if ucfg is None:
|
||||
eventlet.sleep(0.05)
|
||||
return None
|
||||
bpassphrase = None
|
||||
if isinstance(passphrase, dict) and len(passphrase) == 1:
|
||||
passphrase = list(passphrase.values())[0]
|
||||
if isinstance(passphrase, bytes):
|
||||
bpassphrase = passphrase
|
||||
else:
|
||||
elif not isinstance(passphrase, dict):
|
||||
bpassphrase = passphrase.encode('utf8')
|
||||
if (user, tenant) in _passcache:
|
||||
if (user, tenant) in _passcache and bpassphrase:
|
||||
if hashlib.sha256(bpassphrase).digest() == _passcache[(user, tenant)]:
|
||||
return authorize(user, element, tenant, operation=operation)
|
||||
else:
|
||||
@ -233,7 +236,7 @@ def check_user_passphrase(name, passphrase, operation=None, element=None, tenant
|
||||
# while someone is legitimately logged in
|
||||
# invalidate cache and force the slower check
|
||||
del _passcache[(user, tenant)]
|
||||
if 'cryptpass' in ucfg:
|
||||
if 'cryptpass' in ucfg and bpassphrase:
|
||||
_passchecking[(user, tenant)] = True
|
||||
# TODO(jbjohnso): WORKERPOOL
|
||||
# PBKDF2 is, by design, cpu intensive
|
||||
@ -296,7 +299,8 @@ def check_user_passphrase(name, passphrase, operation=None, element=None, tenant
|
||||
# user
|
||||
usergood = pam.authenticate(user, passphrase, service=_pamservice)
|
||||
if usergood:
|
||||
_passcache[(user, tenant)] = hashlib.sha256(bpassphrase).digest()
|
||||
if bpassphrase:
|
||||
_passcache[(user, tenant)] = hashlib.sha256(bpassphrase).digest()
|
||||
return authorize(user, element, tenant, operation, skipuserobj=False)
|
||||
eventlet.sleep(0.05) # stall even on test for existence of a username
|
||||
return None
|
||||
|
@ -305,8 +305,13 @@ def _authorize_request(env, operation):
|
||||
# of a CSRF
|
||||
return {'code': 401}
|
||||
return ('logout',)
|
||||
name, passphrase = base64.b64decode(
|
||||
env['HTTP_AUTHORIZATION'].replace('Basic ', '')).split(b':', 1)
|
||||
if env['HTTP_AUTHORIZATION'].startswith('MultiBasic '):
|
||||
name, passphrase = base64.b64decode(
|
||||
env['HTTP_AUTHORIZATION'].replace('MultiBasic ', '')).split(b':', 1)
|
||||
passphrase = json.loads(passphrase)
|
||||
else:
|
||||
name, passphrase = base64.b64decode(
|
||||
env['HTTP_AUTHORIZATION'].replace('Basic ', '')).split(b':', 1)
|
||||
try:
|
||||
authdata = auth.check_user_passphrase(name, passphrase, operation=operation, element=element)
|
||||
except Exception as e:
|
||||
|
@ -116,7 +116,7 @@ class pam():
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def authenticate(self, username, password, service='login', encoding='utf-8', resetcreds=True, answers=None):
|
||||
def authenticate(self, username, password, service='login', encoding='utf-8', resetcreds=True):
|
||||
"""username and password authentication for the given service.
|
||||
|
||||
Returns True for success, or False for failure.
|
||||
@ -142,19 +142,38 @@ class pam():
|
||||
def my_conv(n_messages, messages, p_response, app_data):
|
||||
"""Simple conversation function that responds to any
|
||||
prompt where the echo is off with the supplied password"""
|
||||
for i in range(n_messages):
|
||||
if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF:
|
||||
currprompt = messages[i].contents.msg.decode('utf8').strip()
|
||||
prompts.add(currprompt)
|
||||
for i in range(n_messages):
|
||||
if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF:
|
||||
currprompt = messages[i].contents.msg.decode('utf8').strip()
|
||||
if isinstance(password, dict):
|
||||
if currprompt in password:
|
||||
continue
|
||||
elif len(prompts) > 1:
|
||||
return 19 # PAM_CONV_ERR
|
||||
else:
|
||||
if len(prompts) > 1:
|
||||
return 19 # PAM_CONV_ERR
|
||||
# Create an array of n_messages response objects
|
||||
addr = calloc(n_messages, sizeof(PamResponse))
|
||||
response = cast(addr, POINTER(PamResponse))
|
||||
p_response[0] = response
|
||||
for i in range(n_messages):
|
||||
if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF:
|
||||
prompts.add(messages[i].contents.msg)
|
||||
if answers and messages[i].contents.msg in answers:
|
||||
currpassword = answers[messages[i].contents.msg]
|
||||
currcpassword = c_char_p(currpassword)
|
||||
currprompt = messages[i].contents.msg.decode('utf8').strip()
|
||||
if isinstance(password, dict):
|
||||
if currprompt in password:
|
||||
currpassword = password[currprompt]
|
||||
currcpassword = c_char_p(currpassword.encode('utf8'))
|
||||
elif len(password) == 1:
|
||||
currpassword = list(password.values())[0]
|
||||
currcpassword = c_char_p(currpassword.encode('utf8'))
|
||||
else:
|
||||
currpassword = password
|
||||
currcpassword = cpassword
|
||||
currcpassword = c_char_p(password.encode('utf8'))
|
||||
dst = calloc(len(currpassword)+1, sizeof(c_char))
|
||||
memmove(dst, currcpassword, len(currpassword))
|
||||
response[i].resp = dst
|
||||
@ -164,7 +183,6 @@ class pam():
|
||||
# python3 ctypes prefers bytes
|
||||
if sys.version_info >= (3,):
|
||||
if isinstance(username, str): username = username.encode(encoding)
|
||||
if isinstance(password, str): password = password.encode(encoding)
|
||||
if isinstance(service, str): service = service.encode(encoding)
|
||||
else:
|
||||
if isinstance(username, unicode):
|
||||
@ -174,14 +192,13 @@ class pam():
|
||||
if isinstance(service, unicode):
|
||||
service = service.encode(encoding)
|
||||
|
||||
if b'\x00' in username or b'\x00' in password or b'\x00' in service:
|
||||
if b'\x00' in username or b'\x00' in service:
|
||||
self.code = 4 # PAM_SYSTEM_ERR in Linux-PAM
|
||||
self.reason = 'strings may not contain NUL'
|
||||
return False
|
||||
|
||||
# do this up front so we can safely throw an exception if there's
|
||||
# anything wrong with it
|
||||
cpassword = c_char_p(password)
|
||||
prompts = set([])
|
||||
|
||||
handle = PamHandle()
|
||||
@ -212,7 +229,7 @@ class pam():
|
||||
|
||||
if hasattr(libpam, 'pam_end'):
|
||||
pam_end(handle, retval)
|
||||
if answers is None and len(prompts) > 1 and not auth_success:
|
||||
if (not isinstance(password, dict)) and len(prompts) > 1 and not auth_success:
|
||||
raise PromptsNeeded(prompts)
|
||||
return auth_success
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
dracut_install /usr/bin/mktemp
|
||||
dracut_install mktemp
|
||||
dracut_install /usr/lib64/libtss2-tcti-device.so.*
|
||||
dracut_install tpm2_create tpm2_pcrread tpm2_createpolicy tpm2_createprimary
|
||||
dracut_install tpm2_load tpm2_unseal tpm2_getcap tpm2_evictcontrol
|
||||
|
Loading…
Reference in New Issue
Block a user