Exemplo n.º 1
0
	def authenticate(self, msg):
		# PAM MUST be initialized outside of a thread. Otherwise it segfaults e.g. with pam_saml.so.
		# See http://pam-python.sourceforge.net/doc/html/#bugs

		args = msg.body.copy()
		locale = args.pop('locale', None)
		args.pop('auth_type', None)
		args.setdefault('new_password', None)
		args.setdefault('username', '')
		args.setdefault('password', '')

		self.pam = PamAuth(locale)
		thread = threads.Simple('pam', notifier.Callback(self.__authenticate_thread, **args), notifier.Callback(self.__authentication_result, msg))
		thread.run()
Exemplo n.º 2
0
class AuthHandler(signals.Provider):

	def __init__(self):
		signals.Provider.__init__(self)
		self.signal_new('authenticated')

	def authenticate(self, msg):
		# PAM MUST be initialized outside of a thread. Otherwise it segfaults e.g. with pam_saml.so.
		# See http://pam-python.sourceforge.net/doc/html/#bugs

		args = msg.body.copy()
		locale = args.pop('locale', None)
		args.pop('auth_type', None)
		args.setdefault('new_password', None)
		args.setdefault('username', '')
		args.setdefault('password', '')

		self.pam = PamAuth(locale)
		thread = threads.Simple('pam', notifier.Callback(self.__authenticate_thread, **args), notifier.Callback(self.__authentication_result, msg))
		thread.run()

	def __authenticate_thread(self, username, password, new_password, **custom_prompts):
		AUTH.info('Trying to authenticate user %r' % (username,))
		username = self.__canonicalize_username(username)
		try:
			self.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:
				self.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

	def __authentication_result(self, thread, result, request):
		if isinstance(result, BaseException) and not isinstance(result, (AuthenticationFailed, AuthenticationInformationMissing, PasswordExpired, PasswordChangeFailed, AccountExpired)):
			msg = ''.join(thread.trace + traceback.format_exception_only(*thread.exc_info[:2]))
			AUTH.error(msg)
		if isinstance(result, tuple):
			username, password = result
			result = {'username': username, 'password': password, 'auth_type': request.body.get('auth_type')}
		auth_result = AuthenticationResult(result)
		self.signal_emit('authenticated', auth_result, request)