o
    4˜ŽjáL  ã                   @   sÂ  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 ddl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 #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d„Z-de de fd d!„Z.d"e dee e f fd#d$„Z/G d%d&„ d&ƒZ0d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)ÚFinalÚLiteralÚ	TypedDict)Ú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   úb/var/www/kodo/Anonymous/send/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ÚDigestFunctions)é   é   z?(?:^|\s|,\s*)(\w+)(?:\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([^\s,]+)))?zC(?:^|\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                 C   ó   |   dd¡  dd¡S )z=Escape backslashes and double quotes for HTTP quoted-strings.ú\ú\\ú"ú\"©Úreplace©r,   r   r   r   Úescape_quotesh   ó   r6   c                 C   r.   )z>Unescape backslashes and double quotes in HTTP quoted-strings.r2   r1   r0   r/   r3   r5   r   r   r   Úunescape_quotesm   r7   r8   Úheaderc                 C   sl   i }t  | ¡D ],}| d¡}| d¡| d¡}}|du r'|du r'|r& |S q|dur/t|ƒn|||< q|S )a�  
    Parse key-value pairs from the first challenge of a WWW-Authenticate header.

    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.

    A single header may carry several challenges
    (https://www.rfc-editor.org/rfc/rfc7235#section-4.1). Parsing
    stops at the next auth-scheme token so a later challenge's parameters cannot
    overwrite the first challenge's values; a leading scheme token is skipped.

    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
    r   é   r#   N)Ú_HEADER_PAIRS_PATTERNÚfinditerÚgroupr8   )r9   ÚpairsÚmatchÚkeyÚ
quoted_valÚunquoted_valr   r   r   Úparse_header_pairsr   s   
üÿrC   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	d B 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 )ÚDigestAuthMiddlewarea1  
    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

    Origin scoping:
    The credentials are scoped to the origin of the first request the
    middleware handles. A request to a different origin is passed through
    untouched, so it never receives a digest response computed from those
    credentials, unless that origin falls within a protection space the
    anchor origin advertised through the RFC 7616 ``domain`` directive. Make
    the first request through the middleware against the intended origin, as
    the anchor is pinned to it and not reset for the life of the instance.

    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Ú
preemptiver-   Nc                 C   sv   |d u rt dƒ‚|d u rt dƒ‚d|v rt dƒ‚|| _| d¡| _| d¡| _d| _d| _i | _|| _g | _	d | _
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Ú_origin)ÚselfrE   rF   rG   r   r   r   Ú__init__Ä   s   
zDigestAuthMiddleware.__init__ÚmethodÚurlÚbodyrJ   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rƒt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rÒt|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   rI   rJ   Úauthzauth-intc                 S   s   h | ]
}|  ¡ r|  ¡ ’qS r   )Ústrip)Ú.0Ú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)).)Ú	hexdigestrM   )rb   )Ú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)rf   rg   )re   r   r   ÚKD/  s   z(DigestAuthMiddleware._encode.<locals>.KDrh   rH   Nr   Ú08xé   é   z-SESS)r*   r   r   r'   r)   r   Úncr(   z="r1   ú=zDigest )#rR   r	   ÚgetÚupperrM   r   Úraw_path_qsÚintersectionÚsplitr"   ri   r&   ÚbytesrN   rO   Ú
isinstancer   Úas_bytesrP   rQ   ÚhashlibÚsha1r   ÚtimeÚctimeÚosÚurandomrc   Úendswithr6   rL   ÚdecodeÚitemsr+   Úappend)"rV   rX   rY   rZ   Ú	challenger   r   Úqop_rawÚalgorithm_originalr   r   Únonce_bytesÚrealm_bytesÚpathr   Ú	qop_bytesÚ
valid_qopsrj   ÚA1ÚA2Úentity_bytesÚentity_hashÚHA1ÚHA2ÚncvalueÚncvalue_bytesr(   Úcnonce_bytesÚnoncebitÚresponse_digestÚheader_fieldsr>   Úfieldr,   r   )re   rd   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   rT   Ú
startswithÚlen)rV   rY   Úrequest_strÚ	space_strr   r   r   Ú_in_protection_space…  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 ]}| |¡ }durG|| j|< q7|j 	¡ }	g | _
| j d¡ }
r„|
 ¡ D ]'}| d	¡}|sfq\| d
¡ry| j
 t|	 t|ƒ¡ƒ¡ q\| j
 tt|ƒƒ¡ q\| j
s�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[   ú ÚdigestNr   r1   r™   )ÚstatusÚheadersrp   Ú	partitionÚlowerrC   rR   r%   rY   ÚoriginrT   rt   r]   rš   r�   r   ri   r   Úbool)rV   r)   Úauth_headerrX   Úsepr¢   Úheader_pairsr–   r,   r¥   r   r'   r   r   r   Ú_authenticate™  s@   

€



z"DigestAuthMiddleware._authenticateÚrequestÚhandlerc                 Ã   sÂ   �|j  ¡ }| jdu r|| _n|| jkr!|  |j ¡s!||ƒI dH S d}tdƒD ]1}|dks9| jrJ| jrJ|  |j ¡rJ|  |j|j |j	¡I dH |j
tj< ||ƒI dH }|  |¡sX nq'|dus_J ‚|S )zRun the digest auth middleware.Nr:   r   )rY   r¥   rU   rž   ÚrangerS   rR   r—   rX   rZ   r¢   r   ÚAUTHORIZATIONrª   )rV   r«   r¬   r¥   r)   Úretry_countr   r   r   Ú__call__Ö  s0   €

ÿþ
ýÿ
ÿzDigestAuthMiddleware.__call__)T)r   r   r   Ú__doc__r   r¦   rW   r   r   r   r—   rž   r   rª   r   r
   r°   r   r   r   r   rD   œ   s.    +üþýü
û" &=ÿÿþrD   )1r±   rx   r|   ÚreÚsysrz   Úcollections.abcr   Útypingr   r   r   Úyarlr   r[   r   Úclient_exceptionsr	   Úclient_middlewaresr
   Úclient_reqrepr   r   Úpayloadr   r   Úmd5ry   Úsha256Úsha512r"   Údictr   ru   r   ÚcompileÚversion_infor;   r%   ÚtupleÚsortedÚkeysr&   Ú	frozensetr+   r6   r8   rC   rD   r   r   r   r   Ú<module>   s^    	 ô
ÿýü
ÿÿ$ÿ*