Ë
    "ïàj#k  ã                   óì   — d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZmZ ddlmZ ddlmZmZ ddlmZ dd	lmZ dd
lmZmZmZ dZ ej8                  e«      Zd„ Z G d„ de«      Z y)a:  
WSGI middleware for HTTP basic and digest authentication.

Usage::

   from http_authenticator import HTTPAuthenticator

   WSGIApp = HTTPAuthenticator(ProtectedWSGIApp, domain_controller, accept_basic,
                               accept_digest, default_to_digest)

   where:
     ProtectedWSGIApp is the application requiring authenticated access

     domain_controller is a domain controller object meeting specific
     requirements (below)

     accept_basic is a boolean indicating whether to accept requests using
     the basic authentication scheme (default = True)

     accept_digest is a boolean indicating whether to accept requests using
     the digest authentication scheme (default = True)

     default_to_digest is a boolean. if True, an unauthenticated request will
     be sent a digest authentication required response, else the unauthenticated
     request will be sent a basic authentication required response
     (default = True)

The HTTPAuthenticator will put the following authenticated information in the
environ dictionary::

   environ["wsgidav.auth.realm"] = realm name
   environ["wsgidav.auth.user_name"] = user_name
   environ["wsgidav.auth.roles"] = <tuple> (optional)
   environ["wsgidav.auth.permissions"] = <tuple> (optional)


**Domain Controllers**

The HTTP basic and digest authentication schemes are based on the following
concept:

Each requested relative URI can be resolved to a realm for authentication,
for example:
/fac_eng/courses/ee5903/timetable.pdf -> might resolve to realm 'Engineering General'
/fac_eng/examsolns/ee5903/thisyearssolns.pdf -> might resolve to realm 'Engineering Lecturers'
/med_sci/courses/m500/surgery.htm -> might resolve to realm 'Medical Sciences General'
and each realm would have a set of user_name and password pairs that would
allow access to the resource.

A domain controller provides this information to the HTTPAuthenticator.
This allows developers to write their own domain controllers, that might,
for example, interface with their own user database.

for simple applications, a SimpleDomainController is provided that will take
in a single realm name (for display) and a single dictionary of user_name (key)
and password (value) string pairs

Usage::

   from wsgidav.dc.simple_dc import SimpleDomainController
   users = dict(({'John Smith': 'YouNeverGuessMe', 'Dan Brown': 'DontGuessMeEither'})
   realm = 'Sample Realm'
   domain_controller = SimpleDomainController(users, realm)


Domain Controllers must provide the methods as described in
``wsgidav.interfaces.domaincontrollerinterface`` (interface_)

.. _interface : interfaces/domaincontrollerinterface.py

The environ variable here is the WSGI 'environ' dictionary. It is passed to
all methods of the domain controller as a means for developers to pass information
from previous middleware or server config (if required).
é    N)Úmd5)Údedent)ÚunquoteÚurlsplit)Úutil)ÚHTTP_NOT_FOUNDÚDAVError)ÚSimpleDomainController)ÚBaseMiddleware)Úcalc_base64Úcalc_hexdigestÚdynamic_import_classÚreStructuredTextc                 ó  — t        j                  |dd¬«      }|j                  d«      }|}|du s|st        }n t        j                  |«      rt        |«      }t        j                  |«      r || |«      }|S t        d|› d�«      ‚)NÚhttp_authenticatorT©Úas_dictÚdomain_controllerz/Could not resolve domain controller class (got ú))	r   Úget_dict_valueÚgetr
   Úis_basestringr   ÚinspectÚisclassÚRuntimeError)Úwsgidav_appÚconfigÚ	auth_confÚdcÚorg_dcs        úI/srv/dav/.venv/lib/python3.12/site-packages/wsgidav/http_authenticator.pyÚmake_domain_controllerr"   e   sˆ   € Ü×#Ñ# FÐ,@È$ÔO€IØ	�‰Ð*Ó	+€BØ€FØ	ˆT�z™ä#‰Ü	×	Ñ	˜BÔ	ä! "Ó%ˆä‡��rÔá�˜VÓ$ˆð €Iô ÐLÈVÈHÐTUÐVÓWÐWó    c                   óx   ‡ — e Zd ZdZ ed«      Zˆ fd„Zd„ Zd„ Zd„ Z	d„ Z
