Ë
    âß²jK(  ã                  ó²  — U d Z ddlmZ ddlZddl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 ddlmZ ddlmZ ddlmZ  ej(                  e«      Z edd	h«      Zd
ddœZdZdd„Zd d„Z G d„ de	j:                  j<                  «      Z G d„ de	j:                  j@                  «      Z!da"de#d<   d!d„Z$d"d„Z%d#d„Z&d$d„Z'ddœd%d„Z(dddœ	 	 	 	 	 d&d„Z)g d¢Z*y)'z>Security policy for credential-bearing stdlib urllib requests.é    )ÚannotationsN)ÚCallableÚIterable)ÚPath)ÚAny)Úfile_signatureÚacceptz
user-agentéP   i»  )ÚhttpÚhttps)ÚHERMES_CA_BUNDLEÚSSL_CERT_FILEÚREQUESTS_CA_BUNDLEÚCURL_CA_BUNDLEc                ó$  — t         j                  j                  | «      }|j                  xs dj	                  «       }|j
                  }||j                  xs dj	                  «       j                  d«      |�|fS t        j                  |«      fS )z>Return a normalized (scheme, hostname, effective port) origin.Ú ú.)
ÚurllibÚparseÚurlparseÚschemeÚlowerÚportÚhostnameÚrstripÚ_DEFAULT_PORTSÚget)ÚurlÚparsedr   r   s       ú?/home/ubuntu/.hermes/hermes-agent/hermes_cli/urllib_security.pyÚ
url_originr!      s|   € ä�\‰\×"Ñ" 3Ó'€FØ�m‰mÒ!˜r×(Ñ(Ó*€Fð �;‰;€DØ�F—O‘OÒ) r×0Ñ0Ó2×9Ñ9¸#Ó>ÈÐHXÀÐxÐxÔ^l×^pÑ^pÐqwÓ^xÐxÐxó    c                óŽ   — t        | j                  «       «      D ])  \  }}|j                  «       |vsŒ| j                  |«       Œ+ y)zFDrop every header on *request* whose lowercased name is not in *keep*.N)ÚlistÚheader_itemsr   Úremove_header)ÚrequestÚkeepÚnameÚ_values       r    Ú_strip_headersr+   %   s?   € ä˜W×1Ñ1Ó3Ó4ò (‰ˆˆfØ�:‰:‹<˜tÒ#Ø×!Ñ! $Õ'ñ(r"   c                  ó:   ‡ — e Zd ZdZedœ	 	 	 	 	 dd„Zˆ fd„Zˆ xZS )ÚSafeCredentialRedirectHandlerzAPreserve request headers only while redirects stay on one origin.)Úcross_origin_safe_headersc               óR   — t        |«      | _        t        d„ |D «       «      | _        y )Nc              3  óN   K  — | ]  }t        |«      j                  «       –— Œ y ­w©N)Ústrr   )Ú.0r)   s     r    ú	<genexpr>z9SafeCredentialRedirectHandler.__init__.<locals>.<genexpr>3   s   è ø€ Ò3lÈ$´C¸³I·O±O×4EÑ3lùs   ‚#%)r!   Ú_original_originÚ	frozensetÚ_cross_origin_safe_headers)ÚselfÚoriginal_urlr.   s      r    Ú__init__z&SafeCredentialRedirectHandler.__init__/   s%   € ô !+¨<Ó 8ˆÔÜ*3Ñ3lÐRkÔ3lÓ*lˆÕ'r"   c                óâ   •— t         ‰| �  ||||||«      }|€y t        t        j                  j                  |j                  |«      «      | j                  k7  rt        || j                  «       |S r1   )
ÚsuperÚredirect_requestr!   r   r   ÚurljoinÚfull_urlr5   r+   r7   )	r8   ÚreqÚfpÚcodeÚmsgÚheadersÚnewurlÚ
redirectedÚ	__class__s	           €r    r=   z.SafeCredentialRedirectHandler.redirect_request5   se   ø€ ä‘WÑ-¨c°2°t¸SÀ'È6ÓRˆ
ØÐØô ”f—l‘l×*Ñ*¨3¯<©<¸Ó@ÓAÀT×EZÑEZÒZÜ˜: t×'FÑ'FÔGØÐr"   )r9   r2   r.   zIterable[str]ÚreturnÚNone)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú_CROSS_ORIGIN_SAFE_HEADERSr:   r=   Ú__classcell__)rG   s   @r    r-   r-   ,   s8   ø„ ÙKð PjñmØðmØ?Lðmà	óm÷
ð 
r"   r-   c                  ó8   — e Zd ZdZ ed«      Zdd„Zdd„ZeZeZ	y)Ú_CrossOriginRequestSanitizerz:Strip headers after installed request processors have run.Úinfc                ó$   — t        |«      | _        y r1   )r!   r5   )r8   r9   s     r    r:   z%_CrossOriginRequestSanitizer.__init__K   s   € Ü *¨<Ó 8ˆÕr"   c                ój   — t        |j                  «      | j                  k7  rt        |t        «       |S r1   )r!   r?   r5   r+   rN   )r8   r'   s     r    Ú	_sanitizez&_CrossOriginRequestSanitizer._sanitizeN   s+   € Ü�g×&Ñ&Ó'¨4×+@Ñ+@Ò@Ü˜7Ô$>Ô?Øˆr"   N)r9   r2   rH   rI   )r'   úurllib.request.Request)
rJ   rK   rL   rM   ÚfloatÚhandler_orderr:   rU   Úhttp_requestÚhttps_request© r"   r    rQ   rQ   B   s&   „ ÙDñ ˜%“L€Mó9óð
 €LØ�Mr"   rQ   z#tuple[tuple, ssl.SSLContext] | NoneÚ_HTTPS_CONTEXT_CACHEc                 óø  ‡— g } t        ˆfd„t        D «       d«      }|rZt        |«      j                  «       }|j	                  «       r| j                  t        |«      «       nt        j                  d|«       t        j                  dk(  r/	 ddl}| j                  |j                  «       «       t        | «      S t        | «      S # t        $ r*}t        j                  d|«       Y d}~t        | «      S d}~ww xY w)u6  Bundles to try in order; empty keeps the stdlib default.

    Resolving the candidates and loading them are split so the memo below can key on the files that
    are actually going to be read â€” one precedence rule, not one for the loader and a second for the
    cache key that could drift away from it.
    c              3  óp   •K  — | ]-  }t        j                  |d «      j                  «       xŠsŒ*‰–— Œ/ y­w)r   N)ÚosÚgetenvÚstrip)r3   r)   Úvalues     €r    r4   z(_ca_bundle_candidates.<locals>.<genexpr>f   s1   øè ø€ Òf ÌÏÉÐSWÐY[ÓI\×IbÑIbÓIdÐ@dÀÑ@d”eÑfùs   ƒ+6¯6r   uJ   CA bundle path does not exist: %s â€” falling back to default certificatesÚdarwinr   Nua   Could not load certifi for urllib HTTPS verification: %s â€” falling back to default certificates)ÚnextÚ_CA_BUNDLE_ENV_VARSr   Ú
expanduserÚis_fileÚappendr2   ÚloggerÚwarningÚsysÚplatformÚcertifiÚwhereÚImportErrorÚtuple)Ú
candidatesÚ	ca_bundleÚca_pathrm   Úexcrb   s        @r    Ú_ca_bundle_candidatesru   ^   sÖ   ø€ ð €JÜÓfÔ(;ÔfÐhjÓk€IÙÜ�y“/×,Ñ,Ó.ˆØ�?‰?ÔØ×Ñœc '›lÕ+ä�N‰NÐgÐirÔsô ‡|�|�xÒð	Ûà×Ñ˜gŸm™m›oÔ.ô �ÓÐŒ5�ÓÐøô ò 	Ü�N‰NØsØ÷ð ô �ÓÐûð	ús   Â#C Ã	C9ÃC4Ã4C9c                óv   — 	 | gt        t        | «      j                  «       «      ¢­S # t        $ r | dfcY S w xY w)u%  ``(path, *file_signature(stat))`` so an edited or rotated bundle invalidates the memo.

    ``utils.file_signature`` adds inode and ctime to mtime + size, so a timestamp-preserving
    replacement (``cp -p``, ``rsync -t``) of the bundle is caught as well. Unreadable â†’ ``(path, None)``.
    N)r   r   ÚstatÚOSError)Úpaths    r    Ú_bundle_signaturerz   }   s>   € ðØÐ9”~¤d¨4£j§o¡oÓ&7Ó8Ñ9Ð9øÜò Ø�dˆ|Òðús   ‚%( ¨8·8c                 óš   — t        «       } | syt        | d   «      }t        }|�|d   |k(  r|d   S t        | «      \  }}|| d   k(  r||fa|S )uŒ  Return the shared explicit-CA context for Hermes-owned urllib openers.

    Memoised on the preferred bundle's signature only: that is the one file a memoised context was
    built from, so a change to a fallback bundle (certifi on macOS) that was never read must not
    invalidate it â€” and costs no stat per request. The returned context is shared and must not be
    mutated by callers.
    Nr   é   )ru   rz   r\   Ú_build_https_context)rq   ÚkeyÚcachedÚcontextÚ	used_paths        r    Ú_resolved_https_contextr‚   ‰   sl   € ô 'Ó(€JÙØÜ
