def _conversation( self, auth, query_list, data ): # type: (Any, List[Tuple[Any, Any]], Any) -> Iterator[Tuple[str, int]] answers, prompts, missing = data prompts.extend(query_list) for query, qt in query_list: prompt = qt if qt == PAM_PROMPT_ECHO_OFF and query.strip( ':\t ') in self.custom_prompts: prompt = query response = '' try: response = answers[prompt] if isinstance(response, list): response = response.pop(0) except KeyError as exc: AUTH.error('Missing answer for prompt: %r' % (str(exc), )) missing.append(query) except IndexError: AUTH.error('Unexpected prompt: %r' % (query, )) if qt in (PAM_TEXT_INFO, PAM_ERROR_MSG): AUTH.info('PAM says: %r' % (query, )) # AUTH.error('# PAM(%d) %s: answer=%r' % (qt, repr(query).strip("':\" "), response)) yield (response, 0)
def __authenticate_thread(self, pam, username, password, new_password, **custom_prompts): AUTH.info('Trying to authenticate user %r' % (username, )) username = self.__canonicalize_username(username) try: pam.authenticate(username, password, **custom_prompts) except AuthenticationFailed as auth_failed: AUTH.error(str(auth_failed)) raise except PasswordExpired as pass_expired: AUTH.info(str(pass_expired)) if new_password is None: raise try: pam.change_password(username, password, new_password) except PasswordChangeFailed as change_failed: AUTH.error(str(change_failed)) raise else: AUTH.info('Password change for %r was successful' % (username, )) return (username, new_password) else: AUTH.info('Authentication for %r was successful' % (username, )) return (username, password)
def __canonicalize_username(self, username): try: lo, po = get_machine_connection(write=False) result = None if lo: attr = 'mailPrimaryAddress' if '@' in username else 'uid' result = lo.search(filter_format('(&(%s=%s)(objectClass=person))', (attr, username)), attr=['uid'], unique=True) if result and result[0][1].get('uid'): username = result[0][1]['uid'][0] AUTH.info('Canonicalized username: %r' % (username,)) except (ldap.LDAPError, udm_errors.ldapError) as exc: # /etc/machine.secret missing or LDAP server not reachable AUTH.warn('Canonicalization of username was not possible: %s' % (exc,)) reset_cache() except: AUTH.error('Canonicalization of username failed: %s' % (traceback.format_exc(),)) finally: # ignore all exceptions, even in except blocks return username