d„ Zd	„ Zd
„ Zed„ «       Zd„ Zd„ Zˆ xZS )ÚHTTPAuthenticatorz4WSGI Middleware for basic and digest authentication.z¿        <html>
            <head><title>401 Access not authorized</title></head>
            <body>
                <h1>401 Access not authorized</h1>
            </body>
        </html>
    c                 ó”  •— t         ‰| �  |||«       |j                  dd«      | _        || _        t        ||«      }|| _        t        j                  |dd¬«      }|j                  dd«      | _	        |j                  dd«      | _
        |j                  d	d«      | _        t        j                  |d
d¬«      }|j                  dd«      | _        |j                  dd«      | _        |j                  dd«      | _        |j                  dd «      | _        |j!                  «       sF| j                  s| j                  s| j                  s"t#        |j$                  j&                  › d�«      ‚t)        g «      | _        t-        j.                  d«      | _        t-        j.                  d«      | _        t-        j.                  d«      | _        y )NÚverboseé   ÚhotfixesTr   Úwinxp_accept_root_share_loginFÚwin_accept_anonymous_optionsÚdigest_skip_uri_checkr   Úaccept_basicÚaccept_digestÚdefault_to_digestÚtrusted_auth_headerzl does not support digest authentication.
Set accept_basic=True, accept_digest=False, default_to_digest=Falsez\b([\w]+)=([^,]*),z\b([\w]+)=("[^"]*,[^"]*"),z^([\w]+))ÚsuperÚ__init__r   Ú_verboser   r"   r   r   r   r*   r+   r,   r-   r.   r/   r0   Úsupports_http_digest_authr   Ú	__class__Ú__name__ÚdictÚ_nonce_dictÚreÚcompileÚ_header_parserÚ_header_fix_parserÚ_header_method)Úselfr   Únext_appr   r   r)   r   r5   s          €r!   r2   zHTTPAuthenticator.__init__Š   s“  ø€ Ü‰Ñ˜ h°Ô7ØŸ
™
 9¨aÓ0ˆŒØˆŒä# K°Ó8ˆØ!#ˆÔä×&Ñ& v¨zÀ4ÔHˆð
 .6¯\©\Ø+¨Uó.
