U
    ςdT                     @   s   d 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 ddl	m
Z
 ddlmZmZmZmZmZmZmZ ddlmZ ddlmZmZ ddlmZ d	d
 ZG dd deZdd ZG dd dZdS )z
Packet handling
    N)HMAC)util)linefeed_bytecr_byte_value	MSG_NAMESDEBUG	xffffffff	zero_bytebyte_ord)u)SSHExceptionProxyCommandFailure)Messagec                 C   s   t | || S N)r   digest)keymessageZdigest_class r   L/var/www/html/myproject/myenv/lib/python3.8/site-packages/paramiko/packet.pycompute_hmac.   s    r   c                   @   s   e Zd ZdZdS )NeedRekeyExceptionz1
    Exception indicating a rekey is needed.
    N)__name__
__module____qualname____doc__r   r   r   r   r   2   s   r   c                 C   s.   d }t | jtkr*t| jdkr*| jd }|S )Nr   )typeargstuplelen)eargr   r   r   	first_arg:   s    
r!   c                   @   s"  e Zd ZdZeddZeddZeddZeddZdd Z	e
dd Zdd	 Zd>ddZd?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dd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd@d)d*Zd+d, Zd-d. Zd/d0 Zd1d2 Z d3d4 Z!d5d6 Z"d7d8 Z#d9d: Z$d;d< Z%d=S )A
Packetizerz9
    Implementation of the base SSH packet protocol.
          c                 C   s   || _ d | _d| _d| _d| _d| _t | _d| _d| _	d| _
d| _d| _d| _d| _d| _d| _d| _d | _d | _d| _d | _d | _t | _t | _d | _d | _d| _d| _d| _d| _t  | _!d| _"t## | _$d | _%d | _&d| _'d| _(d S )NFr      ))_Packetizer__socket_Packetizer__logger_Packetizer__closed_Packetizer__dump_packets_Packetizer__need_rekey_Packetizer__init_countbytes_Packetizer__remainder_Packetizer__sent_bytes_Packetizer__sent_packets_Packetizer__received_bytes_Packetizer__received_packets$_Packetizer__received_bytes_overflow&_Packetizer__received_packets_overflow_Packetizer__block_size_out_Packetizer__block_size_in_Packetizer__mac_size_out_Packetizer__mac_size_in_Packetizer__block_engine_out_Packetizer__block_engine_in_Packetizer__sdctr_out_Packetizer__mac_engine_out_Packetizer__mac_engine_in_Packetizer__mac_key_out_Packetizer__mac_key_in _Packetizer__compress_engine_out_Packetizer__compress_engine_in _Packetizer__sequence_number_out_Packetizer__sequence_number_in_Packetizer__etm_out_Packetizer__etm_in	threadingRLock_Packetizer__write_lock_Packetizer__keepalive_intervaltime_Packetizer__keepalive_last_Packetizer__keepalive_callback_Packetizer__timer_Packetizer__handshake_complete_Packetizer__timer_expired)selfsocketr   r   r   __init__Q   sJ    

zPacketizer.__init__c                 C   s   | j S r   )r(   rO   r   r   r   closed   s    zPacketizer.closedc                 C   s
   || _ dS )z?
        Set the Python log object to use for logging.
        N)r'   )rO   logr   r   r   set_log   s    zPacketizer.set_logFc                 C   s^   || _ || _|| _|| _|| _|| _d| _d| _|| _|  j	dO  _	| j	dkrZd| _	d| _
dS )zd
        Switch outbound data cipher.
        :param etm: Set encrypt-then-mac from OpenSSH
        r         FN)r8   r:   r4   r;   r6   r=   r.   r/   rC   r+   r*   )rO   block_engine
block_size
mac_enginemac_sizemac_keyZsdctretmr   r   r   set_outbound_cipher   s    
zPacketizer.set_outbound_cipherc                 C   sd   || _ || _|| _|| _|| _d| _d| _d| _d| _|| _	|  j
dO  _
| j
dkr`d| _
d| _dS )zc
        Switch inbound data cipher.
        :param etm: Set encrypt-then-mac from OpenSSH
        r   r#   rW   FN)r9   r5   r<   r7   r>   r0   r1   r2   r3   rD   r+   r*   )rO   rX   rY   rZ   r[   r\   r]   r   r   r   set_inbound_cipher   s    
zPacketizer.set_inbound_cipherc                 C   s
   || _ d S r   )r?   rO   Z
compressorr   r   r   set_outbound_compressor   s    z"Packetizer.set_outbound_compressorc                 C   s
   || _ d S r   )r@   r`   r   r   r   set_inbound_compressor   s    z!Packetizer.set_inbound_compressorc                 C   s   d| _ | j  d S NT)r(   r&   closerR   r   r   r   rd      s    zPacketizer.closec                 C   s
   || _ d S r   r)   )rO   hexdumpr   r   r   set_hexdump   s    zPacketizer.set_hexdumpc                 C   s   | j S r   re   rR   r   r   r   get_hexdump   s    zPacketizer.get_hexdumpc                 C   s   | j S r   )r7   rR   r   r   r   get_mac_size_in   s    zPacketizer.get_mac_size_inc                 C   s   | j S r   )r6   rR   r   r   r   get_mac_size_out   s    zPacketizer.get_mac_size_outc                 C   s   | j S )z
        Returns ``True`` if a new set of keys needs to be negotiated.  This
        will be triggered during a packet read or write, so it should be
        checked after every read or write, or at least after every few.
        r*   rR   r   r   r   
