Ë
    "ïàjÞ  ã                   óv   — d Z ddlZddlmZmZ ddlmZ ddlmZ dZ	 ej                  e«      Z G d„ de«      Zy)	a  
Abstract base class of a domain controller (used by HTTPAuthenticator).

This ABC serves as base class for DomainControllers and provides some
default implementations.

Domain controllers are called by `HTTPAuthenticator` to handle these tasks:

- Basic authentication:
  Check if user_name/password is allowed to perform a request

- Digest authentication (optional):
  Check if user_name is allowed to perform a request and return the MD5 hash.

- Define permissions and roles for a given user (optional).


Note that there is no checking for `isinstance(BaseDomainController)` in the
code, so WsgiDAV also accepts duck-typed domain controllers.

Digest Authentication
---------------------

See https://en.wikipedia.org/wiki/Digest_access_authentication


Permissions and Roles
---------------------

A domain controller MAY add entries to the `environment["wsgidav.auth. ..."]`
namespace in order to define access permissions for the following middleware
(e.g. dir_browser) and DAV providers.

TODO: Work In Progress / Subject to change

é    N)ÚABCÚabstractmethod)Úmd5)ÚutilÚreStructuredTextc                   óx   — e Zd ZdZdZd„ Zd„ Zd„ Zed„ «       Z	ed„ «       Z
d„ Zed	„ «       Zed
„ «       Zd„ Zd„ Zy)ÚBaseDomainController)Ú
browse_dirÚdelete_resourceÚedit_resource)ÚadminÚeditorÚreaderc                 ó    — || _         || _        y )N)Úwsgidav_appÚconfig)Úselfr   r   s      úA/srv/dav/.venv/lib/python3.12/site-packages/wsgidav/dc/base_dc.pyÚ__init__zBaseDomainController.__init__:   s   € Ø&ˆÔØˆ�ó    c                 ó4   — | j                   j                  › d�S )Nz())Ú	__class__Ú__name__©r   s    r   Ú__str__zBaseDomainController.__str__>   s   € Ø—.‘.×)Ñ)Ð*¨"Ð-Ð-r   c                 ó  — |r|d   }n| j                   j                  |«      \  }}|sHt        j                  dt	        j
                  |t        j                  j                  «      ›dd›�«       y|j                  }|dk(  rd}|S )zDInternal helper for derived classes to implement get_domain_realm().zwsgidav.providerz_calc_realm_from_path_provider(z): NÚ ú/)