ˆÔ*ð -5¯L©LØ*¨Eó-
ˆÔ)ð &.§\¡\Ð2IÈ5Ó%QˆÔ"ä×'Ñ'¨Ð0DÈdÔSˆ	à%ŸM™M¨.¸$Ó?ˆÔØ&Ÿ]™]¨?¸DÓAˆÔØ!*§¡Ð/BÀDÓ!IˆÔØ#,§=¡=Ð1FÈÓ#MˆÔ à×+Ñ+Ô-Ø×Ò $×"8Ò"8À×@QÒ@QäØ—<‘<×(Ñ(Ð)ð *Vð Vóð ô
   ›8ˆÔô !Ÿj™jÐ)>Ó?ˆÔô #%§*¡*Ð-JÓ"KˆÔÜ Ÿj™j¨Ó5ˆÕr#   c                 ó   — | j                   S ©N)r   )r>   s    r!   Úget_domain_controllerz'HTTPAuthenticator.get_domain_controllerÅ   s   € Ø×%Ñ%Ð%r#   c                 ó<   — | j                   j                  |d «       S rA   )r   Úrequire_authentication)r>   Úshares     r!   Úallow_anonymous_accessz(HTTPAuthenticator.allow_anonymous_accessÈ   s   € Ø×)Ñ)×@Ñ@ÀÈÓMÐMÐMr#   c                 óx  — | j                   j                  |d   |«      }||d<   d|d<   d |d<   d |d<   d}d|j                  d	d«      v rd
}t        j	                  d«       d}| j
                  r|d   dk(  rt        j	                  d«       d
}|s| j                   j                  ||«      s| j                  ||«      S | j                  rŒ|j                  | j                  «      rqt        j                  d| j                  › d|j                  | j                  «      ›d|›�«       |j                  | j                  «      |d<   | j                  ||«      S d|v �r1|�s.|d   }| j                  j                  |«      }d}|r|j                  d«      j                  «       }|dk(  r| j                  r| j                  ||«      S |dk(  r| j                   r| j#                  ||«      S |dk(  r| j                   r| j%                  ||«      S | j&                  r| j                  r| j)                  ||«      S | j                   r| j#                  ||«      S t        j	                  d|› �«        |dddt+        j,                  «       fg«       dgS | j&                  r| j)                  ||«      S | j#                  ||«      S )NÚ	PATH_INFOúwsgidav.auth.realmÚ úwsgidav.auth.user_namezwsgidav.auth.roleszwsgidav.auth.permissionsFÚlogoutÚQUERY_STRINGTzForce logoutÚREQUEST_METHODÚOPTIONSz,No authorization required for OPTIONS methodzAccept trusted user_name ú=z
for realm ÚHTTP_AUTHORIZATIONÚNoneé   ÚdigestÚbasicz>HTTPAuthenticator: respond with 400 Bad request; Auth-Method: z400 Bad Request)úContent-LengthÚ0ÚDate)r   Úget_domain_realmr   Ú_loggerÚwarningr+   rD   r?   r0   Údebugr=   ÚsearchÚgroupÚlowerr.   Úhandle_digest_auth_requestr-   Úsend_basic_auth_responseÚhandle_basic_auth_requestr/   Úsend_digest_auth_responser   Úget_rfc1123_time)	r>   ÚenvironÚstart_responseÚrealmÚforce_logoutÚforce_allowÚauth_headerÚ
auth_matchÚauth_methods	            r!   Ú__call__zHTTPAuthenticator.__call__Ë   sÈ  € Ø×&Ñ&×7Ñ7¸ÀÑ8LÈgÓVˆà(-ˆÐ$Ñ%Ø,.ˆÐ(Ñ)ð )-ˆÐ$Ñ%Ø.2ˆÐ*Ñ+ð ˆØ�w—{‘{ >°2Ó6Ñ6ØˆLÜ�O‰O˜NÔ+àˆØ×,Ò,°Ð9IÑ1JÈiÒ1WÜ�O‰OÐJÔKØˆKá˜d×4Ñ4×KÑKØ�7ô
ð —=‘= ¨.Ó9Ð9à×#Ò#¨¯©°D×4LÑ4LÔ(Mä�M‰MØ+¨D×,DÑ,DÐ+EÀQÀwÇ{Á{ÐSW×SkÑSkÓGlÐFoÐoyÐzð  zCð  Dôð 18·±¸D×<TÑ<TÓ0UˆGÐ,Ñ-Ø—=‘= ¨.Ó9Ð9à 7Ò*²<Ø!Ð"6Ñ7ˆKØ×,Ñ,×3Ñ3°KÓ@ˆJØ ˆKÙØ(×.Ñ.¨qÓ1×7Ñ7Ó9�à˜hÒ&¨4×+=Ò+=Ø×6Ñ6°wÀÓOÐOØ Ò(¨T×->Ò->Ø×4Ñ4°W¸nÓMÐMØ Ò'¨D×,=Ò,=Ø×5Ñ5°g¸~ÓNÐNð ×'Ò'¨D×,>Ò,>Ø×5Ñ5°g¸~ÓNÐNØ×"Ò"Ø×4Ñ4°W¸nÓMÐMä�O‰OØPÐQ\ÐP]Ð^ôñ Ø!Ø(¨6´4×3HÑ3HÓ3JÐ*KÐLôð �4ˆKà×!Ò!Ø×1Ñ1°'¸>ÓJÐJØ×,Ñ,¨W°nÓEÐEr#   c                 ó0  — | j                   j                  |d   |«      }t        j                  d|›d�«       d|› d�}t	        j
                  | j                  «      } |dd|fdd	t        t        |«      «      fd
t	        j                  «       fg«       |gS )NrH   ú401 Not Authorized for realm z (basic)zBasic realm="ú"ú401 Not AuthorizedúWWW-Authenticate©zContent-Typeztext/html; charset=utf-8rV   rX   )
r   rY   rZ   r\   r   Úto_bytesÚerror_message_401ÚstrÚlenrd   )r>   re   rf   rg   ÚwwwauthheadersÚbodys         r!   ra   z*HTTPAuthenticator.send_basic_auth_response  sœ   € Ø×&Ñ&×7Ñ7¸ÀÑ8LÈgÓVˆÜ�‰Ð5°e°Y¸hÐGÔHØ(¨¨¨qÐ1ˆä�}‰}˜T×3Ñ3Ó4ˆÙØ à# ^Ð4Ø<Ø!¤3¤s¨4£y£>Ð2Øœ×.Ñ.Ó0Ð1ð	ô	
ð ˆvˆr#   c                 ó  — | j                   j                  |d   |«      }|d   }d}	 |t        d«      d  j                  «       }t        j                  t        j                  |«      «      }t        j                  |«      }|j                  dd«      \  }}| j                   j                  ||||«      r||d<   ||d<   | j                  ||«      S t        j                  d	|›d
|›d�«       | j                  ||«      S # t        $ r d}Y ŒÇw xY w)NrH   rQ   rJ   zBasic ú:rS   rI   rK   z'Authentication (basic) failed for user ú, realm ú.)r   rY   rw   ÚstripÚ	ExceptionÚbase64Údecodebytesr   rt   Úto_strÚsplitÚbasic_auth_userr?   rZ   r[   ra   )r>   re   rf   rg   rj   Ú
auth_valueÚ	user_nameÚpasswords           r!   rb   z+HTTPAuthenticator.handle_basic_auth_request)  s  € Ø×&Ñ&×7Ñ7¸ÀÑ8LÈgÓVˆØÐ2Ñ3ˆØˆ
ð	Ø$¤S¨£] _Ð5×;Ñ;Ó=ˆJô ×'Ñ'¬¯©°jÓ(AÓBˆ
Ü—[‘[ Ó,ˆ
Ø(×.Ñ.¨s°AÓ6Ñˆ	�8à×!Ñ!×1Ñ1°%¸ÀHÈgÔVØ,1ˆGÐ(Ñ)Ø09ˆGÐ,Ñ-Ø—=‘= ¨.Ó9Ð9ä�‰Ø5°i°]À(È5È)ÐSTÐUô	
ð ×,Ñ,¨W°nÓEÐEøô ò 	ØŠJð	ús   ¨C> Ã>DÄDc                 ó  — | j                   j                  |d   |«      }t        j                  d«      }t	        |d   «      }t        t        j                  «       «      }|t	        |dz   |z   dz   |z   «      z   }t        |«      }d|› d|› d�}	t        j                  d|›d|	› �«       t        j                  | j                  «      }
 |d	d
