a
    mzfk9                  	   @   s  d Z ddlZddlZddlZddlZddlmZ dZdZ	dZ
dZdZd	ZG d
d dejZdUddZejdd Zejdd Zejdd Zejdd Zdd Zdd Zdd Zejdddd jeejjd! fd"d# Zd$d% Z d&d' Z!ejdd(d)d* Z"d+d, Z#d-d. Z$d/d0 Z%d1d2 Z&d3d4 Z'ejj(d5d6d7d8d9 Z)ejd:d;ed<fd=ed>fd?ed@fdAedBffdCdD Z*dEdF Z+dGdH Z,dIdJ Z-dKdL Z.G dMdN dNZ/G dOdP dPZ0ejdQdR Z1dSdT Z2dS )Vz9Tests for managing HTTP issues (malformed requests, etc).    N)helperi  i  i  i     i  c                   @   sd   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdedededeedeedededeiZ	dS )HelloControllerz!Controller for serving WSGI apps.c                 C   s   dS )zRender Hello world.Hello world! reqrespr   r   D/var/www/media/lib/python3.9/site-packages/cheroot/test/test_core.pyhello   s    zHelloController.helloc                 C   s    | j dddu rd|_dS dS )zRender Hello world or set 411.Content-LengthNz411 Length Requiredr   )environgetstatusr   r   r   r
   body_required   s    zHelloController.body_requiredc                 C   s   | j ddS )zRender QUERY_STRING value.QUERY_STRING )r   r   r   r   r   r
   query_string"   s    zHelloController.query_stringc                 C   s$   | j dd}d}|jf i t S )zRender request method value.REQUEST_METHODzNO METHOD FOUNDz*Got asterisk URI path with {method} method)r   r   formatlocals)r   r	   methodtmplr   r   r
   asterisk&   s    zHelloController.asteriskc                 C   s   |  ddS )zEncode PATH_INFO correctly depending on Python version.

        WSGI 1.0 is a mess around unicode. Create endpoints
        that match the PATH_INFO that it produces.
        utf-8latin-1)encodedecode)stringr   r   r
   _munge-   s    zHelloController._munge/hello/no_body/body_requiredz/query_stringu   /привітu   /Юххууу   / Ðblah key 0 900 4 dataz/*N)
__name__
__module____qualname____doc__r   r   r   r   r   handlersr   r   r   r
   r      s   	r   GETc                 C   s   | j | j|dS )Nr   )response_classsock)
connectionr   r   r   r
   _get_http_responseG   s    r.   c                 C   s   | j }t |_d|_| |_|S :Attach a WSGI app to the given server and preconfigure it.i)server_instancer   wsgi_appmax_request_body_sizeserver_clientZwsgi_server_clientZwsgi_serverr   r   r
   testing_serverK   s
    r6   c                 C   s   | j S z5Get and return a test client out of the given server.r4   )r6   r   r   r
   test_clientU   s    r9   c                 C   s   | j }t |_| |_|S )r0   )r1   r   r2   r4   r5   r   r   r
   testing_server_with_defaults[   s    r:   c                 C   s   | j S r7   r8   )r:   r   r   r
   test_client_with_defaultsd   s    r;   c                 C   s.   |  dd }t|dd }|dks*J dS )z>Check that CONNECT query results in Method Not Allowed status.z	/anythingr   N   i  )connectint)r9   status_lineactual_statusr   r   r
   test_http_connect_requestj   s    rA   c                 C   s<   |  d\}}}t|dd }|tks,J |dks8J dS )z%Check that normal GET query succeeds.r    Nr<      Hello world!r   r>   HTTP_OKr9   r?   _actual_resp_bodyr@   r   r   r
   test_normal_requestq   s    rH   c                 C   s<   |  d\}}}t|dd }|tks,J |dks8J dS )z$Check that GET param is parsed well./query_string?test=TrueNr<   s	   test=TruerC   rE   r   r   r
   test_query_string_requesty   s    
rJ   urir    rI   z/{0}?{1}={2})u   Юххуууu   їu   йоc                 C   s.   |  |d }t|dd }|tks*J dS )z8Check that server responds with OK to valid GET queries.r   Nr<   rC   )r9   rK   r?   r@   r   r   r
   test_parse_acceptable_uri   s    rL   c                 C   s   |   }dd}tj|}|dks*J djf i t }||d |  t	|dd}|
  |jtksvJ |dd	ksJ |  d
S )a#  Test that malicious URI does not allow HTTP injection.

    This effectively checks that sending GET request with URL

    /%A0%D0blah%20key%200%20900%204%20data

    is not converted into

    GET /
    blah key 0 900 4 data
    HTTP/1.1

    which would be a security issue otherwise.
    r#   r   z&/%A0%D0blah%20key%200%20900%204%20datazGET {quoted} HTTP/1.1r   r)   r*      rB   N)get_connectionr   urllibparsequoter   r   _output_send_outputr.   beginr   rD   readclose)r9   cresourcequotedrequestresponser   r   r
   test_parse_uri_unsafe_uri   s    
r\   c                 C   s`   |   }|dd |  t|dd}|  |jtksBJ |ddksTJ |	  dS )zCheck that server responds with Bad Request to invalid GET queries.

    Invalid request line test case: it should only contain US-ASCII.
    u   GET /йопта! HTTP/1.1r   r)   r*      s   Malformed Request-URIN)
rN   rR   r   rS   r.   rT   r   HTTP_BAD_REQUESTrU   rV   )r9   rW   r[   r   r   r
   test_parse_uri_invalid_uri   s    r_   )r   u   привітc                 C   sD   |  tj|\}}}t|dd }|tks4J d|v s@J dS )zCheck that server responds with Bad Request to invalid GET queries.

    Invalid request line test case: it should have leading slash (be absolute).
    Nr<   s   starting with a slash)r   rO   rP   rQ   r>   r^   )r9   rK   r?   rF   rG   r@   r   r   r
   #test_parse_no_leading_slash_invalid   s    

r`   c                 C   s@   |  d\}}}t|dd }|tks,J d}||ks<J dS )zlCheck that server responds with Bad Request to Absolute URI.

    Only proxy servers should allow this.
    zhttp://google.com/Nr<   s2   Absolute URI not allowed if server is not a proxy.r   r>   r^   r9   r?   rF   rG   r@   expected_bodyr   r   r
   test_parse_uri_absolute_uri   s
    rd   c                 C   s@   |  d\}}}t|dd }|tks,J d}||ks<J dS )zDCheck that server responds with OK to OPTIONS with "*" Absolute URI.*Nr<   s)   Got asterisk URI path with OPTIONS method)optionsr>   rD   rb   r   r   r
   test_parse_uri_asterisk_uri   s
    rg   c                 C   s@   |  d\}}}t|dd }|tks,J d}||ks<J dS )zACheck that server responds with Bad Request to URI with fragment.z/hello?test=something#fakeNr<   s!   Illegal #fragment in Request-URI.ra   rb   r   r   r
   test_parse_uri_fragment_uri   s    
rh   c                 C   sN   |   }|dd | }| }|j}|tks6J |dksBJ |  dS )z4Test POST query with an empty body being successful.POSTr!   rB   N)rN   rZ   getresponserU   r   rD   rV   )r9   rW   r[   rG   r@   r   r   r
   test_no_content_length   s    rk   c                 C   sB   |   }|dd | }|  |j}|tks6J |  dS )zDTest POST query with body failing because of missing Content-Length.ri   r"   N)rN   rZ   rj   rU   r   HTTP_LENGTH_REQUIREDrV   )r9   rW   r[   r@   r   r   r
   test_content_length_required  s    rm   z.https://github.com/cherrypy/cheroot/issues/106F)reasonstrictc                 C   sJ   |   }|dd |dtd |  | }|j}|tksFJ dS )z5Test GET query with maliciously large Content-Length.r)   r    r   l            N)rN   
putrequest	putheaderstr
endheadersrj   r   HTTP_REQUEST_ENTITY_TOO_LARGE)r;   rW   r[   r@   r   r   r
   test_large_request  s    ru   )request_linestatus_coderc   s   GET /   Malformed Request-Lines   GET / HTTPS/1.1s$   Malformed Request-Line: bad protocols   GET / HTTP/1s#   Malformed Request-Line: bad versions   GET / HTTP/2.15s   Cannot fulfill requestc                 C   s^   |   }|| |  t|dd}|  |j|ks<J |t||ksRJ |  dS )z5Test missing or invalid HTTP version in Request-Line.r)   r*   N)	rN   rR   rS   r.   rT   r   rU   lenrV   )r9   rv   rw   rc   rW   r[   r   r   r
   test_malformed_request_line-  s    
rz   c                 C   sd   |   }|dd |dd |  | }|j}|tksBJ |d}|dksXJ |  dS )zTest non-uppercase HTTP method.ZGeTz/malformed_method_caseContent-Type
text/plainr]   s   Malformed method nameN)	rN   rp   rq   rs   rj   r   r^   rU   rV   r9   rW   r[   r@   rG   r   r   r
   test_malformed_http_methodQ  s    
r~   c                 C   sn   |   }|dd |dd |d |  | }|j}|tksLJ |d}|dksbJ |	  dS )	z5Check that broken HTTP header results in Bad Request.r)   /r{   r|   s   Re, 1.2.3.4#015#012   s   Illegal header line.N)
rN   rp   rq   rR   rs   rj   r   r^   rU   rV   r}   r   r   r
   test_malformed_headera  s    

r   c                 C   s6   d}t d| dksJ | |d }|dks2J dS )z?Check that HTTP request line of exactly 256 chars length is OK.z/hello?intervenant-entreprise-evenement_classaction=evenement-mailremerciements&_path=intervenant-entreprise-evenement&intervenant-entreprise-evenement_action-id=19404&intervenant-entreprise-evenement_id=19404&intervenant-entreprise_id=28092zGET %s HTTP/1.1
      rB   N)ry   r   )r9   ZRequest_URIrG   r   r   r
   "test_request_line_split_issue_1220s  s
    	r   c              
   C   s   |   }|d |  |j|jdd}z<|  |j}|tksFJ |d}|dks\J |	  W n4 t
jy } z|jtjkr W Y d}~n
d}~0 0 dS )z>Test that server sends an error for garbage received over TCP.s   gjkgjklsgjklsgjkljklsgr)   r*      rx   N)rN   rR   rS   r+   r,   rT   r   r^   rU   rV   socketerrorerrno
ECONNRESET)r9   rW   r[   r@   rG   exr   r   r
   test_garbage_in  s    

r   c                   @   s    e Zd ZdZdd Zdd ZdS )CloseControllerz*Controller for testing the close callback.c                 C   s*   |j j| _t| j}||j|j  |S )z'Get the req to know header sent status.)__self__r   CloseResponserV   r   headersitems)selfr   Zstart_responser	   r   r   r
   __call__  s    

zCloseController.__call__c                 C   s   | j d dS )zClose, writing hello.   helloN)r   writer   r   r   r
   rV     s    zCloseController.closeN)r$   r%   r&   r'   r   rV   r   r   r   r
   r     s   r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r   z3Dummy empty response to trigger the no body status.c                 C   s   d| _ ddi| _|| _dS )z-Use some defaults to ensure we have a header.z200 OKr{   z	text/htmlN)r   r   rV   )r   rV   r   r   r
   __init__  s    
zCloseResponse.__init__c                 C   s
   t  dS )zEnsure we don't have a body.N)
IndexError)r   indexr   r   r
   __getitem__  s    zCloseResponse.__getitem__c                 C   s   | S )z%Return self to hook the close method.r   r   r   r   r
   output  s    zCloseResponse.outputN)r$   r%   r&   r'   r   r   r   r   r   r   r
   r     s   r   c                 C   s   | j }t |_d|_| |_|S r/   )r1   r   r2   r3   r4   r5   r   r   r
   testing_server_close  s
    r   c                 C   s"   | j d\}}}|dksJ dS )z@Test we are actually sending the headers before calling 'close'.r   r   N)r4   r   )r   rF   Z	resp_bodyr   r   r
   test_send_header_before_closing  s    r   )r)   )3r'   r   r   urllib.parserO   ZpytestZcheroot.testr   r^   rl   ZHTTP_NOT_FOUNDrt   rD   HTTP_VERSION_NOT_SUPPORTEDZ
Controllerr   r.   Zfixturer6   r9   r:   r;   rA   rH   rJ   markZparametrizer   maprP   rQ   rL   r\   r_   r`   rd   rg   rh   rk   rm   Zxfailru   rz   r~   r   r   r   r   r   r   r   r   r   r   r
   <module>   s   3

	






	


	