r   Úresolve_providerÚloggerÚwarningr   Úsafe_re_encodeÚsysÚstdoutÚencodingÚ
share_path)r   Ú	path_infoÚenvironÚdav_providerÚ_shareÚrealms         r   Ú_calc_realm_from_path_providerz3BaseDomainController._calc_realm_from_path_providerA   s�   € áð #Ð#5Ñ6‰Lð $(×#3Ñ#3×#DÑ#DÀYÓ#OÑ ˆF�LáÜ�N‰NØ1´$×2EÑ2EÀiÔQT×Q[ÑQ[×QdÑQdÓ2eÐ1hÐhkÐlpÐksÐtôð à×'Ñ'ˆØ�BŠ;ØˆEØˆr   c                 ó   — t         ‚)a  Return the normalized realm name for a given URL.

        This method is called

        - On startup, to check if anonymous access is allowed for a given share.
          In this case, `environ` is None.
        - For every request, before basic or digest authentication is handled.

        A domain controller that uses the share path as realm name may use
        the `_calc_realm_from_path_provider()` helper.

        Args:
            path_info (str):
            environ (dict | None):
        Returns:
            str
        ©ÚNotImplementedError)r   r'   r(   s      r   Úget_domain_realmz%BaseDomainController.get_domain_realmW   s
   € ô& "Ð!r   c                 ó   — t         ‚)a  Return False to disable authentication for this request.

        This method is called

        - On startup, to check if anonymous access is allowed for a given share.
          In this case, `environ` is None.
        - For every request, before basic or digest authentication is handled.
          If False is returned, we MAY also set environment variables for
          anonymous access::

                environment["wsgidav.auth.roles"] = (<role>, ...)
                environment["wsgidav.auth.permissions"] = (<perm>, ...)
                return False

        Args:
            realm (str):
            environ (dict | None):
        Returns:
            False to allow anonymous access
            True to force subsequent digest or basic authentication
        r.   )r   r+   r(   s      r   Úrequire_authenticationz+BaseDomainController.require_authenticationl   s
   € ô. "Ð!r   c                 óL   — | j                  |d«      }| j                  |d«       S )z¹Return true if anonymous access will be granted to the share path.

        This method is called on start-up to print out info and warnings.

        Returns:
            bool
        N)r0   r2   )r   r'   r+   s      r   Úis_share_anonymousz'BaseDomainController.is_share_anonymous…   s,   € ð ×%Ñ% i°Ó6ˆØ×.Ñ.¨u°dÓ;Ð;Ð;r   c                 ó   — t         ‚)a(  Check request access permissions for realm/user_name/password.

        Called by http_authenticator for basic authentication requests.

        Optionally set environment variables:

            environ["wsgidav.auth.roles"] = (<role>, ...)
            environ["wsgidav.auth.permissions"] = (<perm>, ...)

        Args:
            realm (str):
            user_name (str):
            password (str):
            environ (dict):
        Returns:
            False if user is not known or not authorized
            True if user is authorized
        r.   )r   r+   Ú	user_nameÚpasswordr(   s        r   Úbasic_auth_userz$BaseDomainController.basic_auth_user�   s
   € ô( "Ð!r   c                 ó   — t         ‚)zòSignal if this DC instance supports the HTTP digest authentication theme.

        If true, `HTTPAuthenticator` will call `dc.digest_auth_user()`,
        so this method must be implemented as well.

        Returns:
            bool
        r.   r   s    r   Úsupports_http_digest_authz.BaseDomainController.supports_http_digest_auth¦   s
   € ô "Ð!r   c                 óz   — |dz   |z   dz   |z   }t        t        j                  |«      «      j                  «       }|S )zGInternal helper for derived classes to compute a digest hash (A1 part).ú:)r   r   Úto_bytesÚ	hexdigest)r   r+   r6   r7   ÚdataÚA1s         r   Ú_compute_http_digest_a1z,BaseDomainController._compute_http_digest_a1Ä   s;   € à˜3‰ Ñ&¨Ñ,¨xÑ7ˆÜ”—‘˜tÓ$Ó%×/Ñ/Ó1ˆØˆ	r   c                 ó   — t         ‚)a  Check access permissions for realm/user_name.

        Called by http_authenticator for basic authentication requests.

        Compute the HTTP digest hash A1 part.

        Any domain controller that returns true for `supports_http_digest_auth()`
        MUST implement this method.

        Optionally set environment variables:

            environ["wsgidav.auth.roles"] = (<role>, ...)
            environ["wsgidav.auth.permissions"] = (<perm>, ...)

        Note that in order to calculate A1, we need either

        - Access the plain text password of the user.
          In this case the method `self._compute_http_digest_a1()` can be used
          for convenience.
          Or

        - Return a stored hash value that is associated with the user name
          (for example from Apache's htdigest files).

        Args:
            realm (str):
            user_name (str):
            environ (dict):

        Returns:
            str: MD5("{usern_name}:{realm}:{password}")
            or false if user is unknown or rejected
        r.   )r   r+   r6   r(   s       r   Údigest_auth_userz%BaseDomainController.digest_auth_userÊ   s   € ôD "Ð!r   N)r   Ú
__module__Ú__qualname__Úknown_permissionsÚknown_rolesr   r   r,   r   r0   r2   r4   r8   r:   rA   rC   © r   r   r	   r	   3   s~   „ ð KÐà/€Kòò.òð, ñ"ó ð"ð( ñ"ó ð"ò0	<ð ñ"ó ð"ð* ñ	"ó ð	"ò:ó""r   r	   )Ú__doc__r#   Úabcr   r   Úhashlibr   Úwsgidavr   Ú__docformat__Úget_module_loggerr   r    r	   rH   r   r   ú<module>rO      s>   ðñ#óJ ß #Ý å à"€à	ˆ×	Ñ	 Ó	)€ôy"˜3õ y"r   