
    qi7]                         S r SSKrSSKrSSKrSSKrSSKrSSKJr  SSKJ	r	  SSK
Jr  SSKJrJr  SSKJr  SSKJr  SS	KJrJrJr  S
r\R0                  " \5      rS r " S S\5      rg)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)util)HTTP_NOT_FOUNDDAVError)SimpleDomainController)BaseMiddleware)calc_base64calc_hexdigestdynamic_import_classreStructuredTextc                 .   [         R                  " USSS9nUR                  S5      nUnUSL d  U(       d  [        nO&[         R                  " U5      (       a  [        U5      n[        R                  " U5      (       a
  U" X5      nU$ [        SU S35      e)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        O/home/kali/flask_env/lib/python3.13/site-packages/wsgidav/http_authenticator.pymake_domain_controllerr    b   s    ##F,@$OI	*	+BF	Tz#			B		!"%r$ I LVHTUVWW    c                   l   ^  \ rS rSrSr\" S5      rU 4S jrS rS r	S r
S rS	 rS
 rS rS rSrU =r$ )HTTPAuthenticatory   z4WSGI 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U ]  XU5        UR                  SS5      U l        X0l        [        X5      nX@l        [        R                  " USSS9nUR                  SS5      U l	        UR                  SS5      U l
        [        R                  " US	SS9nUR                  S
S5      U l        UR                  SS5      U l        UR                  SS5      U l        UR                  SS 5      U l        UR                  5       (       dU  U R                  (       d"  U R                  (       d  U R                  (       d"  [!        UR"                  R$                   S35      e['        / 5      U l        [*        R,                  " S5      U l        [*        R,                  " S5      U l        [*        R,                  " S5      U l        g )Nverbose   hotfixesTr   winxp_accept_root_share_loginFwin_accept_anonymous_optionsr   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([\w]+)=([^,]*),z([\w]+)=("[^"]*,[^"]*"),z^([\w]+))super__init__r   _verboser   r    r   r   r   r)   r*   r+   r,   r-   r.   supports_http_digest_authr   	__class____name__dict_nonce_dictrecompile_header_parser_header_fix_parser_header_method)selfr   next_appr   r   r(   r   r3   s          r   r0   HTTPAuthenticator.__init__   sx   7

9a0#K8!#&&vz4H
 .6\\+U.
* -5LL*E-
) ''0DdS	%MM.$?&]]?DA!*/BD!I#,==1F#M ++--$"8"8@Q@Q<<(() *V V 
  8 jj)<= #%**-H"I jj5r!   c                     U R                   $ N)r   )r<   s    r   get_domain_controller'HTTPAuthenticator.get_domain_controller   s    %%%r!   c                 D    U R                   R                  US 5      (       + $ r@   )r   require_authentication)r<   shares     r   allow_anonymous_access(HTTPAuthenticator.allow_anonymous_access   s    ))@@MMMr!   c                    U R                   R                  US   U5      nX1S'   SUS'   S US'   S US'   SnSUR                  S	S5      ;   a  S
n[        R	                  S5        SnU R
                  (       a   US   S:X  a  [        R	                  S5        S
nU(       d   U R                   R                  X15      (       d  U R                  X5      $ U R                  (       a  UR                  U R                  5      (       ar  [        R                  SU R                   SUR                  U R                  5      < SU< 35        UR                  U R                  5      US'   U R                  X5      $ SU;   GaX  U(       GdP  US   nU R                  R                  U5      nSnU(       a  UR                  S5      R                  5       nUS:X  a"  U R                  (       a  U R                  X5      $ US:X  a"  U R                   (       a  U R#                  X5      $ US:X  a"  U R                   (       a  U R%                  X5      $ U R&                  (       a"  U R                  (       a  U R)                  X5      $ U R                   (       a  U R#                  X5      $ [        R	                  SU 35        U" SSS[*        R,                  " 5       4/5        S/$ U R&                  (       a  U R)                  X5      $ U R#                  X5      $ )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=   r.   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__HTTPAuthenticator.__call__   s   &&778LgV(-$%,.() )-$%.2*+ w{{>266LOON+,,9I1Ji1WOOJKKd44KK
 
 ==99##D4L4L(M(MMM+D,D,D+EQw{{SWSkSkGlFooyz  zC  D 18D<T<T0UG,-==997*<!"67K,,33K@J K(..q1779h&4+=+=66wOO(T->->44WMM'D,=,=55gNN ''D,>,>55gNN""44WMMOOPQ\P]^ !(643H3H3J*KL 4K!!11'JJ,,WEEr!   c                 6   U R                   R                  US   U5      n[        R                  SU< S35        SU S3n[        R
                  " U R                  5      nU" SSU4SS	[        [        U5      5      4S
[        R                  " 5       4/5        U/$ )NrI   401 Not Authorized for realm z (basic)zBasic realm=""401 Not AuthorizedWWW-AuthenticatezContent-Typeztext/html; charset=utf-8rW   rY   )
r   rZ   r[   r]   r   to_byteserror_message_401strlenre   )r<   rf   rg   rh   wwwauthheadersbodys         r   rb   *HTTPAuthenticator.send_basic_auth_response	  s    &&778LgV5eYhGH(q1}}T334 #^4<!3s4y>2..01		
 vr!   c                 &   U R                   R                  US   U5      nUS   nSn U[        S5      S  R                  5       n[
        R                  " [        R                  " U5      5      n[        R                  " U5      nUR                  SS5      u  pgU R                   R                  X6Xq5      (       a  X1S'   XaS'   U R                  X5      $ [        R                  S	U< S
U< S35        U R                  X5      $ ! [         a    Sn Nf = f)NrI   rR   rK   zBasic :rT   rJ   rL   z'Authentication (basic) failed for user , realm .)r   rZ   ry   strip	Exceptionbase64decodebytesr   rv   to_strsplitbasic_auth_userr=   r[   r\   rb   )r<   rf   rg   rh   rk   
auth_value	user_namepasswords           r   rc   +HTTPAuthenticator.handle_basic_auth_request  s   &&778LgV23
	$S]_5;;=J ''j(AB
[[,
(..sA6	!!11%HVV,1()09,-==995i](5)STU	
 ,,WEE  	J	s   D DDc                 P   U R                   R                  US   U5      n[        R                  " 5         [	        [        R
                  " S5      5      SS  n[        US   5      n[        [        R                  " 5       5      nU[        US-   U-   S-   U-   5      -   n[        U5      nSU SU S3n	[        R                  SU< S	U	 35        [        R                  " U R                  5      n
U" S
SU	4SS[        [        U
5      5      4S[        R                   " 5       4/5        U
/$ )NrI          r~   zDigest realm="z
", nonce="z", algorithm=MD5, qop="auth"rq   z (digest): rs   rt   ru   rW   rY   )r   rZ   randomseedhexgetrandbitsr   rx   timer
   r[   r]   r   rv   rw   ry   re   )r<   rf   rg   rh   	serverkeyetagkeytimekeynonce_sourcenoncerz   r{   s              r   rd   +HTTPAuthenticator.send_digest_auth_response1  s(   &&778LgV**2./3	 !56diik"cMG#c)I5"
 
 L)UG:eW4PQ 	 	+E9K?OP	
 }}T334 #^4<!3s4y>2..01		
 vr!   c                 ,	   U R                   R                  US   U5      nU(       d  [        [        SUS    3S9eSn/ n0 nUS   S-   nUR	                  5       R                  5       R                  S5      (       d  SnUR                  S	U 35        U R                  R                  U5      nU R                  R                  U5      n	U	(       a  [        R                  S
U SU	 35        X-  nU H.  n
U
S   nU
S   R                  5       R                  S5      nXU'   M0     S nSU;   a\  US   nU(       d  SnUR                  SU< 35        OKSU;   a1  UnUR                  SS5      n[        R                  SU< SU< 35        OSnUR                  S5        SU;   al  US   R                  5       UR                  5       :w  aG  U R                  (       a  US   S:X  a  [        R                  S5        OSnUR                  SU< 35        SU;   a*  US   R                  5       S:w  a  SnUR                  S5        UR!                  S5      nSU;   a  US   nOSnUR                  S5        SnS U;   a/  SnUS    nUR	                  5       S!:w  a  SnUR                  S"5        OS nS#U;   a  US#   nOS nU(       a  SnUR                  S$5        S%U;   a  US%   nOS nU(       a  SnUR                  S&5        S'U;   a  US'   nOSnUR                  S(5        U(       d  US)   nU R#                  UUUUWUUUU5	      nU(       d  SnUR                  S*U< S+U< S,35        OUW:w  a  S-U< S+U< S.U S/U 3nU R                  (       aW  US:w  aQ  U R#                  SUUUUUUUU5	      nUU:X  a  [        R%                  S0U< S135        O,SnUR                  US2-   5        OSnUR                  U5        O U(       a  UR                  S3U 35        U R&                  S4:  a5  [        R%                  S5R)                  XS6R+                  U5      5      5        O[        R%                  S7U< S8U< S135        U R-                  X5      $ X1S9'   XS:'   U R/                  X5      $ );NrI   zCould not resolve realm for )context_infoFrR   ,rU   Tz-HTTP_AUTHORIZATION must start with 'digest': z)Fixing auth_header comma-parsing: extend z with r   rT   rr   usernamez`username` is empty: z\\\z+Fixing Windows name with double backslash: z --> zMissing 'username' in headersrh   /r)   zRealm mismatch: 	algorithmMD5z"Unsupported 'algorithm' in headersurir   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 headersrO   z Rejected by DC.digest_auth_user(z, r   z_compute_digest_response(z, ...): z != z<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   rJ   rL   )r   rZ   r   r   r`   r   
startswithappendr9   findallr:   r[   inforeplaceupperr)   r   _compute_digest_responser\   r1   formatjoinrd   r=   )r<   rf   rg   rh   is_invalid_reqinvalid_req_reasonsauth_header_dictauth_headersauth_header_listauth_header_fixlistrk   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   ra   ,HTTPAuthenticator.handle_digest_auth_requestO  sE   &&778LgV;GK<P;QR 
  34s:!!#))+66x@@!N&&?~N  ..66|D"55==lKLL;<L;MVTgShi 3+K)!nO +A 4 4 6 < <S A0A_- , ))+J7L!%#**-B<BR+ST,&
 $0 +33FDAABRAUUZ[gZjk "N&&'FG
 &&(..0EKKMA66(1S8 LL!@A%)N'..1A%/KL**,224=!%#**+OP"&&u-&&(1I!N&&'DE$$K&u-G}}&(!%#**+EFG'')(3JJ!%#**C ##%d+FF!%#**+VW))+J7L!N&&'GH !12J";;
O #!%#**6uir,AQQRS !L0 9%"\DTT\]l\mmqr~q  A55%3, #'"?"?$"!"
#K #l2Z[`Zccde *.+22'*CC &*N'..{; &&8H7I'JK}}!U\\$V[[9L-M >|>NhW\V__`a 11'JJ(-$%,8()}}W55r!   c
                    ^ S mU4S jn
U R                   R                  XU	5      nU(       d  gUS-   U-   nU(       a(  U
" XS-   U-   S-   U-   S-   U-   S-   T" U5      -   5      nU$ U
" XS-   T" U5      -   5      nU$ )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                 \    [        [        R                  " U 5      5      R                  5       $ r@   )r   r   rv   	hexdigest)datas    r   md5h8HTTPAuthenticator._compute_digest_response.<locals>.md5h4  s    t}}T*+5577r!   c                     > T" U S-   U-   5      $ )Nr~    )secretr   r   s     r   md5kd9HTTPAuthenticator._compute_digest_response.<locals>.md5kd7  s    t+,,r!   Fr~   )r   digest_auth_user)r<   rh   r   methodr   r   r   r   r   rf   r   A1A2resr   s                 @r   r   *HTTPAuthenticator._compute_digest_response  s    ,	8	- ##44UwOc\CCK"$s*V3c9C?#ERPC 
 CK$r(23C
r!   )r:   r;   r9   r6   r1   r+   r,   r   r-   r   r.   r*   r)   )r4   
__module____qualname____firstlineno____doc__r   rw   r0   rA   rF   rn   rb   rc   rd   ra   r   __static_attributes____classcell__)r3   s   @r   r#   r#   y   sP    >		-6^&NKFZ"F.<M6^) )r!   r#   )r   r   r   r   r7   r   hashlibr   textwrapr   wsgidavr   wsgidav.dav_errorr   r   wsgidav.dc.simple_dcr   wsgidav.mw.base_mwr	   wsgidav.utilr
   r   r   __docformat__get_module_loggerr4   r[   r    r#   r   r!   r   <module>r      s]   
IT    	     6 7 - J J"

 
 
*.N Nr!   