
    `Kh*B                        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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jJ                  d      Z&dZ'eeed   df      e$d<    e( e)e!jU                                     Z+eee"df      e$d<    e,h d      Z-ee	e"      e$d<   de"de"fdZ.de"de"fdZ/de"dee"e"f   fdZ0 G d d       Z1y)!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                   T    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<   y)	DigestAuthChallengerealmnonceqop	algorithmopaquedomainstaleN)__name__
__module____qualname__str__annotations__     /var/www/CtrlAgent-Voice-Telephony-Channel/python-server/venv/lib/python3.12/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                 &    | j                  dd      S )z,Escape double quotes for HTTP header values."\"replacer2   s    r$   escape_quotesr:   q   s    ==e$$r#   c                 &    | j                  dd      S )z-Unescape double quotes in HTTP header values.r6   r5   r7   r9   s    r$   unescape_quotesr<   v   s    ==$$r#   headerc           	          t         j                  |       D ci c](  \  }}}|j                         x}r||rt        |      n|* c}}}S c c}}}w )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
    )_HEADER_PAIRS_PATTERNfindallstripr<   )r=   key
quoted_valunquoted_valstripped_keys        r$   parse_header_pairsrF   {   sZ    , .C-J-J6-R )C\IIK'L' 	Zoj1\Q  s   -A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y)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.
    loginpassword
preemptiver3   Nc                    |t        d      |t        d      d|v rt        d      || _        |j                  d      | _        |j                  d      | _        d| _        d| _        i | _        || _        g | _	        y )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)selfrI   rJ   rK   s       r$   __init__zDigestAuthMiddleware.__init__   s     =ABBDEE%<WXX&+*/,,w*?-5__W-E!$/1!+,.r#   methodurlbodyr#   c           
        "#K   | j                   }d|vrt        d      d|vrt        d      |d   }|d   }|st        d      |j                  dd      }|j                  dd	      j                         }|j                  d
d      }	|j	                  d      }
|j	                  d      }t        |      j                  }d}d}|rxddhj                  |j                  d      D ch c]#  }|j                         s|j                         % c}      }|st        d|       d|v rdnd}|j	                  d      }|t        vr$t        d| ddj                  t                     t        |   #dt        dt        f#fd"dt        dt        dt        f"fd}dj                  | j                  || j                  f      }|j                          d| j	                         }|dk(  rFt!        |t"              r|j%                          d{   }n|} "|      }dj                  ||f      } "|      } "|      }|
| j&                  k(  r| xj(                  dz  c_        nd| _        |
| _        | j(                  d}|j	                  d      }t+        j,                  dj                  t/        | j(                        j	                  d      |
t1        j2                         j	                  d      t5        j6                  d      g            j9                         dd  }|j	                  d      }|j                         j;                  d!      r "dj                  ||
|f            }|r dj                  |
||||f      } |||      }n ||dj                  |
|f            }t=        | j>                        t=        |      t=        |      ||jA                         |d"}|	rt=        |	      |d
<   |r||d<   ||d#<   ||d$<   g }|jC                         D ];  \  } }!| tD        v r|jG                  |  d%|! d&       &|jG                  |  d'|!        = d(dj                  |       S c c}w 7 `w))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   rN   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, xr3   c                 L     |       j                         j                         S )z<RFC 7616 Section 3: Hash function H(data) = hex(hash(data)).)	hexdigestrQ   )rb   hash_fns    r$   Hz'DigestAuthMiddleware._encode.<locals>.H  s    1:'')0022r#   sdc                 6     dj                  | |f            S )zDRFC 7616 Section 3: KD(secret, data) = H(concat(secret, ":", data)).   :)join)rg   rh   rf   s     r$   KDz(DigestAuthMiddleware._encode.<locals>.KD  s    TYY1v&''r#   rj   rM   Nr   08x      z-SESS)r0   r   r   r-   r/   r   ncr.   z="r5   =zDigest )$rV   r   getupperrQ   r   path_qsintersectionsplitrA   r*   rk   r,   bytesrR   rS   
isinstancer   as_bytesrT   rU   hashlibsha1r    timectimeosurandomrd   endswithr:   rP   decodeitemsr1   append)$rY   r[   r\   r]   	challenger   r   qop_rawr   r   nonce_bytesrealm_bytespathr   	qop_bytesq
valid_qopsrl   A1A2entity_bytesentity_hashHA1HA2ncvaluencvalue_bytesr.   cnonce_bytesnoncebitresponse_digestheader_fieldspairsfieldr2   rf   re   s$                                     @@r$   _encodezDigestAuthMiddleware._encode   s    & OO	)#L  )#L 
 '"'" T  --r*MM+u5;;=	x, ll7+ll7+3x 	 *-::$+MM#$6Dq!'')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(# )//1 	1LE5**wbq12waw/0		1 5)*++S E<  5s&   C#Q4'Q,=Q,DQ4Q1I Q4c                     t        |      }| j                  D ]H  }|j                  |      st        |      t        |      k(  s|d   dk(  r y|t        |         dk(  sH y y)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    rX   
startswithlen)rY   r\   request_str	space_strs       r$   _in_protection_spacez)DigestAuthMiddleware._in_protection_spacep  sk     #h// 		I)))4;3y>1Yr]c5I3y>*c1		 r#   r/   c           
      P   |j                   dk7  ry|j                  j                  dd      }|sy|j                  d      \  }}}|sy|j	                         dk7  ry|syt        |      x}syi | _        t        D ]%  }|j                  |      x}s|| j                  |<   ' |j                  j                         }	| j                  j                  d      x}
rg | _
        |
j                         D ]  }|j                  d      }|j                  d	      r=| j                  j                  t        |	j!                  t#        |                         b| j                  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-authenticater_    digestr   r5   r   )statusheadersrr   	partitionlowerrF   rV   r+   r\   originrX   rv   rA   r   r   r    rk   r   bool)rY   r/   auth_headerr[   sepr   header_pairsr   r2   r   r   r-   s               r$   _authenticatez"DigestAuthMiddleware._authenticate  s    ??c!&&**+=rB*44S9W<<>X% !37 ;;; % 	/E$((//u/).&	/
 $$&__((2262%'D"||~ Aiin>>#&**11#fkk#c(6K2LM **11#c#h-@A '*&k]D" DOO$$r#   requesthandlerc                   K   d}t        d      D ]  }|dkD  s3| j                  r{| j                  ro| j                  |j                        rT| j                  |j                  |j                  |j                         d{   |j                  t        j                  <    ||       d{   }| j                  |      r n |J |S 7 J7 !w)zRun the digest auth middleware.N   r   )rangerW   rV   r   r\   r   r[   r]   r   r   AUTHORIZATIONr   )rY   r   r   r/   retry_counts        r$   __call__zDigestAuthMiddleware.__call__  s       8 	K Q  OO--gkk:<@LLNNGKK= 7 2 23
 %W--H %%h/%	* ###7
 .s*   A=C?C
 *C*C+C
CC)T)r   r   r   __doc__r    r   rZ   r   r   r   r   r   r   r   r   r   r   r   r"   r#   r$   rH   rH      s    D  	// / 	/
 
/4_,_, #_,+0'#,1F+G_,	_,B  (9%n 9% 9%v$/@	r#   rH   )2r   rz   r~   rer|   typingr   r   r   r   r   r   r	   r
   r   yarlr   r_   r   client_exceptionsr   client_middlewaresr   client_reqrepr   r   payloadr   r   md5r{   sha256sha512r*   r    rw   r!   compiler?   r+   tuplesortedkeysr,   	frozensetr1   r:   r<   rF   rH   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#   