U
    8ÄT_ä5  ã                   @   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 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   ZCSRF_FAILURE_VIEW© r   r   ú:/tmp/pip-unpacked-wheel-dv63caxw/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 ‡ fdd„|D ƒ¡}|| S )z�
    Given a secret (assumed to be a string of CSRF_ALLOWED_CHARS), generate a
    token by adding a mask and applying it to the secret.
    c                 3   s   | ]}ˆ   |¡V  qd S ©N©Úindex©Ú.0Úx©Úcharsr   r   Ú	<genexpr>4   s     z&_mask_cipher_secret.<locals>.<genexpr>Ú c                 3   s&   | ]\}}ˆ || t ˆ ƒ  V  qd S r   )Úlen©r   r   Úyr   r   r   r   5   s     )r   r   ÚzipÚjoin)ÚsecretÚmaskÚpairsÚcipherr   r   r   Ú_mask_cipher_secret-   s
    &r)   c                    sZ   | dt … }| t d… } t‰ t‡ fdd„| D ƒ‡ fdd„|D ƒƒ}d ‡ 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 mask), use it to decrypt
    the second half to produce the original secret.
    Nc                 3   s   | ]}ˆ   |¡V  qd S r   r   r   r   r   r   r   B   s     z'_unmask_cipher_token.<locals>.<genexpr>r   c                 3   s   | ]\}}ˆ ||  V  qd S r   r   r!   r   r   r   r   C   s     )r   r   r#   r$   )Útokenr&   r'   r   r   r   Ú_unmask_cipher_token9   s
    &r+   c                   C   s
   t tƒ ƒS r   )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    


r1   c                 C   s   | 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)r0   r   r   r   Úrotate_token]   s
    þr4   c                 C   s<   t  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    r8   c                 C   s   t t| ƒt|ƒƒS r   )r   r+   )Úrequest_csrf_tokenÚ
csrf_tokenr   r   r   Ú_compare_masked_tokensz   s    þr;   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)Úselfr0   r   r   r   Ú_accept�   s    zCsrfViewMiddleware._acceptc                 C   s(   t ƒ ||d�}td||j||td� |S )N)ÚreasonzForbidden (%s): %s)Úresponser0   Úlogger)r   r   ÚpathrB   )r>   r0   r@   rA   r   r   r   Ú_reject”   s      üzCsrfViewMiddleware._rejectc                 C   sz   t jr4z|j t¡W S  tk
r0   tdƒ‚Y qvX nBz|jt j }W n t	k
rZ   Y d S X t
|ƒ}||krrd|_|S d S )Nz„CSRF_USE_SESSIONS is enabled, but request.session is not set. SessionMiddleware must appear before CsrfViewMiddleware in MIDDLEWARE.T)r   ÚCSRF_USE_SESSIONSÚsessionÚgetÚCSRF_SESSION_KEYÚAttributeErrorr   ZCOOKIESÚCSRF_COOKIE_NAMEÚKeyErrorr8   r3   )r>   r0   Zcookie_tokenr:   r   r   r   Ú
_get_tokenž   s    ÿzCsrfViewMiddleware._get_tokenc              
   C   sj   t jr.|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-   )Zmax_ageÚdomainrC   ÚsecureÚhttponlyÚsamesite)ÚCookie)r   rE   rF   rG   rH   r/   Ú
set_cookierJ   ZCSRF_COOKIE_AGEÚCSRF_COOKIE_DOMAINZCSRF_COOKIE_PATHZCSRF_COOKIE_SECUREZCSRF_COOKIE_HTTPONLYZCSRF_COOKIE_SAMESITEr   ©r>   r0   rA   r   r   r   Ú
_set_tokenµ   s    øzCsrfViewMiddleware._set_tokenc                 C   s    |   |¡}|d k	r||jd< d S )Nr-   )rL   r/   )r>   r0   r:   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�rât |ddƒrB|  |¡S | ¡ �rN|j d¡‰ ˆ d krl|  |t¡S tˆ ƒ‰ dˆ j	ˆ j
fkr�|  |t¡S ˆ j	dkr¦|  |t¡S tjr²tjntj}|d k	rÞ| ¡ }|d	krÜd
||f }n"z| ¡ }W n tk
rþ   Y nX ttjƒ}|d k	�r| |¡ t‡ fdd„|D ƒƒ�sNtˆ  ¡  }|  ||¡S |  |¡}	|	d k�rn|  |t¡S d}
|jdk�r¨z|j dd¡}
W n tk
�r¦   Y nX |
dk�rÂ|j tjd¡}
t|
ƒ}
t |
|	ƒ�sâ|  |t!¡S |  |¡S )Nr=   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 r   )r   Únetloc)r   Úhost©Zrefererr   r   r     s     z2CsrfViewMiddleware.process_view.<locals>.<genexpr>ÚPOSTZcsrfmiddlewaretoken)"ÚgetattrÚmethodr?   Z	is_securer/   rG   rD   ÚREASON_NO_REFERERr   Úschemer^   ÚREASON_MALFORMED_REFERERÚREASON_INSECURE_REFERERr   rE   ZSESSION_COOKIE_DOMAINrS   Zget_portÚget_hostr   ÚlistZCSRF_TRUSTED_ORIGINSÚappendÚanyÚREASON_BAD_REFERERÚgeturlrL   ÚREASON_NO_CSRF_COOKIEra   ÚOSErrorZCSRF_HEADER_NAMEr8   r;   ÚREASON_BAD_TOKEN)r>   r0   ÚcallbackÚcallback_argsÚcallback_kwargsZgood_refererZserver_portZ
good_hostsr@   r:   r9   r   r`   r   Úprocess_viewÍ   sb    


ÿý





zCsrfViewMiddleware.process_viewc                 C   sD   t |ddƒst |ddƒr|S |j dd¡s.|S |  ||¡ d|_|S )Nr3   FÚcsrf_cookie_setr.   T)rb   r/   rG   rU   ru   rT   r   r   r   Úprocess_response=  s    z#CsrfViewMiddleware.process_responseN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r?   rD   rL   rU   rV   rt   rv   r   r   r   r   r<   ƒ   s   	
pr<   )0rz   Úloggingr5   ÚstringÚurllib.parser   Zdjango.confr   Zdjango.core.exceptionsr   r   Zdjango.urlsr   Zdjango.utils.cacher   Zdjango.utils.cryptor   r	   Zdjango.utils.deprecationr
   Zdjango.utils.httpr   Zdjango.utils.logr   Ú	getLoggerrB   rd   rl   rn   rp   rf   rg   r   r7   Úascii_lettersÚdigitsr   rH   r   r   r)   r+   r,   r1   r4   r8   r;   r<   r   r   r   r   Ú<module>   sB   
	