o
    ç÷¡gú^  ã                   @   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ÚmessageÚdigest_class© r   ú:/usr/local/lib/python3.10/dist-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u rt| jƒdkr| jd }|S ©Nr   )ÚtypeÚargsÚtupleÚlen)ÚeÚargr   r   r   Ú	first_arg:   s   
r#   c                   @   sH  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				dDdd„Z			dEd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dFd.d/„Zd0d1„ Zd2d3„ Z d4d5„ Z!d6d7„ Z"d8d9„ Z#d:d;„ Z$d<d=„ Z%d>d?„ Z&d@dA„ Z'dBdC„ Z(dS )GÚ
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| _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Ú_Packetizer__aead_outÚ_Packetizer__aead_inÚ_Packetizer__iv_outÚ_Packetizer__iv_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   sT   


zPacketizer.__init__c                 C   ó   | j S r   )r*   ©rV   r   r   r   Úclosedˆ   s   zPacketizer.closedc                 C   ó
   d| _ d S r   )rD   rZ   r   r   r   Úreset_seqno_outŒ   ó   
zPacketizer.reset_seqno_outc                 C   r\   r   )rE   rZ   r   r   r   Úreset_seqno_in�   r^   zPacketizer.reset_seqno_inc                 C   s
   || _ dS )z?
        Set the Python log object to use for logging.
        N)r)   )rV   Úlogr   r   r   Úset_log’   s   
zPacketizer.set_logFNc
           
      C   sn   || _ || _|| _|| _|| _|| _d| _d| _|| _|| _	|	| _
|  jdO  _| jdkr5d| _d| _dS dS )zd
        Switch outbound data cipher.
        :param etm: Set encrypt-then-mac from OpenSSH
        r   é   é   FN)r;   r=   r7   r>   r9   r@   r1   r2   rF   rH   rJ   r-   r,   )
rV   Úblock_engineÚ
block_sizeÚ
mac_engineÚmac_sizeÚmac_keyÚsdctrÚetmÚaeadÚiv_outr   r   r   Úset_outbound_cipher˜   s    

þzPacketizer.set_outbound_cipherc	           	      C   st   || _ || _|| _|| _|| _d| _d| _d| _d| _|| _	|| _
|| _|  jdO  _| jdkr8d| _d| _dS dS )zc
        Switch inbound data cipher.
        :param etm: Set encrypt-then-mac from OpenSSH
        r   r%   rc   FN)r<   r8   r?   r:   rA   r3   r4   r5   r6   rG   rI   rK   r-   r,   )	rV   rd   re   rf   rg   rh   rj   rk   Úiv_inr   r   r   Úset_inbound_cipherº   s"   

þzPacketizer.set_inbound_cipherc                 C   ó
   || _ d S r   )rB   ©rV   Ú
compressorr   r   r   Úset_outbound_compressorÜ   r^   z"Packetizer.set_outbound_compressorc                 C   rp   r   )rC   rq   r   r   r   Úset_inbound_compressorß   r^   z!Packetizer.set_inbound_compressorc                 C   s   d| _ | j ¡  d S ©NT)r*   r(   ÚcloserZ   r   r   r   rv   â   s   zPacketizer.closec                 C   rp   r   ©r+   )rV   Úhexdumpr   r   r   Úset_hexdumpæ   r^   zPacketizer.set_hexdumpc                 C   rY   r   rw   rZ   r   r   r   Úget_hexdumpé   ó   zPacketizer.get_hexdumpc                 C   rY   r   )r:   rZ   r   r   r   Úget_mac_size_inì   r{   zPacketizer.get_mac_size_inc                 C   rY   r   )r9   rZ   r   r   r   Úget_mac_size_outï   r{   zPacketizer.get_mac_size_outc                 C   rY   )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,   rZ   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)rO   rR   rP   rQ   )rV   ÚintervalÚcallbackr   r   r   Úset_keepaliveú   s   zPacketizer.set_keepalivec                 C   r\   ru   )rU   rZ   r   r   r   Ú
read_timer  r^   zPacketizer.read_timerc                 C   s,   | j st t|ƒ| j¡| _ | j  ¡  dS 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)rS   rL   ÚTimerÚfloatrƒ   Ústart)rV   Ú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)rS   rT   rU   rZ   r   r   r   Úhandshake_timed_out  s
   
zPacketizer.handshake_timed_outc                 C   s$   | j r| j  ¡  d| _d| _dS dS )zF
        Tells `Packetizer` that the handshake has completed.
        FTN)rS   ÚcancelrU   rT   rZ   r   r   r   Úcomplete_handshake#  s
   

