Source code for wsgidav.dc.pam_dc

# (c) 2009-2024 Martin Wendt and contributors; see WsgiDAV
# Licensed under the MIT license:
Implementation of a domain controller that allows users to authenticate against
a Pluggable Authentication Module ('PAM').

Used by HTTPAuthenticator. Only available on linux and macOS.

import threading

from wsgidav import util
from wsgidav.dc.base_dc import BaseDomainController

__docformat__ = "reStructuredText"
_logger = util.get_module_logger(__name__)

    import pam
except ImportError:
        "pam_dc requires the `python-pam` module. Try `pip install wsgidav[pam]`."

[docs] class PAMDomainController(BaseDomainController): def __init__(self, wsgidav_app, config): super().__init__(wsgidav_app, config) self.lock = threading.RLock() self.pam = pam.pam() dc_conf = util.get_dict_value(config, "pam_dc", as_dict=True) self.pam_service = dc_conf.get("service", "login") self.pam_encoding = dc_conf.get("encoding", "utf-8") self.pam_resetcreds = dc_conf.get("resetcreds", True) def __str__(self): return f"{self.__class__.__name__}({self.pam_service!r})"
[docs] def get_domain_realm(self, path_info, environ): return f"PAM({self.pam_service})"
[docs] def require_authentication(self, realm, environ): return True
[docs] def basic_auth_user(self, realm, user_name, password, environ): # Seems that python_pam is not threadsafe (#265) with self.lock: is_ok = self.pam.authenticate( user_name, password, service=self.pam_service, resetcreds=self.pam_resetcreds, encoding=self.pam_encoding, ) if not is_ok: _logger.warning( f"pam.authenticate({user_name!r}, '<redacted>', {self.pam_service!r}) failed with code {self.pam.code}: {self.pam.reason}" ) return False _logger.debug(f"User {user_name!r} logged on.") return True
[docs] def supports_http_digest_auth(self): # We don't have access to a plaintext password (or stored hash) return False