
    2h*B                        % S r SSKrSSKrSSKrSSKrSSKJrJrJrJ	r	J
r
JrJrJrJr  SSKJ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\SS9r\R:                  \R:                  \R<                  \R<                  \R>                  \R>                  \R>                  \R>                  \R@                  \R@                  \R@                  \R@                  S.r!\\"\\#/S4   4   \$S'   \RJ                  " S5      r&Sr'\\\S   S4      \$S'   \(" \)" \!RU                  5       5      5      r+\\\"S4      \$S'   \," 1 Sk5      r-\\	\"      \$S'   S\"S\"4S jr.S\"S\"4S jr/S\"S\\"\"4   4S jr0 " S S 5      r1g)!av  
Digest authentication middleware for aiohttp client.

This middleware implements HTTP Digest Authentication according to RFC 7616,
providing a more secure alternative to Basic Authentication. It supports all
standard hash algorithms including MD5, SHA, SHA-256, SHA-512 and their session
variants, as well as both 'auth' and 'auth-int' quality of protection (qop) options.
    N)	CallableDictFinal	FrozenSetListLiteralTuple	TypedDictUnion)URL   )hdrs)ClientError)ClientHandlerType)ClientRequestClientResponse)Payloadc                   \    \ rS rSr% \\S'   \\S'   \\S'   \\S'   \\S'   \\S'   \\S'   S	rg
)DigestAuthChallenge#   realmnonceqop	algorithmopaquedomainstale N)__name__
__module____qualname____firstlineno__str__annotations____static_attributes__r       ]/var/www/auris/envauris/lib/python3.13/site-packages/aiohttp/client_middleware_digest_auth.pyr   r   #   s%    JJ	HNKKJr&   r   F)total)MD5zMD5-SESSSHAzSHA-SESSSHA256zSHA256-SESSzSHA-256zSHA-256-SESSSHA512zSHA512-SESSzSHA-512zSHA-512-SESSzhashlib._HashDigestFunctionsz-(\w+)\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([^\s,]+)))r   r   r   r   r   r   r   .CHALLENGE_FIELDSSUPPORTED_ALGORITHMS>   urir   r   cnoncer   responseusernameQUOTED_AUTH_FIELDSvaluereturnc                 &    U R                  SS5      $ )z,Escape double quotes for HTTP header values."\"replacer5   s    r'   escape_quotesr=   q   s    ==e$$r&   c                 &    U R                  SS5      $ )z-Unescape double quotes in HTTP header values.r9   r8   r:   r<   s    r'   unescape_quotesr?   v   s    ==$$r&   headerc           	          [         R                  U 5       VVVs0 s H3  u  pnUR                  5       =n(       d  M  XB(       a  [        U5      OU_M5     snnn$ s  snnnf )aI  
Parse key-value pairs from WWW-Authenticate or similar HTTP headers.

This function handles the complex format of WWW-Authenticate header values,
supporting both quoted and unquoted values, proper handling of commas in
quoted values, and whitespace variations per RFC 7616.

Examples of supported formats:
  - key1="value1", key2=value2
  - key1 = "value1" , key2="value, with, commas"
  - key1=value1,key2="value2"
  - realm="example.com", nonce="12345", qop="auth"

Args:
    header: The header value string to parse

Returns:
    Dictionary mapping parameter names to their values
)_HEADER_PAIRS_PATTERNfindallstripr?   )r@   key
quoted_valunquoted_valstripped_keys        r'   parse_header_pairsrI   {   s\    , .C-J-J6-R-R)C\IIK'L' 	RZoj1\Q-R  s
   AAc            	           \ rS rSrSr SS\S\S\SS4S jjrS	\S
\S\	\
\S   4   S\4S jrS
\S\4S jrS\S\4S jrS\S\S\4S jrSrg)DigestAuthMiddleware   a  
HTTP digest authentication middleware for aiohttp client.

This middleware intercepts 401 Unauthorized responses containing a Digest
authentication challenge, calculates the appropriate digest credentials,
and automatically retries the request with the proper Authorization header.

Features:
- Handles all aspects of Digest authentication handshake automatically
- Supports all standard hash algorithms:
  - MD5, MD5-SESS
  - SHA, SHA-SESS
  - SHA256, SHA256-SESS, SHA-256, SHA-256-SESS
  - SHA512, SHA512-SESS, SHA-512, SHA-512-SESS
- Supports 'auth' and 'auth-int' quality of protection modes
- Properly handles quoted strings and parameter parsing
- Includes replay attack protection with client nonce count tracking
- Supports preemptive authentication per RFC 7616 Section 3.6

Standards compliance:
- RFC 7616: HTTP Digest Access Authentication (primary reference)
- RFC 2617: HTTP Authentication (deprecated by RFC 7616)
- RFC 1945: Section 11.1 (username restrictions)

