o
    FhB                     @   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                   @   sF   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__ 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   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_quotesq      r7   c                 C   r1   )z-Unescape double quotes in HTTP header values.r3   r2   r4   r6   r    r    r!   unescape_quotesv   r8   r9   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    )stripr9   ).0key
quoted_valunquoted_valstripped_keyr    r!   
<dictcomp>   s    
z&parse_header_pairs.<locals>.<dictcomp>)_HEADER_PAIRS_PATTERNfindall)r:   r    r@   r!   parse_header_pairs{   s   
rE   c                	   @   s   e Zd ZdZ	dde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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
    - 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
preemptiver0   Nc                 C   sp   |d u rt d|d u r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-8    r   )

ValueError
_login_strencode_login_bytes_password_bytes_last_nonce_bytes_nonce_count
_challenge_preemptive_protection_space)selfrG   rH   rI   r    r    r!   __init__   s   
zDigestAuthMiddleware.__init__methodurlbodyrL   c           "   
      sJ  | 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}|rrddhdd |dD }|setd| d|v rkd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}|rAd
|||||f}|||}n
||d
||f}t| jt|t||| |d&}|
rft|
|d
< |ru||d< ||d'< ||d(< g }|  D ]!\} }!| t!v r|"|  d)|! d* q{|"|  d+|!  q{d,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   rK   rL   authzauth-intc                 S   s   h | ]
}|  r|  qS r    )r;   )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, xr0   c                    s    |    S )z<RFC 7616 Section 3: Hash function H(data) = hex(hash(data)).)	hexdigestrO   )ra   )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)re   rf   )rd   r    r!   KD  s   z(DigestAuthMiddleware._encode.<locals>.KDrg   rJ   Nr   08x      z-SESS)r-   r   r   r*   r,   r   ncr+   z="r2   =zDigest )#rT   r   getupperrO   r   path_qsintersectionsplitr'   rh   r)   bytesrP   rQ   
isinstancer   as_bytesrR   rS   hashlibsha1r   timectimeosurandomrb   endswithr7   rN   decodeitemsr.   append)"rW   rY   rZ   r[   	challenger   r   qop_rawalgorithm_originalr   r   nonce_bytesrealm_bytespathr   	qop_bytes
valid_qopsri   A1A2entity_bytesentity_hashHA1HA2ncvaluencvalue_bytesr+   cnonce_bytesnoncebitresponse_digestheader_fieldspairsfieldr/   r    )rd   rc   r!   _encode   s   








	


zDigestAuthMiddleware._encodec                 C   s\   t |}| jD ]$}||sqt|t|ks|d dkr  dS |t| dkr+ dS qd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   rV   
startswithlen)rW   rZ   request_str	space_strr    r    r!   _in_protection_spacer  s   

z)DigestAuthMiddleware._in_protection_spacer,   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|< q7|j	 }	| jd }
rg | _
|
 D ]$}|d}|d	rt| j
t|	t| qZ| j
tt| qZn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-authenticater\    digestr   r2   r   )statusheadersro   	partitionlowerrE   rT   r(   rZ   originrV   rs   r;   r   r   r   rh   r   bool)rW   r,   auth_headerrY   sepr   header_pairsr   r/   r   r   r*   r    r    r!   _authenticate  s<   





z"DigestAuthMiddleware._authenticaterequesthandlerc                    s   d}t dD ]1}|dks| jr*| jr*| |jr*| |j|j|jI dH |jt	j
< ||I dH }| |s8 nq|dus?J |S )zRun the digest auth middleware.N   r   )rangerU   rT   r   rZ   r   rY   r[   r   r   AUTHORIZATIONr   )rW   r   r   r,   retry_countr    r    r!   __call__  s&   

zDigestAuthMiddleware.__call__)T)r   r   r   __doc__r   r   rX   r   r
   r   r   r   r   r   r   r   r   r   r    r    r    r!   rF      s>    "

 $;rF   )2r   rw   r{   rery   typingr   r   r   r   r   r   r   r	   r
   yarlr   r\   r   client_exceptionsr   client_middlewaresr   client_reqrepr   r   payloadr   r   md5rx   sha256sha512r'   r   rt   r   compilerC   r(   tuplesortedkeysr)   	frozensetr.   r7   r9   rE   rF   r    r    r    r!   <module>   sV    	, 
$