ýzPacketizer.complete_handshakec              
   C   s2  t ƒ }t| jƒdkr| jd|… }| j|d… | _|t|ƒ8 }|dkr—d}|  ¡ r,tƒ ‚z| j |¡}t|ƒdkr<tƒ ‚||7 }|t|ƒ8 }W n1 tjyS   d}Y n& tj	yx } zt
|ƒ}|tjkrgd}n| jrmtƒ ‚‚ W Y d}~nd}~ww |r“| jr�tƒ ‚|r�t|ƒdkr�| jr�tƒ ‚|  ¡  |dks#|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(   ÚrecvrW   r‡   Úerrorr#   ÚerrnoÚEAGAINr*   r,   r   Ú_check_keepalive)rV   ÚnÚcheck_rekeyÚoutÚgot_timeoutÚxr!   r"   r   r   r   Úread_all,  sF   
ü€úäzPacketizer.read_allc              
   C   s  t   ¡ | _d}t|ƒdkr‰d}z| j |¡}W n= tjy#   d}Y n2 tjyC } zt|ƒ}|t	j
kr7d}nd}W Y d }~nd }~w tyJ   ‚  tyT   d}Y nw |r_d}| jr^d}n|dkri|dkrid}|d7 }|dk rttƒ ‚|t|ƒkr}	 d S ||d … }t|ƒdksd S )Nr   FTéÿÿÿÿé
   rb   )rP   rQ   r    r(   ÚsendrW   r‡   rŽ   r#   r�   r�   r   Ú	Exceptionr*   rŒ   )rV   r”   Ú#iteration_with_zero_as_return_valueÚretry_writer’   r!   r"   r   r   r   Ú	write_all\  sF   

€þ€ÿÞ#zPacketizer.write_allc                 C   sx   | j }t|vr||  |¡7 }t|vs| t¡}||d d… | _ |d|… }t|ƒdkr8|d tkr8|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.
        rb   Nr   r˜   )r/   r   Ú_read_timeoutÚindexr    r   r   )rV   r‡   Úbufr’   r   r   r   Úreadline„  s   ÿ
zPacketizer.readlinec                 C   s@   |dd … }t  |d¡}|d }| dd¡}|dd… | }|S )Né   Úbigrb   r'   r   )ÚintÚ
from_bytesÚto_bytes)rV   ÚivÚiv_counter_bÚ
iv_counterÚinc_iv_counterÚinc_iv_counter_bÚnew_ivr   r   r   Ú_inc_iv_counter“  s   zPacketizer._inc_iv_counterc                 C   sL  |  ¡ }t|d ƒ}|tv rt| }nd |¡}t|ƒ}| j ¡  zþ| jdur,|  |¡}|  |¡}| j	rH|  
td ||¡¡ |  
tt |d¡¡ | jdurŠ| jra|dd… | j |dd… ¡ }n+| jrƒ|dd… | j | j|dd… |dd… ¡ }|  | j¡| _n	| j |¡}n|}| jdur³| js³t d| j¡}|| jr¡|n| }|t| j|| jƒd| j… 7 }| jd t@ }	|	dkrÅ| jsÅtd	ƒ‚|	| _|  |¡ |  j t|ƒ7  _ |  j!d7  _!| j!| j"kpè| j | j#k}
|
�r| j$�sd
}|  
t| | j!| j ¡¡ d| _%d| _&|  '¡  W | j (¡  dS W | j (¡  dS W | j (¡  dS | j (¡  w )zR
        Write a block of data using the current cipher, as an SSH block.
        r   ú${:x}NzWrite packet <{}>, length {}zOUT: r£   ú>Irb   ú/Sequence number rolled over during initial kex!z(Rekeying (hit {} packets, {} bytes sent)))Úasbytesr
   r   Úformatr    rN   ÚacquirerB   Ú_build_packetr+   Ú_logr   r   Úformat_binaryr;   rF   ÚupdaterH   ÚencryptrJ   r®   ÚstructÚpackrD   r   r@   r>   r9   r   r0   r   rž   r1   r2   ÚREKEY_PACKETSÚREKEY_BYTESr,   r5   r6   Ú_trigger_rekeyÚrelease)rV   ÚdataÚcmdÚcmd_nameÚorig_lenÚpacketr”   ÚpackedÚpayloadÚnext_seqÚsent_too_muchÚmsgr   r   r   Úsend_messagež  s|   






þ

ÿÿ
ÿþÿ