|	fddt        t        |
«      «      fdt        j                  «       fg«       |
gS )NrH   é   r{   zDigest realm="z
", nonce="z", algorithm=MD5, qop="auth"ro   z (digest): rq   rr   rs   rV   rX   )r   rY   ÚsecretsÚ	token_hexr   rv   Útimer   rZ   r\   r   rt   ru   rw   rd   )r>   re   rf   rg   Ú	serverkeyÚetagkeyÚtimekeyÚnonce_sourceÚnoncerx   ry   s              r!   rc   z+HTTPAuthenticator.send_digest_auth_response@  s  € Ø×&Ñ&×7Ñ7¸ÀÑ8LÈgÓVˆô ×%Ñ% bÓ)ˆ	Ü  ¨Ñ!5Ó6ˆÜ”d—i‘i“kÓ"ˆØ¤Ø�c‰M˜GÑ# cÑ)¨IÑ5ó"
ñ 
ˆô ˜LÓ)ˆà˜U˜G :¨e¨WÐ4PÐQð 	ô 	�‰Ø+¨E¨9°KÀÐ?OÐPô	
ô �}‰}˜T×3Ñ3Ó4ˆÙØ à# ^Ð4Ø<Ø!¤3¤s¨4£y£>Ð2Øœ×.Ñ.Ó0Ð1ð	ô	
ð ˆvˆr#   c                 ó	  — | j                   j                  |d   |«      }|st        t        d|d   › �¬«      ‚d}g }i }|d   dz   }|j	                  «       j                  «       j                  d«      sd}|j                  d	|› �«       | j                  j                  |«      }| j                  j                  |«      }	|	r t        j                  d
|› d|	› �«       ||	z  }|D ].  }
|
d   }|
d   j                  «       j                  d«      }|||<   Œ0 d }d|v rR|d   }|sd}|j                  d|›�«       nGd|v rC|}|j                  dd«      }t        j                  d|›d|›�«       nd}|j                  d«       d|v rd|d   j                  «       |j                  «       k7  r@| j                  r|d   dk(  rt        j                  d«       nd}|j                  d|›�«       d|v r)|d   j                  «       dk7  rd}|j                  d«       |j!                  d«      }| j#                  ||«      sd}|j                  d|›d�«       d |v r|d    }nd}|j                  d!«       d}d"|v r.d}|d"   }|j	                  «       d#k7  rd}|j                  d$«       nd }d%|v r|d%   }nd }|rd}|j                  d&«       d'|v r|d'   }nd }|rd}|j                  d(«       d)|v r|d)   }nd}|j                  d*«       |sâ|d+   }| j%                  ||||||||«	      }|sd}|j                  d,|›d-|›d.�«       n§t'        j(                  |«      s�d/|›d-|›d0�}| j                  rg|dk7  rb| j%                  d||||||||«	      }|r0t'        j(                  ||«      rt        j+                  d1|›d2�«       n,d}|j                  |d3z   «       nd}|j                  |«       n	 |r‡|j                  d4|› �«       | j,                  d5k\  r6t        j+                  d6j/                  ||d7j1                  |«      «      «       nt        j+                  d8|›d9|›d2�«       | j3                  ||«      S ||d:<   ||d;<   | j5                  ||«      S )<NrH   zCould not resolve realm for )Úcontext_infoFrQ   ú,rT   Tz-HTTP_AUTHORIZATION must start with 'digest': z)Fixing auth_header comma-parsing: extend z with r   rS   rp   Úusernamez`username` is empty: z\\ú\z+Fixing Windows name with double backslash: z --> zMissing 'username' in headersrg   ú/r*   zRealm mismatch: Ú	algorithmÚMD5z"Unsupported 'algorithm' in headersÚurizDigest 'uri' z" does not match the request targetr‘   zExpected 'nonce' in headersÚqopÚauthzExpected 'qop' == 'auth'Úcnoncez-Expected 'cnonce' in headers if qop is passedÚncz)Expected 'nc' in headers if qop is passedÚresponsezExpected 'response' in headersrN   z Rejected by DC.digest_auth_user(z, r   z_compute_digest_response(z, ...): digest mismatchz<handle_digest_auth_request: HOTFIX: accepting '/' login for r}   z (also tried '/' realm)zHeaders:
    é   z>Authentication (digest) failed for user {!r}, realm {!r}:
  {}z
  z(Authentication (digest) failed for user r|   rI   rK   )r   rY   r	   r   r_   r~   Ú