˜J q™MÓ
*€CÜ!€FØÐ˜f Q™i¨3Ò.Ø�a‰yÐÜ-¨jÓ9Ñ€GˆYØ�J˜q‘MÒ!ð
 !$ W˜~ÐØ€Nr"   c                óî   — | D ]  }	 t        j                  |¬«      |fc S  | rt        j                  d«       y# t        t         j                  f$ r!}t        j                  d||«       Y d}~Œld}~ww xY w)zQReturn ``(context, path)`` for the first loadable candidate, or ``(None, None)``.)ÚcafileuD   CA bundle could not be loaded from %s: %s â€” trying the next bundleNuP   No configured CA bundle could be loaded â€” falling back to default certificates)NN)ÚsslÚcreate_default_contextrx   ÚSSLErrorri   rj   )rq   ry   rt   s      r    r}   r}   ¤   sw   € àò nˆð	nÜ×-Ñ-°TÔ:¸DÐ@Ò@ðnñ
 Ü�‰ÐiÔjØøô	 œŸ™Ð&ò 	nÜ�N‰NÐaÐcgÐil×mÑmûð	nús   ‡:ºA4ÁA/Á/A4©Ússl_contextc               óü  — t        t        j                  dd«      }|€It        «       }t        j                  j                  |€g n t        j                  j                  |¬«      gŽ }t        t        j                  dd«      }|duxr |du}t        |dd«      D �cg c]I  }t        |t        j                  j                  «      s#|rt        ||«      st        j                  |«      ‘ŒK }}|r|j                   ||¬«      «       |j                  t        | «      «       |j                  t        | «      «       t        j                  j                  |Ž }t        t        |dd«      «      |_        g |_        |S c c}w )a_  Clone the installed opener's handlers, replacing redirect policy only.

    ``ssl_context`` rebinds the cloned HTTPS handler so per-provider TLS settings
    (``ssl_ca_cert``/``ssl_verify``) apply; with None a Hermes-owned opener gets the explicit CA
    default from ``_resolved_https_context`` and an application-installed opener keeps its TLS.
    Ú_openerN)r€   ÚHTTPSHandlerÚhandlersr[   Ú
addheaders)Úgetattrr   r'   r‚   Úbuild_openerrŒ   Ú
isinstanceÚHTTPRedirectHandlerÚcopyrh   r-   rQ   r$   Ú_hermes_initial_addheadersrŽ   )	r9   r‰   Ú	installedr€   Ú_https_handler_clsÚreplace_httpsÚhandlerr�   Úsecureds	            r    Ú$_secure_opener_from_installed_policyrš   °   sG  € ô œŸ™¨	°4Ó8€IØÐÜ)Ó+ˆÜ—N‘N×/Ñ/¸¸±"ÌfÏnÉn×NiÑNiÐryÐNiÓNzÐM{Ð}ˆ	ä ¤§¡°ÀÓFÐØ tÐ+ÒNÐ0BÈ$Ð0N€Mô ˜y¨*°bÓ9öàÜ˜'¤6§>¡>×#EÑ#EÔFÙ¤:¨gÐ7IÔ#Jô 	�	‰	�'Õð€Hð ñ Ø�‰Ñ*°;Ô?Ô@Ø‡O�OÔ1°,Ó?Ô@Ø‡O�OÔ0°Ó>Ô?Ü�n‰n×)Ñ)¨8Ð4€Gô *.¬g°iÀÈrÓ.RÓ)S€GÔ&Ø€GÔØ€Nùòs   ÂAE9)Úopener_factoryr‰   c               ó  — |€Qt        | j                  |¬«      }t        |dd«      D ])  \  }}| j                  |«      rŒ| j	                  ||«       Œ+ n |t        | j                  «      «      }|j                  | |¬«      S )a`  Open a request without forwarding credentials across origins.

    Preserves an application-installed opener's proxy/TLS/cookies/handlers while replacing its
    redirect handler. ``opener_factory`` is an explicit test seam (security is never disabled
    based on global ``urlopen`` identity); ``ssl_context`` overrides TLS for this request only.
    rˆ   r”   r[   )Útimeout)rš   r?   r�   Ú
