o
    i)"                     @   s6  U d Z ddl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	 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 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 ddlmZ eeZe Z ed e!d< G dd dZ"G dd dZ#dd Z$d dee# fddZ%de#defddZ&dS )!a  IAST module patching implementation.

This module provides the core functionality for patching Python functions to enable IAST analysis.
It implements the wrapper classes and utilities needed to:
1. Wrap security-sensitive functions using wrapt
2. Manage module patching state
3. Handle forced patching when needed
4. Support testing scenarios with unpatching capabilities

The module uses wrapt's function wrapping capabilities to intercept calls to security-sensitive
functions and enable taint tracking and vulnerability detection.
    N)Callable)Optional)Text)FunctionWrapper)$iast_instrumentation_wrapt_debug_log)SecurityControl)get_security_controls_from_env)SC_SANITIZER)SC_VALIDATOR)create_sanitizer)create_validator)
try_unwrap)try_wrap_function_wrapper)wrap_object)
get_logger)configIASTFunctionMODULES_TO_UNPATCHc                   @   s\   e Zd ZdZdZdZdZdZdddZe	de
de
defd	d
Zdd Zdd Zdd ZdS )r   a  Represents a function to be patched for IAST analysis.

    This class encapsulates the information needed to patch a specific function in a module
    for IAST analysis. It handles both forced and lazy patching scenarios.

    Attributes:
        name (str): The name of the module to patch
        function (str): The name of the function to wrap
        hook (callable): The wrapper function to apply
        force (bool): Whether to force immediate patching or wait for module import
     Fc                 C   s   || _ || _|| _|| _dS )aH  Initialize an IASTFunction instance.

        Args:
            name (str): The name of the module to patch
            function (str): The name of the function to wrap
            hook (callable): The wrapper function to apply
            force (bool, optional): Whether to force immediate patching. Defaults to False.
        Nnamefunctionhookforce)selfr   r   r   r    r   W/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/appsec/_iast/_patch_modules.py__init__:   s   	
zIASTFunction.__init__moduler   wrapperc              	   C   sF   zt | |t|f W dS  ttfy"   td|  d| d Y dS w )al  Force immediate wrapping of a module's function.

        This method attempts to immediately wrap a function in a module, regardless of
        whether the module has been imported yet.

        Args:
            module (str): The module name
            name (str): The function name to wrap
            wrapper (callable): The wrapper function to apply
        zModule .z not existsN)r   r   ImportErrorAttributeErrorr   )r   r   r   r   r   r   force_wrapperH   s
   zIASTFunction.force_wrapperc                 C   s8   | j du r| | j| j| j dS t| j| j| j dS )a#  Apply the patch to the target module and function.

        This method handles both forced and lazy patching scenarios. If force is True,
        it attempts immediate patching. Otherwise, it sets up lazy patching.

        Returns:
            bool: True if patching was attempted
        T)r   r#   r   r   r   r   r   r   r   r   patchY   s
   
	zIASTFunction.patchc                 C   s   t | j| j dS )zRemove the patch from the target module and function.

        This method attempts to remove any existing wrapper from the target function.
        N)r   r   r   r$   r   r   r   unpatchh   s   zIASTFunction.unpatchc              	   C   s&   d| j  d| j d| j d| j d	S )z<Return a string representation of the IASTFunction instance.zIASTFunction(name=z, function=z, hook=z, force=)r   r$   r   r   r   __repr__o   s   &zIASTFunction.__repr__N)F)__name__
__module____qualname____doc__r   r   r   r   r   staticmethodr   r   r#   r%   r&   r(   r   r   r   r   r   (   s    
c                   @   s:   e Zd ZdZdddZdd Zdd	 Zd
d Zdd ZdS )WrapFunctonsForIASTa  Manages the collection and patching of IAST modules.

    This class maintains a set of IASTFunction instances and handles their patching
    and unpatching. It supports both normal operation and testing scenarios.

    Attributes:
        functions (set[IASTFunction]): set of modules to be patched
        testing (bool): Whether the instance is being used in a testing context
    returnNc                 C   s   t  | _tj| _dS )z*Initialize a WrapFunctonsForIAST instance.N)set	functions
