3
v^k5                 @   s*  d Z ddlZddlZddlZddlmZ ddlmZ ddlm	Z	m
Z
 ddlmZ ddlm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dZdZdZdZdZdZdZdZ de  Z!ej"ej# Z$dZ%dd Z&dd Z'dd Z(dd Z)dd Z*d d! Z+d"d# Z,d$d% Z-d&d' Z.G d(d) d)eZ/dS )*z
Cross Site Request Forgery Middleware.

This module provides a middleware that implements protection
against request forgeries from other sites.
    N)urlparse)settings)DisallowedHostImproperlyConfigured)get_callable)patch_vary_headers)constant_time_compareget_random_string)MiddlewareMixin)is_same_domain)log_responsezdjango.security.csrfz%Referer checking failed - no Referer.z@Referer checking failed - %s does not match any trusted origins.zCSRF cookie not set.z CSRF token missing or incorrect.z/Referer checking failed - Referer is malformed.zCReferer checking failed - Referer is insecure while host is secure.       Z
_csrftokenc               C   s
   t tjS )z/Return the view to be used for CSRF rejections.)r   r   CSRF_FAILURE_VIEW r   r   :/usr/lib/python3.6/site-packages/django/middleware/csrf.py_get_failure_view$   s    r   c               C   s   t ttdS )N)allowed_chars)r	   CSRF_SECRET_LENGTHCSRF_ALLOWED_CHARSr   r   r   r   _get_new_csrf_string)   s    r   c                sP   t  }t t fdd| D  fdd|D }dj fdd|D }|| S )z
    Given a secret (assumed to be a string of CSRF_ALLOWED_CHARS), generate a
    token by adding a salt and using it to encrypt the secret.
    c             3   s   | ]} j |V  qd S )N)index).0x)charsr   r   	<genexpr>4   s    z&_salt_cipher_secret.<locals>.<genexpr> c             3   s&   | ]\}} || t    V  qd S )N)len)r   r   y)r   r   r   r   5   s    )r   r   zipjoin)secretsaltpairscipherr   )r   r   _salt_cipher_secret-   s
    &r%   c                sZ   | dt  }| t d } t t fdd| D  fdd|D }dj fdd|D S )z
    Given a token (assumed to be a string of CSRF_ALLOWED_CHARS, of length
    CSRF_TOKEN_LENGTH, and that its first half is a salt), use it to decrypt
    the second half to produce the original secret.
    Nc             3   s   | ]} j |V  qd S )N)r   )r   r   )r   r   r   r   B   s    z'_unsalt_cipher_token.<locals>.<genexpr>r   c             3   s   | ]\}} ||  V  qd S )Nr   )r   r   r   )r   r   r   r   C   s    )r   r   r   r    )tokenr"   r#   r   )r   r   _unsalt_cipher_token9   s
    &r'   c               C   s
   t t S )N)r%   r   r   r   r   r   _get_new_csrf_tokenF   s    r(   c             C   s@   d| j kr t }t|| j d< nt| j d }d| j d< t|S )a  
    Return the CSRF token required for a POST form. The token is an
    alphanumeric value. A new token is created if one is not already set.

    A side effect of calling this function is to make the csrf_protect
    decorator and the CsrfViewMiddleware add a CSRF cookie and a 'Vary: Cookie'
    header to the outgoing response.  For this reason, you may need to use this
    function lazily, as is done by the csrf context processor.
    CSRF_COOKIETCSRF_COOKIE_USED)METAr   r%   r'   )requestZcsrf_secretr   r   r   	get_tokenJ   s    


r-   c             C   s   | j jdt d d| _dS )zi
    Change the CSRF token in use for a request - should be done on login
    for security purposes.
    T)r*   r)   N)r+   updater(   csrf_cookie_needs_reset)r,   r   r   r   rotate_token]   s    r0   c             C   s<   t jd| rt S t| tkr"| S t| tkr6t| S t S )Nz[^a-zA-Z0-9])researchr(   r   CSRF_TOKEN_LENGTHr   r%   )r&   r   r   r   _sanitize_tokeni   s    r4   c             C   s   t t| t|S )N)r   r'   )request_csrf_token