has_headerÚ
add_headerr-   Úopen)r'   r�   r›   r‰   Úopenerr)   rb   s          r    Úopen_credentialed_urlr¢   Ð   sƒ   € ð ÐÜ5°g×6FÑ6FÐT_Ô`ˆÜ" 6Ð+GÈÓLò 	0‰KˆD�%Ø×%Ñ% dÕ+Ø×"Ñ" 4¨Õ/ñ	0ñ  Ô =¸g×>NÑ>NÓ OÓPˆØ�;‰;�w¨ˆ;Ó0Ð0r"   )r-   r¢   r!   )r   r2   rH   ztuple[str, str, int | None])r(   zfrozenset[str]rH   rI   )rH   útuple[str, ...])ry   r2   rH   rp   )rH   zssl.SSLContext | None)rq   r£   rH   z(tuple[ssl.SSLContext | None, str | None])r9   r2   )r'   rV   r�   rW   r›   zCallable[..., Any] | None)+rM   Ú
__future__r   r“   Úloggingr_   r…   rk   Úurllib.parser   Úurllib.requestÚcollections.abcr   r   Úpathlibr   Útypingr   Úutilsr   Ú	getLoggerrJ   ri   r6   rN   r   re   r!   r+   r'   r’   r-   ÚBaseHandlerrQ   r\   Ú__annotations__ru   rz   r‚   r}   rš   r¢   Ú__all__r[   r"   r    ú<module>r°      sø   ðÚ Då "ã Û Û 	Û 
Û 
Û Û ß .Ý Ý å  à	ˆ×	Ñ	˜8Ó	$€ñ '¨°,Ð'?Ó@Ð Ø sÑ+€ØcÐ óyó(ô F§N¡N×$FÑ$Fô ô, 6§>¡>×#=Ñ#=ô ð2 =AÐ Ð9Ó @óó>	óó6	ð LPõ ðH 15Øñ1Ø#ð1ð ð1ð .ó	1ò. S�r"   