need_rekey   s    zPacketizer.need_rekeyc                 C   s   || _ || _t | _dS )z
        Turn on/off the callback keepalive.  If ``interval`` seconds pass with
        no data read from or written to the socket, the callback will be
        executed and the timer will be reset.
        N)rH   rK   rI   rJ   )rO   intervalcallbackr   r   r   set_keepalive   s    zPacketizer.set_keepalivec                 C   s
   d| _ d S rc   )rN   rR   r   r   r   
read_timer   s    zPacketizer.read_timerc                 C   s(   | j s$tt|| j| _ | j   dS )z
        Tells `Packetizer` that the handshake process started.
        Starts a book keeping timer that can signal a timeout in the
        handshake process.

        :param float timeout: amount of seconds to wait before timing out
        N)rL   rE   Timerfloatrp   start)rO   timeoutr   r   r   start_handshake   s    zPacketizer.start_handshakec                 C   s   | j s
dS | jrdS | jS )aR  
        Checks if the handshake has timed out.

        If `start_handshake` wasn't called before the call to this function,
        the return value will always be `False`. If the handshake completed
        before a timeout was reached, the return value will be `False`

        :return: handshake time out status, as a `bool`
        F)rL   rM   rN   rR   r   r   r   handshake_timed_out   s
    
zPacketizer.handshake_timed_outc                 C   s    | j r| j   d| _d| _dS )zF
        Tells `Packetizer` that the handshake has completed.
        FTN)rL   cancelrN   rM   rR   r   r   r   complete_handshake  s    
zPacketizer.complete_handshakec              
   C   s8  t  }t| jdkr>| jd| }| j|d | _|t|8 }|dkr4d}|  rZt z6| j|}t|dkrzt ||7 }|t|8 }W nd tjk
r   d}Y nL tj	k
r } z,t
|}|tjkrd}n| jrt n W 5 d}~X Y nX |r>| jrt |r*t|dkr*| jr*t |   q>|S )a&  
        Read as close to N bytes as possible, blocking as long as necessary.

        :param int n: number of bytes to read
        :return: the data read, as a `str`

        :raises:
            ``EOFError`` -- if the socket was closed before all the bytes could
            be read
        r   NFT)r,   r   r-   rv   EOFErrorr&   recvrP   rt   errorr!   errnoEAGAINr(   r*   r   _check_keepalive)rO   ncheck_rekeyoutZgot_timeoutxr   r    r   r   r   read_all  s>    


zPacketizer.read_allc              
   C   s  t   | _d}t|dkrd}z| j|}W n tjk
rJ   d}Y nj tjk
r } z t|}|t	j
krtd}nd}W 5 d }~X Y n, tk
r    Y n tk
r   d}Y nX |rd}| jrd}n|dkr|dkrd}|d7 }|dk rt |t|krq||d  }qd S )Nr   FT
   rV   )rI   rJ   r   r&   sendrP   rt   r{   r!   r|   r}   r   	Exceptionr(   ry   )rO   r   Z#iteration_with_zero_as_return_valueZretry_writer   r   r    r   r   r   	write_allG  s<    


zPacketizer.write_allc                 C   sr   | j }t|kr|| |7 }q|t}||d d | _ |d| }t|dkrj|d tkrj|dd }t|S )z
        Read a line from the socket.  We assume no data is pending after the
        line, so it's okay to attempt large reads.
        rV   Nr   r   )r-   r   _read_timeoutindexr   r   r   )rO   rt   bufr   r   r   r   readlineo  s    