csrf_tokenr   r   r   _compare_salted_tokensz   s    r7   c               @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )CsrfViewMiddlewarez
    Require a present and correct csrfmiddlewaretoken for POST requests that
    have a CSRF cookie, and set an outgoing CSRF cookie.

    This middleware should be used in conjunction with the {% csrf_token %}
    template tag.
    c             C   s
   d|_ d S )NT)csrf_processing_done)selfr,   r   r   r   _accept   s    zCsrfViewMiddleware._acceptc             C   s(   t  ||d}td||j||td |S )N)reasonzForbidden (%s): %s)responser,   logger)r   r   pathr>   )r:   r,   r<   r=   r   r   r   _reject   s    zCsrfViewMiddleware._rejectc             C   s   t jrDy|jjtS  tk
r@   tdt jd kr4dnd Y qX n@y|jt j	 }W n t
k
rh   d S X t|}||krd|_|S d S )NzCSRF_USE_SESSIONS is enabled, but request.session is not set. SessionMiddleware must appear before CsrfViewMiddleware in MIDDLEWARE%s.Z_CLASSESr   T)r   CSRF_USE_SESSIONSsessiongetCSRF_SESSION_KEYAttributeErrorr   
MIDDLEWARECOOKIESCSRF_COOKIE_NAMEKeyErrorr4   r/   )r:   r,   Zcookie_tokenr6   r   r   r   
_get_token   s    zCsrfViewMiddleware._get_tokenc          
   C   sj   t jr.|jjt|jd krf|jd |jt< n8|jt j|jd t jt j	t j
t jt jt jd t|d d S )Nr)   )max_agedomainr?   securehttponlysamesiteCookie)rP   )r   rA   rB   rC   rD   r+   
set_cookierH   CSRF_COOKIE_AGECSRF_COOKIE_DOMAINCSRF_COOKIE_PATHCSRF_COOKIE_SECURECSRF_COOKIE_HTTPONLYCSRF_COOKIE_SAMESITEr   )r:   r,   r=   r   r   r   
_set_token   s    
zCsrfViewMiddleware._set_tokenc             C   s    | j |}|d k	r||jd< d S )Nr)   )rJ   r+   )r:   r,   r6   r   r   r   process_request   s    
z"CsrfViewMiddleware.process_requestc                s  t |ddrd S t |ddr d S |jdkrt |ddrB| j|S |j rP|jjd	  d krl| j|tS t  d
 j	 j
fkr| j|tS  j	dkr| j|tS tjrtjntj}|d k	r|j }|dkrd||f }n$y|j }W n tk
r    Y nX ttj}|d k	r |j| t fdd|D sPt j  }| j||S |jjd}	|	d krr| j|tS d
}
|jdkry|jjdd
}
W n tk
r   Y nX |
d
kr|jjtjd
}
t|
}
t|
|	s| j|t S | j|S )Nr9   FZcsrf_exemptGETHEADOPTIONSTRACEZ_dont_enforce_csrf_checksZHTTP_REFERERr   https44380z%s:%sc             3   s   | ]}t  j|V  qd S )N)r   netloc)r   host)refererr   r   r     s    z2CsrfViewMiddleware.process_view.<locals>.<genexpr>r)   POSTZcsrfmiddlewaretoken)rZ   r[   r\   r]   )r_   r`   )!getattrmethodr;   	is_securer+   rC   r@   REASON_NO_REFERERr   schemera   REASON_MALFORMED_REFERERREASON_INSECURE_REFERERr   rA   SESSION_COOKIE_DOMAINrS   get_portget_hostr   listCSRF_TRUSTED_ORIGINSappendanyREASON_BAD_REFERERgeturlREASON_NO_CSRF_COOKIErd   OSErrorCSRF_HEADER_NAMEr4   r7   REASON_BAD_TOKEN)r:   r,   callbackZcallback_argsZcallback_kwargsZgood_refererserver_portZ
good_hostsr<   r6   r5   r   )rc   r   process_view   s^    







zCsrfViewMiddleware.process_viewc             C   sD   t |ddst |ddr|S |jjdds.|S | j|| d|_|S )Nr/   Fcsrf_cookie_setr*   T)re   r+   rC   rX   r|   )r:   r,   r=   r   r   r   process_response:  s    z#CsrfViewMiddleware.process_responseN)__name__
__module____qualname____doc__r;   r@   rJ   rX   rY   r{   r}   r   r   r   r   r8      s   
mr8   )0r   loggingr1   stringurllib.parser   django.confr   django.core.exceptionsr   r   django.urlsr   Zdjango.utils.cacher   django.utils.cryptor   r	   django.utils.deprecationr
   django.utils.httpr   django.utils.logr   	getLoggerr>   rh   rs   ru   rx   rj   rk   r   r3   ascii_lettersdigitsr   rD   r   r   r%   r'   r(   r-   r0   r4   r7   r8   r   r   r   r   <module>   sB   
	