o
    f>h99                     @   s  U d 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 ded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%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dZ.de"de"fddZ/de"dee"e"f fd d!Z0G d"d# d#Z1d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                   @   s6   e Zd ZU eed< eed< eed< eed< eed< dS )DigestAuthChallengerealmnonceqop	algorithmopaqueN)__name__
__module____qualname__str__annotations__ r   r   X/var/www/html/venv/lib/python3.10/site-packages/aiohttp/client_middleware_digest_auth.pyr   #   s   
 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   .CHALLENGE_FIELDSSUPPORTED_ALGORITHMS>   urir   r   cnoncer   responseusernameQUOTED_AUTH_FIELDSvaluereturnc                 C      |  ddS )z,Escape double quotes for HTTP header values."\"replacer-   r   r   r   escape_quotesk      r5   c                 C   r/   )z-Unescape double quotes in HTTP header values.r1   r0   r2   r4   r   r   r   unescape_quotesp   r6   r7   headerc                    s    fd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                    s0   i | ]\}}}|    r |rt|n|qS r   )stripr7   ).0key
quoted_valunquoted_valstripped_keyr   r   
<dictcomp>   s    
z&parse_header_pairs.<locals>.<dictcomp>)_HEADER_PAIRS_PATTERNfindall)r8   r   r>   r   parse_header_pairsu   s   
rC   c                	   @   st   e Zd ZdZdededdfddZded	ed
eee	d f defddZ
dedefddZdededefd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

    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passwordr.   Nc                 C   sd   |d u rt d|d u rt dd|v rt d|| _|d| _|d| _d| _d| _i | _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-8    r   )
ValueError
_login_strencode_login_bytes_password_bytes_last_nonce_bytes_nonce_count
_challenge)selfrE   rF   r   r   r   __init__   s   
zDigestAuthMiddleware.__init__methodurlbodyrI   c           !   
      sF  | 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}|rpddhdd |dD }|sctd| d|v ridnd}|d}|t	vrtd| dd
t t	| dtdtffdd dtdtdtf fdd}d
| j|| jf}|  d|  }|dkrt|tr| I d H }n|} |}d
||f} |} |}|
| jkr|  jd!7  _nd!| _|
| _| jd"}|d}td
t| jd|
t dtd#g d d$ }|d}| d%r, d
||
|f}|r?d
|
||||f}|||}n
||d
|
|f}t| jt|t||| |d&}|	rdt|	|d
< |rs||d< ||d'< ||d(< g }|  D ]!\}} |t!v r|"| d)|  d* qy|"| d+|   qyd,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   rH   rI   authzauth-intc                 S   s   h | ]
}|  r|  qS r   )r9   )r:   qr   r   r   	<setcomp>   s    z/DigestAuthMiddleware._encode.<locals>.<setcomp>,zEDigest auth error: Unsupported Quality of Protection (qop) value(s): z/Digest auth error: Unsupported hash algorithm: z. Supported algorithms: z, xr.   c                    s    |    S )z<RFC 7616 Section 3: Hash function H(data) = hex(hash(data)).)	hexdigestrL   )r\   )hash_fnr   r   H  s   z'DigestAuthMiddleware._encode.<locals>.Hsdc                    s    d | |fS )zDRFC 7616 Section 3: KD(secret, data) = H(concat(secret, ":", data)).   :)join)r`   ra   )r_   r   r   KD  s   z(DigestAuthMiddleware._encode.<locals>.KDrb   rG   Nr   08x      z-SESS)r+   r   r   r(   r*   r   ncr)   z="r0   =zDigest )#rQ   r   getupperrL   r   path_qsintersectionsplitr%   rc   r'   bytesrM   rN   
isinstancer   as_bytesrO   rP   hashlibsha1r   timectimeosurandomr]   endswithr5   rK   decodeitemsr,   append)!rR   rT   rU   rV   	challenger   r   qop_rawr   r   nonce_bytesrealm_bytespathr   	qop_bytes
valid_qopsrd   A1A2entity_bytesentity_hashHA1HA2ncvaluencvalue_bytesr)   cnonce_bytesnoncebitresponse_digestheader_fieldspairsfieldr-   r   )r_   r^   r   _encode   s   








	


zDigestAuthMiddleware._encoder*   c           	      C   s   |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| }s2dS i | _tD ]}|| }rE|| j|< q7t| 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-authenticaterW    digest)	statusheadersrj   	partitionlowerrC   rQ   r&   bool)	rR   r*   auth_headerrT   sepr   header_pairsr   r-   r   r   r   _authenticatee  s(   


z"DigestAuthMiddleware._authenticaterequesthandlerc                    sj   d}t dD ]%}|dkr| |j|j|jI dH |jtj< ||I dH }| |s, nq|dus3J |S )zRun the digest auth middleware.N   r   )	ranger   rT   rU   rV   r   r   AUTHORIZATIONr   )rR   r   r   r*   retry_countr   r   r   __call__  s   
zDigestAuthMiddleware.__call__)r   r   r   __doc__r   rS   r   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   rD      s6    

 "(rD   )2r   rr   rv   rert   typingr   r   r   r   r   r   r   r	   r
   yarlr   rW   r   client_exceptionsr   client_middlewaresr   client_reqrepr   r   payloadr   r   md5rs   sha256sha512r%   r   ro   r   compilerA   r&   tuplesortedkeysr'   	frozensetr,   r5   r7   rC   rD   r   r   r   r   <module>   sR    	,	 $