zPacketizer.readlinec                 C   s  |  }t|d }|tkr&t| }n
d|}t|}| j  zp| jdk	rZ| |}| 	|}| j
r| td|| | tt|d | jdk	r| jr|dd | j|dd  }q| j|}n|}| jdk	r td| j}|| jr|n| }|t| j|| jd| j 7 }| jd t@ | _| | |  jt|7  _|  jd7  _| j| jkpr| j| jk}	|	r| jsd	}
| t|
| j| j d| _ d| _!| "  W 5 | j  X dS )
zR
        Write a block of data using the current cipher, as an SSH block.
        r   ${:x}NzWrite packet <{}>, length {}zOUT:    >IrV   z(Rekeying (hit {} packets, {} bytes sent))#Zasbytesr
   r   formatr   rG   acquirereleaser?   _build_packetr)   _logr   r   format_binaryr8   rC   updatestructpackrA   r   r=   r;   r6   r   r   r.   r/   REKEY_PACKETSREKEY_BYTESr*   r2   r3   _trigger_rekey)rO   datacmdcmd_nameZorig_lenpacketr   packedpayloadZsent_too_muchmsgr   r   r   send_message~  sj    








  

 zPacketizer.send_messagec                 C   s  | j | jdd}| jrtd|dd d }|| j d }|dd | j |dd }| j | jdd}td| j|| }t| j	|| j
d| j }t||std	|}| jdk	r| j|}| jr| tt|d
 | jr|}ntd|dd d }|dd }|t| | j dkr,td|  || j t| }	|	d|t|  }|	|t| d }
| jdk	r| j|}|| }| jr| tt|d
 | jdkr| js|
d| j }td| j|| }t| j	|| j
d| j }t||std	t|d }|d||  }| jrF| td|| | jdk	r\| |}t|dd }| j|_| jd t@ | _|| j d }|  j|7  _|  jd7  _| jr|  j|7  _|  jd7  _| j| j ks| j| j!krDtdnL| j| j"ks| j| j#krDd}| t|| j| j d| _d| _| $  t|d }|t%krdt%| }n
d|}| jr| td|t| ||fS )z
        Only one thread should ever be in this function (no other locking is
        done).

        :raises: `.SSHException` -- if the packet is mangled
        :raises: `.NeedRekeyException` -- if the transport should rekey
        T)r   r   Nr   r   Fz>IIzMismatched MACzIN: zInvalid packet blockingrV   z"Got payload ({} bytes, {} padding)z+Remote transport is ignoring rekey requestsz,Rekeying (hit {} packets, {} bytes received)r   zRead packet <{}>, length {})&r   r5   rD   r   unpackr7   r   rB   r   r>   r<   r   Zconstant_time_bytes_eqr   r9   r   r)   r   r   r   r   r
   r   r@   r   Zseqnor   r0   r1   r*   r2   r3   REKEY_PACKETS_OVERFLOW_MAXREKEY_BYTES_OVERFLOW_MAXr   r   r   r   )rO   headerZpacket_size	remainingr   macZmac_payloadZmy_macleftoverr   Zpost_packetpaddingr   r   Zraw_packet_sizeerrr   r   r   r   r   read_message  s      
   





zPacketizer.read_messagec                 C   sH   | j d krd S tt|tr6|D ]}| j || q n| j || d S r   )r'   
issubclassr   listrT   )rO   levelr   mr   r   r   r   ?  s    
zPacketizer._logc                 C   s@   | j r| jr| jrd S t }|| j| j  kr<|   || _d S r   )rH   r8   r*   rI   rJ   rK   )rO   nowr   r   r   r~   H  s    zPacketizer._check_keepalivec                 C   st   t   }z&| jd}t|dkr(t W qpW n tjk
rD   Y nX | jrRt t   }|| |krt q|S )N   r   )rI   r&   rz   r   ry   rP   rt   r(   )rO   rt   rs   r   r   r   r   r   r   U  s    
zPacketizer._read_timeoutc                 C   s~   | j }| jrdnd}d| t|| |  }tdt|| d |}||7 }| js^| jd krl|t| 7 }n|t	|7 }|S )Nr   r%   rW   z>IBrV   )
r4   rC   r   r   r   r:   r8   r	   osurandom)rO   r   ZbsizeZaddlenr   r   r   r   r   r   f  s    zPacketizer._build_packetc                 C   s
   d| _ d S rc   rk   rR   r   r   r   r   x  s    zPacketizer._trigger_rekeyN)FF)F)F)&r   r   r   r   powr   r   r   r   rQ   propertyrS   rU   r^   r_   ra   rb   rd   rg   rh   ri   rj   rl   ro   rp   ru   rv   rx   r   r   r   r   r   r   r~   r   r   r   r   r   r   r   r"   A   sL   



0
  
% 

	
0(? 	r"   )r   r|   r   rP   r   rE   rI   hmacr   Zparamikor   Zparamiko.commonr   r   r   r   r   r	   r
   Zparamiko.utilr   Zparamiko.ssh_exceptionr   r   Zparamiko.messager   r   r   r   r!   r"   r   r   r   r   <module>   s    $	