
    tniD                        U 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mZmZm	Z	m
Z
mZmZmZmZmZ ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ  G d ded          Zej        ej        ej        ej        ej         ej         ej         ej         ej!        ej!        ej!        ej!        dZ"ee#ee$gdf         f         e%d<    ej&        ej'        dk     rdnd          Z(dZ)e	eed         df                  e%d<    e* e+e",                                                    Z-e	ee#df                  e%d<    e.h d          Z/e	e
e#                  e%d<   de#de#fdZ0de#de#fdZ1de#dee#e#f         fd Z2 G d! d"          Z3dS )#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                   V    e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   eed<   dS )	DigestAuthChallengerealmnonceqop	algorithmopaquedomainstaleN)__name__
__module____qualname__str__annotations__     b/var/www/html/gpu-tools/venv/lib/python3.11/site-packages/aiohttp/client_middleware_digest_auth.pyr   r   $   sO         JJJJJJ	HHHNNNKKKKKKJJJJJr#   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DigestFunctions)      z:(?:^|\s|,\s*)(\w+)\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([^\s,]+))z>(?:^|\s|,\s*)((?>\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                 .    |                      dd          S )z,Escape double quotes for HTTP header values."\"replacer4   s    r$   escape_quotesr<   u   s    ==e$$$r#   c                 .    |                      dd          S )z-Unescape double quotes in HTTP header values.r8   r7   r9   r;   s    r$   unescape_quotesr>   z   s    ==$$$r#   headerc                 P    fdt                               |           D             S )a  
    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
    c                 l    i | ]0\  }}}|                                 x|rt          |          n|1S r"   )stripr>   ).0key
quoted_valunquoted_valstripped_keys       r$   
<dictcomp>z&parse_header_pairs.<locals>.<dictcomp>   sV       )C\IIKK'LZQoj111\  r#   )_HEADER_PAIRS_PATTERNfindall)r?   rG   s    @r$   parse_header_pairsrK      s<    (   -B-J-J6-R-R   r#   c            	           e Zd ZdZ	 ddedededdfdZd	ed
edee	e
d         f         defdZd
edefdZdedefdZdededefdZdS )DigestAuthMiddlewarea  
    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.
    Tloginpassword
preemptiver5   Nc                 ,   |t          d          |t          d          d|v rt          d          || _        |                    d          | _        |                    d          | _        d| _        d| _        i | _        || _        g | _	        d S )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)selfrN   rO   rP   s       r$   __init__zDigestAuthMiddleware.__init__   s     =ABBBDEEE%<<WXXX&+*/,,w*?*?-5__W-E-E!$/1!+,.r#   methodurlbodyr#   c           
      	  "#K   | j         }d|vrt          d          d|vrt          d          |d         }|d         }|st          d          |                    dd          }|                    dd	          }|                                }	|                    d
d          }
|                    d          }|                    d          }t          |          j        }d}d}|reddh                    d |                    d          D                       }|st          d|           d|v rdnd}|                    d          }|	t          vr-t          d|	 dd
                    t                               t          |	         #dt          dt          f#fd"dt          dt          dt          f"fd}d
                    | j        || j        f          }|                                 d|                                 }|dk    rTt          |t                     r|                                 d{V }n|} "|          }d
                    ||f          } "|          } "|          }|| j        k    r| xj        dz  c_        nd| _        || _        | j        d}|                    d          }t)          j        d
                    t-          | j                                      d          |t/          j                                        d          t3          j        d           g                                                    dd!         }|                    d          }|	                                                    d"          r! "d
                    |||f                    }|r'd
                    |||||f          } |||          }n! ||d
                    ||f                    }t;          | j                  t;          |          t;          |          ||                                |d#}|
rt;          |
          |d
<   |r||d<   ||d$<   ||d%<   g }|                                 D ]D\  } }!| tB          v r|"                    |  d&|! d'           *|"                    |  d(|!            Ed)d
                    |           S )*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   rS   r#   authzauth-intc                 ^    h | ]*}|                                 |                                 +S r"   )rB   )rC   qs     r$   	<setcomp>z/DigestAuthMiddleware._encode.<locals>.<setcomp>  s-    DDDq!''))DDDDr#   ,zEDigest auth error: Unsupported Quality of Protection (qop) value(s): z/Digest auth error: Unsupported hash algorithm: z. Supported algorithms: z, xr5   c                 b     |                                                                            S )z<RFC 7616 Section 3: Hash function H(data) = hex(hash(data)).)	hexdigestrV   )rj   hash_fns    r$   Hz'DigestAuthMiddleware._encode.<locals>.H  s)    71::''))00222r#   sdc                 D     d                     | |f                    S )zDRFC 7616 Section 3: KD(secret, data) = H(concat(secret, ":", data)).   :)join)ro   rp   rn   s     r$   KDz(DigestAuthMiddleware._encode.<locals>.KD   s#    1TYY1v&&'''r#   rr   rR   Nr   08x      z-SESS)r2   r   r   r/   r1   r   ncr0   z="r7   =zDigest )#r[   r   getupperrV   r   path_qsintersectionsplitr*   rs   r.   bytesrW   rX   
