
    hM+                         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	 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  G d de          ZdS )zP
The _TLSAutomaton class provides methods common to both TLS client and server.
    N)	Automaton)conf)log_interactive)Raw)	_tls_type)CertPrivKey)TLS)SSLv2)TLS13c                   `     e Zd ZdZ fdZd fd	ZddZddZd	 Zdd
Z	d Z
d ZddZ xZS )_TLSAutomatona  
    SSLv3 and TLS 1.0-1.2 typically need a 2-RTT handshake:

    Client        Server
      | --------->>> |    C1 - ClientHello
      | <<<--------- |    S1 - ServerHello
      | <<<--------- |    S1 - Certificate
      | <<<--------- |    S1 - ServerKeyExchange
      | <<<--------- |    S1 - ServerHelloDone
      | --------->>> |    C2 - ClientKeyExchange
      | --------->>> |    C2 - ChangeCipherSpec
      | --------->>> |    C2 - Finished [encrypted]
      | <<<--------- |    S2 - ChangeCipherSpec
      | <<<--------- |    S2 - Finished [encrypted]

    We call these successive groups of messages:
    ClientFlight1, ServerFlight1, ClientFlight2 and ServerFlight2.

    With TLS 1.3, the handshake require only 1-RTT:

    Client        Server
      | --------->>> |    C1 - ClientHello
      | <<<--------- |    S1 - ServerHello
      | <<<--------- |    S1 - Certificate [encrypted]
      | <<<--------- |    S1 - CertificateVerify [encrypted]
      | <<<--------- |    S1 - Finished [encrypted]
      | --------->>> |    C2 - Finished [encrypted]

    We want to send our messages from the same flight all at once through the
    socket. This is achieved by managing a list of records in 'buffer_out'.
    We may put several messages (i.e. what RFC 5246 calls the record fragments)
    in the same record when possible, but we may need several records for the
    same flight, as with ClientFlight2.

    However, note that the flights from the opposite side may be spread wildly
    across TLS records and TCP packets. This is why we use a 'get_next_msg'
    method for feeding a list of received messages, 'buffer_in'. Raw data
    which has not yet been interpreted as a TLS record is kept in 'remain_in'.
    c                 `    d |d<   d |d<    t          t          |           j        |i | d S )Nc                      d S N argskwargss     ^/mounts/lovelace/software/anaconda3/lib/python3.11/site-packages/scapy/layers/tls/automaton.py<lambda>z(_TLSAutomaton.__init__.<locals>.<lambda>D   s    t     llc                      d S r   r   r   s     r   r   z(_TLSAutomaton.__init__.<locals>.<lambda>E   s    T r   recvsock)superr   __init__)selfr   r   	__class__s      r   r   z_TLSAutomaton.__init__C   sD    33t99z+mT""+T<V<<<<<r   Nc                 L   |                     dd          | _         t          t          |           j        di | d | _        d| _        g | _        g | _        d | _	        d | _
        |rt          |          | _        nd | _        |rt          |          | _        d S d | _        d S )NverboseTr   r   )popr!   r   r   
parse_argssocket	remain_in	buffer_in
buffer_outcur_sessioncur_pktr   mycertr	   mykey)r   r*   r+   kargsr   s       r   r#   z_TLSAutomaton.parse_argsH   s    yyD11-mT""-66666 	v,,DKKDK 	 DJJJDJJJr      c                 &	   | j         rdS d}d}d}|rS|st          | j                  |k     r8|sL|dk    rFt          | j                  dk    r.t          j        d| j        dd                   d         dz   }d}n|dk    rvt          | j                  dk    r^t          j        d	| j        dd                   \  }}|t
          v r	|dk    rd}nrd}d}|d
z  rd|dz  dz  z   |z   }nZd|dz  dz  z   |z   }nK|sI|dk    rCt          | j                  dk    r+t          j        d| j        dd                   d         dz   }|t          | j                  k    rn	d}	 t          j        | j        gg g |          \  }	}
}
|	s|dz  }nZ|	d                             |t          | j                  z
            }|s| 	                    d           d}n| xj        |z  c_        |r| 
                                nN# t          $ rA}t          |t          j                  s| 	                    d|z             |dz  }Y d}~nd}~ww xY w|r|t          | j                  |k     8t          | j                  dk     st          | j                  |k    rdS |dk    r]| j        j        dk    s| j        j        dk    r=t#          | j        | j                  }d| _        | xj         |j        j        z  c_         nt)          | j        | j                  }|j        | _        d| _        t          |t,                    r|j        st/          d          |_        | j        j        | j        j        dk     r| xj         |j        z  c_         nEt          |t"                    r| xj         |j        j        z  c_         n| xj         |j        z  c_         |j        rt          |j        t.                    r"| xj        |j        j        z  c_        |j        }nut          |j        t(                    rT|j        }| j        j        | j        j        dk     r| xj         |j        z  c_         n"| xj         |j        j        z  c_         n|j        }|j        dS dS )a}  
        The purpose of the function is to make next message(s) available in
        self.buffer_in. If the list is not empty, nothing is done. If not, in
        order to fill it, the function uses the data already available in
        self.remain_in from a previous call and waits till there are enough to
        dissect a TLS packet. Once dissected, the content of the TLS packet
        (carried messages, or 'fragments') is appended to self.buffer_in.

        We have to grab enough data to dissect a TLS packet. We start by
        reading the first 2 bytes. Unless we get anything different from
        \x14\x03, \x15\x03, \x16\x03 or \x17\x03 (which might indicate
        an SSLv2 record, whose first 2 bytes encode the length), we retrieve
        3 more bytes in order to get the length of the TLS record, and
        finally we can retrieve the remaining of the record.
        NFTr-      z!H   r   BB         ?      zPeer socket closed !z&Could not join host (%s) ! Retrying...     tls_sessionr    )r&   lenr%   structunpackr   selectr$   recvvprintSOCKET_CLOSED	Exception
