U
    weV                     @   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   n/mounts/lovelace/software/anaconda3/envs/qiime2-amplicon-2024.2/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                   @   s2  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 Zdd ZdBddZdCd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dDd-d.Zd/d0 Zd1d2 Z d3d4 Z!d5d6 Z"d7d8 Z#d9d: Z$d;d< Z%d=d> Z&d?d@ Z'dAS )E
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 | _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_initial_kex_done_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   sL    

zPacketizer.__init__c                 C   s   | j S r   )r)   rQ   r   r   r   closed   s    zPacketizer.closedc                 C   s
   d| _ d S r   )rC   rT   r   r   r   reset_seqno_out   s    zPacketizer.reset_seqno_outc                 C   s
   d| _ d S r   )rD   rT   r   r   r   reset_seqno_in   s    zPacketizer.reset_seqno_inc                 C   s
   || _ dS )z?
        Set the Python log object to use for logging.
        N)r(   )rQ   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)r:   r<   r6   r=   r8   r?   r0   r1   rE   r,   r+   )rQ   block_engine
block_size
mac_enginemac_sizemac_key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$   r[   FN)r;   r7   r>   r9   r@   r2   r3   r4   r5   rF   r,   r+   )rQ   r\   r]   r^   r_   r`   rb   r   r   r   set_inbound_cipher   s    
zPacketizer.set_inbound_cipherc                 C   s
   || _ d S r   )rA   rQ   Z
compressorr   r   r   set_outbound_compressor   s    z"Packetizer.set_outbound_compressorc                 C   s
   || _ d S r   )rB   re   r   r   r   set_inbound_compressor   s    z!Packetizer.set_inbound_compressorc                 C   s   d| _ | j  d S NT)r)   r'   closerT   r   r   r   ri      s    zPacketizer.closec                 C   s
   || _ d S r   r*   )rQ   hexdumpr   r   r   set_hexdump   s    zPacketizer.set_hexdumpc                 C   s   | j S r   rj   rT   r   r   r   get_hexdump   s    zPacketizer.get_hexdumpc                 C   s   | j S r   )r9   rT   r   r   r   get_mac_size_in   s    zPacketizer.get_mac_size_inc                 C   s   | j S r   )r8   rT   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+   rT   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)rJ   rM   rK   rL   )rQ   intervalcallbackr   r   r   set_keepalive   s    zPacketizer.set_keepalivec                 C   s
   d| _ d S rh   )rP   rT   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)rN   rG   Timerfloatru   start)rQ   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)rN   rO   rP   rT   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)rN   cancelrP   rO   rT   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.   r{   EOFErrorr'   recvrR   ry   errorr"   errnoEAGAINr)   r+   r   _check_keepalive)rQ   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
   rZ   )rK   rL   r   r'   sendrR   ry   r   r"   r   r   r   	Exceptionr)   r~   )rQ   r   Z#iteration_with_zero_as_return_valueZretry_writer   r    r!   r   r   r   	write_allN  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.
        rZ   Nr   r   )r.   r   _read_timeoutindexr   r   r   )rQ   ry   bufr   r   r   r   readlinev  s    
zPacketizer.readlinec                 C   s  |  }t|d }|tkr&t| }n
d|}t|}| j  z| 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@ }	|	dkrH| jsHtd	|	| _| | |  jt|7  _|  jd7  _| j| jkp| 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:    >IrZ   /Sequence number rolled over during initial kex!z(Rekeying (hit {} packets, {} bytes sent))%asbytesr
   r   formatr   rI   acquirereleaserA   _build_packetr*   _logr   r   format_binaryr:   rE   updatestructpackrC   r   r?   r=   r8   r   r/   r   r   r0   r1   REKEY_PACKETSREKEY_BYTESr+   r4   r5   _trigger_rekey)rQ   datacmdcmd_nameorig_lenpacketr   packedpayloadnext_seqZsent_too_muchmsgr   r   r   send_message  sp    








  

 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@ }|dkr| jstd|| _|| j d }|  j|7  _|  jd7  _| jr|  j|7  _|  j d7  _ | j | j!ks| j| j"krbtdnL| j| j#ks2| j| j$krbd}| t|| j| j d| _d| _ | %  t|d }|t&krt&| }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 blockingrZ   z"Got payload ({} bytes, {} padding)r   z+Remote transport is ignoring rekey requestsz,Rekeying (hit {} packets, {} bytes received)r   zRead packet <{}>, length {})'r   r7   rF   r   unpackr9   r   rD   r   r@   r>   r   constant_time_bytes_eqr   r;   r   r*   r   r   r   r   r
   r   rB   r   seqnor   r/   r2   r3   r+   r4   r5   REKEY_PACKETS_OVERFLOW_MAXREKEY_BYTES_OVERFLOW_MAXr   r   r   r   )rQ   headerZpacket_size	remainingr   macZmac_payloadZmy_macleftoverr   Zpost_packetpaddingr   r   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   listrX   )rQ   levelr   mr   r   r   r   N  s    
zPacketizer._logc                 C   s@   | j r| jr| jrd S t }|| j| j  kr<|   || _d S r   )rJ   r:   r+   rK   rL   rM   )rQ   nowr   r   r   r   W  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   )rK   r'   r   r   r~   rR   ry   r)   )rQ   ry   rx   r   r   r   r   r   r   d  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&   r[   z>IBrZ   )
r6   rE   r   r   r   r<   r:   r	   osurandom)rQ   r   ZbsizeZaddlenr   r   r   r   r   r   u  s    zPacketizer._build_packetc                 C   s
   d| _ d S rh   rp   rT   r   r   r   r     s    zPacketizer._trigger_rekeyN)FF)F)F)(r   r   r   r   powr   r   r   r   rS   propertyrU   rV   rW   rY   rc   rd   rf   rg   ri   rl   rm   rn   ro   rq   rt   ru   rz   r{   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r#   A   sP   



1
  
% 

	
0(B 	r#   )r   r   r   rR   r   rG   rK   hmacr   paramikor   paramiko.commonr   r   r   r   r   r	   r
   paramiko.utilr   paramiko.ssh_exceptionr   r   paramiko.messager   r   r   r   r"   r#   r   r   r   r   <module>   s    $	