isinstancer   as_bytesrY   rZ   hashlibsha1r    timectimeosurandomrl   endswithr<   rU   decodeitemsr3   append)$r^   r`   ra   rb   	challenger   r   qop_rawalgorithm_originalr   r   nonce_bytesrealm_bytespathr   	qop_bytes
valid_qopsrt   A1A2entity_bytesentity_hashHA1HA2ncvaluencvalue_bytesr0   cnonce_bytesnoncebitresponse_digestheader_fieldspairsfieldr4   rn   rm   s$                                     @@r$   _encodezDigestAuthMiddleware._encode   s     & O	)##L   )##L  
 '"'"  	T   --r**&]];>>&,,..	x,, ll7++ll7++3xx 	 
	, *-::DDGMM#$6$6DDD J  !e\cee   !+j 8 8**fC

7++IO++K) K K)-3G)H)HK K   )3	3 	35 	3 	3 	3 	3 	3 	3	(% 	(E 	(e 	( 	( 	( 	( 	( 	(
 YY);8LMNN''''..00*$(( $%)]]__444444#!L//KB,--Baeeaee $000" !D!,&,,w// HH)**11'::JLL''00JqMM	 	
 	
 )++crc	 }}W-- ??%%g.. 	A!DIIsK>??@@C  	Eyym\9cJ H !bh//OO bdiic0B&C&CDDO &do66"5))"5))'..00+
 
  	<&3F&;&;M(#  	-#&M% ")M$&,M(# )//11 	1 	1LE5***111112222////0000+5))+++r#   c                     t          |          }| j        D ]c}|                    |          st          |          t          |          k    s|d         dk    r dS |t          |                   dk    r dS ddS )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_spacez)DigestAuthMiddleware._in_protection_spacev  s     #hh/ 		 		I)))44 ;3y>>11Yr]c5I5Itt3y>>*c11tt 2ur#   r1   c           
         |j         dk    rdS |j                            dd          }|sdS |                    d          \  }}}|sdS |                                dk    rdS |sdS t          |          x}sdS i | _        t          D ]#}|                    |          x}r
|| j        |<   $|j        	                                }	| j                            d          x}
rg | _
        |
                                D ]}|                    d          }|                    d	          rH| j
                            t          |	                    t#          |                                         t| j
                            t          t#          |                               nt          |	          g| _
        t%          | j                  S )
z
        Takes the given response and tries digest-auth, if needed.

        Returns true if the original request must be resent.
        i  Fzwww-authenticaterd    digestr   r7   r   )statusheadersrz   	partitionlowerrK   r[   r-   ra   originr]   r~   rB   r   r   r    rs   r   bool)r^   r1   auth_headerr`   sepr   header_pairsr   r4   r   r   r/   s               r$   _authenticatez"DigestAuthMiddleware._authenticate  s    ?c!!5&**+=rBB 	5*44S99W 	5<<>>X%%5 	5 !37 ; ;; 	5 % 	/ 	/E$((///u /).& $$&&_((2226 	3%'D"||~~ A Aiinn>>#&& A*11#fkk#c((6K6K2L2LMMMM *11#c#hh--@@@@A '*&kk]D" DO$$$r#   requesthandlerc                 b  K   d}t          d          D ]}|dk    s(| j        r_| j        rX|                     |j                  r>|                     |j        |j        |j                   d{V |j        t          j
        <    ||           d{V }|                     |          s n|J |S )zRun the digest auth middleware.N   r   )ranger\   r[   r   ra   r   r`   rb   r   r   AUTHORIZATIONr   )r^   r   r   r1   retry_counts        r$   __call__zDigestAuthMiddleware.__call__  s        88 	 	K Q  O  --gk:: 
 =ALLNGK= = 7 7 7 7 7 7 23
 %WW--------H %%h//  ###r#   )T)r   r   r   __doc__r    r   r_   r   r   r   r   r   r   r   r   r   r   r   r"   r#   r$   rM   rM      s        D  	/ // / 	/
 
/ / / /4a,a, #a,+0'#,1F+Ga,	a, a, a, a,F     (9%n 9% 9% 9% 9% 9%v$/@	     r#   rM   )4r   r   r   resysr   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!   compileversion_inforI   r-   tuplesortedkeysr.   	frozensetr3   r<   r>   rK   rM   r"   r#   r$   <module>r      sQ      				 				 



 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
             * * * * * * 1 1 1 1 1 1 8 8 8 8 8 8 8 8          )5     ;<n>~Nn>~NB Bc8UG_$<==>   " #

'!! BA	J  <	 %	QRTWW     05uVVO<P<P<R<R5S5S/T/T eE#s(O, T T T -6IIII- - E)C.)   
% % % % % %
%3 %3 % % % %
s tCH~    6F F F F F F F F F Fr#   