isinstancetimeoutr(   advertised_tls_versiontls_versionr   innermsgr
   r:   r   r   payloadload)r   socket_timeoutretryis_sslv2_msgstill_getting_lengrablenbyte0byte1finaltmp_dataexps                 r   get_next_msgz_TLSAutomaton.get_next_msg`   s     > 	F  ,	/* ,	/c$..A.AG.K.K JGqLLS5H5HA5M5M -dnQqS.ABB1EI$)!!A#dn"5"5":":%}T4>"1"3EFFuY&&UaZZ  GG $(L(-%t| H"'EDLQ+>"?%"G"'EDLQ+>"?%"G! Jglls4>7J7Ja7O7O -dnQqS.ABB1EI#dn----E/"M4;-R*8: :	Q 	/QJEEq6;;wT^1D1D'DEED /$:;;; $$.  /,,.../    !"fn55 OKK H2 MNNN
M  ,	/* ,	/c$..A.AG.K.K\ t~""c$.&9&9W&D&DFTMM!8FBB!-77dn$2BCCCA DNNNagk)NNNDN0@AAAA }D DN!U##  AE  B+3+f44!%'a'' ,NNagk1NNN NNae+NNi 	!)S)) !).0IAIs++ I#/7#/&88NNae+NNNNNagk1NNNI i 	 	 	 	 	s    BG: :
I7I  ITc                     |r|                                   | j        rt          | j        d         |          sdS | j        d         | _        | j        dd         | _         |            )z
        If the next message to be processed has type 'pkt_cls', raise 'state'.
        If there is no message waiting to be processed, we try to get one with
        the default 'get_next_msg' parameters.
        r   Nr6   )rY   r&   rD   r)   )r   pkt_clsstaterY   s       r   raise_on_packetz_TLSAutomaton.raise_on_packet   sq      	  	t~a0'::	F~a(+eggr   c                 N    t          fd| j        j        D                       S )z
        Return True if the pkt_cls was present during the handshake.
        This is used to detect whether Certificates were requested, etc.
        c              3   8   K   | ]}t          |          V  d S r   )rD   ).0mr[   s     r   	<genexpr>z-_TLSAutomaton.in_handshake.<locals>.<genexpr>   sA       
 
 q'""
 
 
 
 
 
r   )anyr(   handshake_messages_parsed)r   r[   s    `r   in_handshakez_TLSAutomaton.in_handshake   sC    
  
 
 
 
%?
 
 
 
 
 	
r   c                    |+|)|'| j         j        p| j         j        }|dv rd}n|dk    rd}|r/| j                            t          | j                              dS |r/| j                            t          | j                              dS |r0| j                            t          d| j                              dS | j                            t          | j                              dS )zW
        Add a new TLS or SSLv2 or TLS 1.3 record to the packets buffered out.
        N)i   r-   Tr8   r9   zTLS 1.2)versionr:   )r(   rG   rF   r'   appendr   r   r
   )r   is_sslv2is_tls13is_tls12vs        r   
add_recordz_TLSAutomaton.add_record   s3     0X5E!- 9!8 $$$f 
	FO""5T5E#F#F#FGGGGG 	FO""5T5E#F#F#FGGGGG  	FO""3y373C$E $E $E F F F F F O""343C#D#D#DEEEEEr   c                 "   | j         s|                                  | j         d         }t          |t                    r,| j         d         j        j                            |           dS | j         d         j                            |           dS )z
        Add a TLS message (e.g. TLSClientHello or TLSApplicationData)
        inside the latest record to be sent through the socket.
        We believe a good automaton should not use the first test.
        N)r'   rm   rD   r   rH   rI   rh   )r   pktrs      r   add_msgz_TLSAutomaton.add_msg   s      	OOOBa 	0OB%)0055555OB#**3/////r   c                     d                     d | j        D                       }| j                            |           g | _        dS )zO
        Send all buffered records and update the session accordingly.
        r   c              3   >   K   | ]}|                                 V  d S r   )raw_stateful)r`   rX   s     r   rb   z._TLSAutomaton.flush_records.<locals>.<genexpr>  s,      ??!Q^^%%??????r   N)joinr'   r$   sendr   ss     r   flush_recordsz_TLSAutomaton.flush_records  sG     HH??t?????r   r;   c                     | j         r7t          j        rt          j        d|           d S t          d|z             d S d S )Nz> %s)r!   r   interactiver   infoprintrx   s     r   rA   z_TLSAutomaton.vprint  sR    < 	" "$VQ/////fqj!!!!!		" 	"r   )NN)r-   r-   )T)NNN)r;   )__name__
__module____qualname____doc__r   r#   rY   r]   re   rm   rr   rz   rA   __classcell__)r   s   @r   r   r      s        & &P= = = = =
     0k k k kZ    
 
 
F F F F.0 0 0  " " " " " " " "r   r   )r   r?   r$   r=   scapy.automatonr   scapy.configr   scapy.errorr   scapy.packetr   scapy.layers.tls.basefieldsr   scapy.layers.tls.certr   r	   scapy.layers.tls.recordr
   scapy.layers.tls.record_sslv2r   scapy.layers.tls.record_tls13r   r   r   r   r   <module>r      s       % % % % % %       ' ' ' ' ' '       1 1 1 1 1 1 / / / / / / / / ' ' ' ' ' ' / / / / / / / / / / / /" " " " "I " " " " "r   