asm_config_iast_is_testingtestingr$   r   r   r   r      s   zWrapFunctonsForIAST.__init__c                 C   s   | j t||| dS )zAdd a function for lazy patching.

        Args:
            name (str): The module name
            function (str): The function name to wrap
            hook (callable): The wrapper function to apply
        Nr1   addr   r   r   r   r   r   r   r   wrap_function   s   z!WrapFunctonsForIAST.wrap_functionc                 C   s   | j t|||d dS )zAdd a module for forced immediate patching.

        Args:
            name (str): The module name
            function (str): The function name to wrap
            hook (callable): The wrapper function to apply
        TNr5   r7   r   r   r   add_module_forced   s   z%WrapFunctonsForIAST.add_module_forcedc                 C   s(   | j D ]}| r| jrt| qdS )zApply patches to all registered functions.

        This method attempts to patch all functions in the functions set. If in testing
        mode, it also tracks the functions for later unpatching.
        N)r1   r%   r4   r   r6   r   r   r   r   r   r%      s   

zWrapFunctonsForIAST.patchc                 C   sB   t d| jtt | jrt D ]}|  t| qdS dS )zRemove patches from all functions in testing mode.

        This method is used in testing scenarios to clean up all applied patches.
        It only operates if the instance is in testing mode.
        zTesting: %s. Unwrapping %sN)logdebugr4   lenr   copyr&   remover:   r   r   r   testing_unpatch   s   z#WrapFunctonsForIAST.testing_unpatch)r/   N)	r)   r*   r+   r,   r   r8   r9   r%   r@   r   r   r   r   r.   t   s    



r.   c                  C   s   t  } |   dS )zUtility function to unpatch all IAST functions in testing mode.

    This function creates a WrapFunctonsForIAST instance and uses it to remove
    all patches that were applied during testing.
    N)r.   r@   )
iast_funcsr   r   r   _testing_unpatch_iast   s   rB   rA   c              	   C   s   z<| du rt  } t }|std W dS tdt| |D ]}zt| | W q ty9   tjd|dd Y qw | W S  tyM   tjddd Y dS w )zaApply custom security controls from DD_IAST_SECURITY_CONTROLS_CONFIGURATION environment variable.Nz&No custom security controls configuredz$Applying %s custom security controlsz#Failed to apply security control %sT)exc_infoz'Failed to load custom security controls)r.   r   r;   r<   r=   _apply_security_control	Exceptionwarning)rA   security_controlscontrolr   r   r   _apply_custom_security_controls   s$   
rI   rH   c                 C   s   |j tkrtt|j}n|j tkrtt|j|j}n	t	
d|j  dS | |j|j| t	d|j |j|jdd |jD  dS )zApply a single security control configuration.

    Args:
        control: SecurityControl object containing the configuration
    zUnknown control type: %sNz-Configured %s for %s.%s (vulnerabilities: %s)c                 S   s   g | ]}|j qS r   )r   ).0vr   r   r   
<listcomp>   s    z+_apply_security_control.<locals>.<listcomp>)control_typer	   	functoolspartialr   vulnerability_typesr
   r   
parametersr;   rF   r8   module_pathmethod_namer<   )rA   rH   wrapper_funcr   r   r   rD      s$   

rD   )N)'r,   rN   typingr   r   r   wraptr   ddtrace.appsec._iast._logsr   !ddtrace.appsec._iast.secure_marksr   r   /ddtrace.appsec._iast.secure_marks.configurationr	   r
   ,ddtrace.appsec._iast.secure_marks.sanitizersr   ,ddtrace.appsec._iast.secure_marks.validatorsr   ddtrace.appsec._patch_utilsr   r   r   ddtrace.internal.loggerr   ddtrace.internal.settings.asmr   r2   r)   r;   r0   r   __annotations__r   r.   rB   rI   rD   r   r   r   r   <module>   s2    L<