Implementation notes:
The core digest calculation is inspired by the implementation in
https://github.com/requests/requests/blob/v2.18.4/requests/auth.py
with added support for modern digest auth features and error handling.
loginpassword
preemptiver6   Nc                    Uc  [        S5      eUc  [        S5      eSU;   a  [        S5      eXl        UR                  S5      U l        UR                  S5      U l        SU l        SU l        0 U l        X0l        / U l	        g )Nz"None is not allowed as login valuez%None is not allowed as password value:z8A ":" is not allowed in username (RFC 1945#section-11.1)utf-8r&   r   )

ValueError
_login_strencode_login_bytes_password_bytes_last_nonce_bytes_nonce_count
_challenge_preemptive_protection_space)selfrM   rN   rO   s       r'   __init__DigestAuthMiddleware.__init__   s     =ABBDEE%<WXX&+*/,,w*?-5__W-E!$/1!+,.r&   methodurlbodyr&   c           
      r	  ^"^##    U R                   nSU;  a  [        S5      eSU;  a  [        S5      eUS   nUS   nU(       d  [        S5      eUR                  SS5      nUR                  SS	5      R                  5       nUR                  S
S5      n	UR	                  S5      n
UR	                  S5      n[        U5      R                  nSnSnU(       a  SS1R                  UR                  S5       Vs1 s H)  oR                  5       (       d  M  UR                  5       iM+     sn5      nU(       d  [        SU 35      eSU;   a  SOSnUR	                  S5      nU[        ;  a$  [        SU SSR                  [        5       35      e[        U   m#S[        S[        4U#4S jjm"S[        S[        S[        4U"4S jjnSR                  U R                  XR                  45      nUR                  5        SU 3R	                  5       nUS:X  aK  [!        U["        5      (       a  UR%                  5       I Sh  vN nOUnT"" U5      nSR                  UU45      nT"" U5      nT"" U5      nXR&                  :X  a  U =R(                  S-  sl        OSU l        Xl        U R(                  S nUR	                  S5      n[*        R,                  " SR                  [/        U R(                  5      R	                  S5      U
[0        R2                  " 5       R	                  S5      [4        R6                  " S5      /5      5      R9                  5       SS  nUR	                  S5      nUR                  5       R;                  S!5      (       a  T"" SR                  UU
U45      5      nU(       a   SR                  U
UUUU45      nU" UU5      nOU" USR                  U
U45      5      n[=        U R>                  5      [=        U5      [=        U5      UURA                  5       US".nU	(       a  [=        U	5      US
'   U(       a  UUS'   UUS#'   UUS$'   / nURC                  5        H?  u  n n!U [D        ;   a  URG                  U  S%U! S&35        M)  URG                  U  S'U! 35        MA     S(SR                  U5       3$ s  snf  GN{7f))a}  
Build digest authorization header for the current challenge.

Args:
    method: The HTTP method (GET, POST, etc.)
    url: The request URL
    body: The request body (used for qop=auth-int)

Returns:
    A fully formatted Digest authorization header string

Raises:
    ClientError: If the challenge is missing required parameters or
                 contains unsupported values

r   z:Malformed Digest auth challenge: Missing 'realm' parameterr   z:Malformed Digest auth challenge: Missing 'nonce' parameterzBSecurity issue: Digest auth challenge contains empty 'nonce' valuer    r   r)   r   rR   r&   authzauth-int,zEDigest auth error: Unsupported Quality of Protection (qop) value(s): z/Digest auth error: Unsupported hash algorithm: z. Supported algorithms: z, xr6   c                 L   > T" U 5      R                  5       R                  5       $ )z<RFC 7616 Section 3: Hash function H(data) = hex(hash(data)).)	hexdigestrU   )rg   hash_fns    r'   H'DigestAuthMiddleware._encode.<locals>.H  s    1:'')0022r&   sdc                 4   > T" SR                  X45      5      $ )zDRFC 7616 Section 3: KD(secret, data) = H(concat(secret, ":", data)).   :)join)rm   rn   rk   s     r'   KD(DigestAuthMiddleware._encode.<locals>.KD  s    TYYv&''r&   rp   rQ   Nr   08x      z-SESS)r3   r   r   r0   r2   r   ncr1   z="r8   =zDigest )$rZ   r   getupperrU   r   path_qsintersectionsplitrD   r-   rq   r/   bytesrV   rW   
isinstancer   as_bytesrX   rY   hashlibsha1r#   timectimeosurandomri   endswithr=   rT   decodeitemsr4   append)$r]   r`   ra   rb   	challenger   r   qop_rawr   r   nonce_bytesrealm_bytespathr   	qop_bytesq
valid_qopsrr   A1A2entity_bytesentity_hashHA1HA2ncvaluencvalue_bytesr1   cnonce_bytesnoncebitresponse_digestheader_fieldspairsfieldr5   rk   rj   s$                                     @@r'   _encodeDigestAuthMiddleware._encode   s    & OO	)#L  )#L 
 '"'" T  --r*MM+u5;;=	x, ll7+ll7+3x 	 *-::$+MM#$6D$6q'')$6DJ ![\c[de  !+j 8*fC

7+IO+A) M))-3G)H(IK  )3	3 	35 	3	(% 	(E 	(e 	(
 YY));8L8LMNq'..0*$((%)]]_4#L/KB,-Bee 000" !D!,&&s+w/ HH))*11':JJL''0JJqM		
 )+cr	 }}W- ??%%g..DIIsK>?@C yym\9cJH !h/O diic0B&CDO &doo6"5)"5)'..0"
 &3F&;M(# #&M% ")M$&,M(# )//1LE5**wbq12waw/0	 2 5)*++S E<  5s&   C1R75R/R/%DR79R4:I;R7c                     [        U5      nU R                   HR  nUR                  U5      (       d  M  [        U5      [        U5      :X  d	  US   S:X  a    gU[        U5         S:X  d  MR    g   g)z
Check if the given URL is within the current protection space.

According to RFC 7616, a URI is in the protection space if any URI
in the protection space is a prefix of it (after both have been made absolute).
/TF)r#   r\   
startswithlen)r]   ra   request_str	space_strs       r'   _in_protection_space)DigestAuthMiddleware._in_protection_spacep  si     #h//I)))44;3y>1Yr]c5I3y>*c1 0 r&   r2   c           
         UR                   S:w  a  gUR                  R                  SS5      nU(       d  gUR                  S5      u  p4nU(       d  gUR	                  5       S:w  a  gU(       d  g[        U5      =n(       d  g0 U l        [         H+  nUR                  U5      =n(       d  M  XR                  U'   M-     UR                  R                  5       n	U R                  R                  S5      =n
(       a  / U l
        U
R                  5        H  nUR                  S5      nUR                  S	5      (       a>  U R                  R                  [        U	R!                  [#        U5      5      5      5        Mh  U R                  R                  [        [#        U5      5      5        M     O[        U	5      /U l
        [%        U R                  5      $ )
zr
Takes the given response and tries digest-auth, if needed.

Returns true if the original request must be resent.
i  Fzwww-authenticaterd    digestr   r8   r   )statusheadersry   	partitionlowerrI   rZ   r.   ra   originr\   r}   rD   r   r   r#   rq   r   bool)r]   r2   auth_headerr`   sepr   header_pairsr   r5   r   r   r0   s               r'   _authenticate"DigestAuthMiddleware._authenticate  su    ??c!&&**+=rB*44S9W<<>X% !37 ;;; %E$((//u/).& &
 $$&__((2262%'D"||~iin>>#&&**11#fkk#c(6K2LM **11#c#h-@ & '*&k]D" DOO$$r&   requesthandlerc                   #    Sn[        S5       H  nUS:  dB  U R                  (       a  U R                  (       at  U R                  UR                  5      (       aT  U R                  UR                  UR                  UR                  5      I Sh  vN UR                  [        R                  '   U" U5      I Sh  vN nU R                  U5      (       a  M    O   Uc   eU$  NR N)7f)zRun the digest auth middleware.N   r   )ranger[   rZ   r   ra   r   r`   rb   r   r   AUTHORIZATIONr   )r]   r   r   r2   retry_counts        r'   __call__DigestAuthMiddleware.__call__  s       8K Q  OO--gkk::<@LLNNGKK= 7 2 23
 %W--H %%h//% $* ###7
 .s*   BC&C"*C&:C$;C&C&$C&)rZ   rX   rV   rT   rY   rW   r[   r\   )T)r   r    r!   r"   __doc__r#   r   r^   r   r   r   r   r   r   r   r   r   r   r   r%   r   r&   r'   rK   rK      s    D  	// / 	/
 
/4_,_, #_,+0'#,1F+G_,	_,B  (9%n 9% 9%v$/@	r&   rK   )2r   r   r   rer   typingr   r   r   r   r   r   r	   r
   r   yarlr   rd   r   client_exceptionsr   client_middlewaresr   client_reqrepr   r   payloadr   r   md5r   sha256sha512r-   r#   r~   r$   compilerB   r.   tuplesortedkeysr/   	frozensetr4   r=   r?   rI   rK   r   r&   r'   <module>r      s    	 	 
 
 
   * 1 8 )5  ;;<<nn>>~~NNnn>>~~NNBc8UG_$<==> " 

4 6	 %	QRTWW   05VO<P<P<R5S/T eE#s(O, T -6I- E)C.) 
% % %
%3 %3 %
s tCH~ 6D Dr&   