þÿ
ö
ö
zPacketizer.send_messagec                 C   s>  | j | jdd�}| jrVt d|dd… ¡d }|| j d }|dd… | j |dd� }| j | jdd�}t d| j|¡| }t| j	|| j
ƒd| j… }t ||¡sTtd	ƒ‚|}| jr’t d|dd… ¡d }|dd… }|| j d | j }|dd… | j |dd� }| j | j||¡}|  | j¡| _| jdur | js | j |¡}| jr­|  tt |d
¡¡ | js³| jr¶|}nQt d|dd… ¡d }|dd… }	|t|	ƒ | j dkr×tdƒ‚|   || j t|	ƒ ¡}
|
d|t|	ƒ … }|
|t|	ƒ d… }| jdu�r| j |¡}|	| }| j�r|  tt |d
¡¡ | jdk�rL| j�sL| j�sL|d| j… }t d| j|¡| }t| j	|| j
ƒd| j… }t ||¡�sLtd	ƒ‚t|d ƒ}|d|| … }| j�rh|  td ||¡¡ | jdu�rs|  |¡}t|dd… ƒ}| j|_| jd t@ }|dk�r“| j�s“tdƒ‚|| _|| j d }|  j |7  _ |  j!d7  _!| j"�rÐ|  j#|7  _#|  j$d7  _$| j$| j%k�sË| j#| j&k�rÏtdƒ‚n&| j!| j'k�sÞ| j | j(k�röd}|  t| | j!| j ¡¡ d| _#d| _$|  )¡  t|d ƒ}|t*v �rt*| }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 blockingrb   z"Got payload ({} bytes, {} padding)r±   z+Remote transport is ignoring rekey requestsz,Rekeying (hit {} packets, {} bytes received)r¯   zRead packet <{}>, length {})+r—   r8   rG   rº   Úunpackr:   r»   rE   r   rA   r?   r   Úconstant_time_bytes_eqr   rI   r<   ÚdecryptrK   r®   r¸   r+   r¶   r   r·   r    r
   r³   rC   r   Úseqnor   r0   r3   r4   r,   r5   r6   ÚREKEY_PACKETS_OVERFLOW_MAXÚREKEY_BYTES_OVERFLOW_MAXr¼   r½   r¾   r   )rV   ÚheaderÚpacket_sizeÚ	remainingrÄ   ÚmacÚmac_payloadÚmy_macÚaadÚleftoverr¡   Úpost_packetÚpaddingrÆ   rÉ   rÇ   Úraw_packet_sizeÚerrrÁ   rÂ   r   r   r   Úread_messageè  sà   ÿÿ
ÿþÿÿÿÿ
ÿþÿþ
ÿÿÿþþ


þzPacketizer.read_messagec                 C   sJ   | j d u rd S tt|ƒtƒr|D ]	}| j  ||¡ qd S | j  ||¡ d S r   )r)   Ú
issubclassr   Úlistr`   )rV   ÚlevelrÉ   Úmr   r   r   r¶   }  s   
ÿzPacketizer._logc                 C   sD   | j r	| jr	| jrd S t ¡ }|| j| j  kr |  ¡  || _d S d S r   )rO   r;   r,   rP   rQ   rR   )rV   Únowr   r   r   r‘   †  s   ÿþý
þzPacketizer._check_keepalivec                 C   sn   t   ¡ }	 z| j d¡}t|ƒdkrtƒ ‚W |S  tjy!   Y nw | jr(tƒ ‚t   ¡ }|| |kr6t ¡ ‚q)NTé€   r   )rP   r(   r�   r    rŒ   rW   r‡   r*   )rV   r‡   r†   r–   râ   r   r   r   rŸ   “  s"   ùÿôzPacketizer._read_timeoutc                 C   s†   | j }| js	| jrdnd}d| t|ƒ| |  }t dt|ƒ| d |¡}||7 }| js2| jd u r:|t| 7 }|S |t	 
|¡7 }|S )Nr£   r'   rc   z>IBrb   )r7   rF   rH   r    rº   r»   r=   r;   r	   ÚosÚurandom)rV   rÆ   ÚbsizeÚaddlenrÚ   rÄ   r   r   r   rµ   ¤  s   ÿzPacketizer._build_packetc                 C   r\   ru   r~   rZ   r   r   r   r¾   ¶  s   
zPacketizer._trigger_rekey)FFFN)FFN)F))r   r   r   r   Úpowr¼   r½   rÏ   rÐ   rX   Úpropertyr[   r]   r_   ra   rm   ro   rs   rt   rv   ry   rz   r|   r}   r   r‚   rƒ   rˆ   r‰   r‹   r—   rž   r¢   r®   rÊ   rÝ   r¶   r‘   rŸ   rµ   r¾   r   r   r   r   r$   A   s\    



7

ö)
÷"

	0(J 	r$   )r   r�   rä   rW   rº   rL   rP   Ú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"   $	