startswithÚappendr;   Úfindallr<   rZ   ÚinfoÚreplaceÚupperr*   r   Ú_is_digest_uri_validÚ_compute_digest_responseÚhmacÚcompare_digestr[   r3   ÚformatÚjoinrc   r?   )r>   re   rf   rg   Úis_invalid_reqÚinvalid_req_reasonsÚauth_header_dictÚauth_headersÚauth_header_listÚauth_header_fixlistrj   Úauth_header_keyÚauth_header_valueÚreq_usernameÚreq_username_orgÚreq_uriÚ	req_nonceÚreq_has_qopÚreq_qopÚ
req_cnonceÚreq_ncÚreq_responseÚ
req_methodÚrequired_digestÚwarning_msgÚroot_digests                             r!   r`   z,HTTPAuthenticator.handle_digest_auth_request_  s‹  € Ø×&Ñ&×7Ñ7¸ÀÑ8LÈgÓVˆáÜÜØ;¸GÀKÑ<PÐ;QÐRôð ð
 ˆØ ÐàÐØÐ3Ñ4°sÑ:ˆØ×!Ñ!Ó#×)Ñ)Ó+×6Ñ6°xÔ@Ø!ˆNØ×&Ñ&Ø?À¸~ÐNôð  ×.Ñ.×6Ñ6°|ÓDÐØ"×5Ñ5×=Ñ=¸lÓKÐÙÜ�L‰LØ;Ð<LÐ;MÈVÐTgÐShÐiôð Ð 3Ñ3Ðà+ò 	BˆKØ)¨!™nˆOØ +¨A¡× 4Ñ 4Ó 6× <Ñ <¸SÓ AÐØ0AÐ˜_Ò-ð	Bð ˆØÐ)Ñ)Ø+¨JÑ7ˆLÙØ!%�Ø#×*Ñ*Ð-BÀ<ÐBRÐ+SÕTØ˜,Ñ&ð
 $0Ð Ø+×3Ñ3°F¸DÓA�Ü—‘ØAÐBRÐAUÐUZÐ[gÐZjÐkõð "ˆNØ×&Ñ&Ð'FÔGð
 Ð&Ñ&Ø Ñ(×.Ñ.Ó0°E·K±K³MÒAà×6Ò6Ø(¨Ñ1°SÒ8ô —L‘LÐ!@ÕAà%)�NØ'×.Ñ.Ð1AÀ%ÀÐ/KÔLàÐ*Ñ*Ø Ñ,×2Ñ2Ó4¸Ò=Ø!%�Ø#×*Ñ*Ð+OÔPà"×&Ñ& uÓ-ˆà×(Ñ(¨°'Ô:Ø!ˆNØ×&Ñ&Ø ˜{Ð*LÐMôð Ð&Ñ&Ø(¨Ñ1‰Ià!ˆNØ×&Ñ&Ð'DÔEàˆØÐ$Ñ$ØˆKØ& uÑ-ˆGØ�}‰}‹ &Ò(Ø!%�Ø#×*Ñ*Ð+EÕFàˆGàÐ'Ñ'Ø)¨(Ñ3‰JàˆJÙØ!%�Ø#×*Ñ*ØCôð Ð#Ñ#Ø% dÑ+‰FàˆFÙØ!%�Ø#×*Ñ*Ð+VÔWàÐ)Ñ)Ø+¨JÑ7‰Là!ˆNØ×&Ñ&Ð'GÔHáØ Ð!1Ñ2ˆJà"×;Ñ;ØØØØØØØØØó
ˆOñ #à!%�Ø#×*Ñ*Ø6°u°i¸rÀ,ÐAQÐQRÐSõô ×(Ñ(¨¸,ÔGð !:¸%¸À"À\ÐDTÐTkÐl�Ø×5Ò5¸%À3º,ð #'×"?Ñ"?ØØ$Ø"ØØ!Ø"ØØØó
#�Kñ #¤t×':Ñ':¸;ÈÔ'UÜŸ™ØZÐ[`ÐZcÐcdÐeõð *.˜Ø+×2Ñ2Ø'Ð*CÑCõð &*�NØ'×.Ñ.¨{Õ;ð áØ×&Ñ&¨Ð8HÐ7IÐ'JÔKØ�}‰} Ò!Ü—‘ØU×\Ñ\Ø$ e¨V¯[©[Ð9LÓ-Móõô —‘Ø>¸|Ð>NÈhÐW\ÐV_Ð_`Ðaôð ×1Ñ1°'¸>ÓJÐJà(-ˆÐ$Ñ%Ø,8ˆÐ(Ñ)Ø�}‰}˜W nÓ5Ð5r#   c                 óL   — 	 t        j                  | «      S # t        $ r Y yw xY w)z?Return a comparable form of `path`, or None if it is not valid.N)r   Únormalize_pathr	   )Úpaths    r!   Ú_canonical_pathz!HTTPAuthenticator._canonical_path5  s*   € ð	Ü×&Ñ& tÓ,Ð,øÜò 	áð	ús   ‚ —	#¢#c                 óð  — | j                   ry|syt        |«      }|j                  d«      dk(  rH|j                  d«      xs |j                  d«      dk(  s|j                  d«      d	v r|j                  d
v S |j                  |j                  dd«      k7  ry| j                  t        |j                  «      «      }|€y|j                  dd«      |j                  dd«      z   }|| j                  |«      k(  S )a…  Return True if the Authorization header's `uri` matches the request.

        RFC 7616, section 3.4.6:

            The authenticating server MUST verify that the resource
            designated by the "uri" parameter is the same as the resource
            specified in the Request-Line.

        The digest is computed over the `uri` taken from the header, while the
        request is served for ``PATH_INFO``. Without this check, an
        ``Authorization: Digest ...`` header that was captured for one resource
        authenticates requests for *any other* resource in the same realm,
        using the captured method (CWE-294).
        TFrN   rO   ÚREQUEST_URIÚRAW_URIÚ*rH   )rÉ   ú/*)rÉ   rÊ   r—   rM   rJ   ÚSCRIPT_NAME)r,   r   r   rÄ   ÚqueryrÅ   r   )r>   r·   re   ÚpartsÚreq_pathÚtarget_paths         r!   r§   z&HTTPAuthenticator._is_digest_uri_valid>  sé   € ð ×%Ò%ØÙØô ˜Ó!ˆð �;‰;Ð'Ó(¨IÒ5Ø�[‰[˜Ó'ÒA¨7¯;©;°yÓ+AÀcÒIØ�{‰{˜;Ó'¨;Ñ6à—:‘:Ð!1Ð1Ð1à�;‰;˜'Ÿ+™+ n°bÓ9Ò9Øà×'Ñ'¬°·
±
Ó(;Ó<ˆØÐØØ—k‘k -°Ó4°w·{±{À;ÐPRÓ7SÑSˆØ˜4×/Ñ/°Ó<Ñ<Ð<r#   c
                 óè   ‡— d„ Šˆfd„}
| j                   j                  |||	«      }|sy|dz   |z   }|r) |
||dz   |z   dz   |z   dz   |z   dz    ‰|«      z   «      }|S  |
||dz    ‰|«      z   «      }|S )a`  Computes digest hash.

        Calculation of the A1 (HA1) part is delegated to the dc interface method
        `digest_auth_user()`.

        Args:
            realm (str):
            user_name (str):
            method (str): WebDAV Request Method
            uri (str):
            nonce (str): server generated nonce value
            cnonce (str): client generated cnonce value
            qop (str): quality of protection
            nc (str) (number), nonce counter incremented by client
        Returns:
            MD5 hash string
            or False if user rejected by domain controller
        c                 óZ   — t        t        j                  | «      «      j                  «       S rA   )r   r   rt   Ú	hexdigest)Údatas    r!   Úmd5hz8HTTPAuthenticator._compute_digest_response.<locals>.md5h  s   € Ü”t—}‘} TÓ*Ó+×5Ñ5Ó7Ð7r#   c                 ó    •—  ‰| dz   |z   «      S )Nr{   © )ÚsecretrÓ   rÔ   s     €r!   Úmd5kdz9HTTPAuthenticator._compute_digest_response.<locals>.md5kd‚  s   ø€ Ù˜ ™ tÑ+Ó,Ð,r#   Fr{   )r   Údigest_auth_user)r>   rg   r†   Úmethodrš   r‘   r�   r›   rž   re   rØ   ÚA1ÚA2ÚresrÔ   s                 @r!   r¨   z*HTTPAuthenticator._compute_digest_responsei  s¡   ø€ ò,	8ô	-ð ×#Ñ#×4Ñ4°U¸IÀwÓOˆÙØà�c‰\˜CÑˆáÙØ�E˜C‘K "Ñ$ sÑ*¨VÑ3°cÑ9¸CÑ?À#ÑEÉÈRËÑPóˆCð ˆ
ñ ˜˜E C™K©$¨r«(Ñ2Ó3ˆCàˆ
r#   )r6   Ú
__module__Ú__qualname__Ú__doc__r   ru   r2   rB   rF   rm   ra   rb   rc   r`   ÚstaticmethodrÅ   r§   r¨   Ú__classcell__)r5   s   @r!   r%   r%   |   se   ø„ Ù>áð	ó	Ðô96òv&òNòKFòZò"Fò.ò>T6ðl ñó ðò)=öV)r#   r%   )!rà   r€   r©   r   r9   rŠ   rŒ   Úhashlibr   Útextwrapr   Úurllib.parser   r   Úwsgidavr   Úwsgidav.dav_errorr   r	   Úwsgidav.dc.simple_dcr
   Úwsgidav.mw.base_mwr   Úwsgidav.utilr   r   r   Ú__docformat__Úget_module_loggerr6   rZ   r"   r%   rÖ   r#   r!   ú<module>rí      se   ðñ
IóV Û Û Û 	Û Û Ý Ý ß *å ß 6Ý 7Ý -ß JÑ Jà"€à
 ˆ$×
 Ñ
  Ó
*€òô.V˜õ Vr#   