o
    9BiO                     @  s  d Z ddlmZ ddlZddlZddlmZmZm	Z	 ddl
mZ ddlmZ ddlmZmZmZmZ ddlmZ dd	lmZmZmZ dd
lmZ ddlmZmZ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( ddl)m*Z* ddl+m,Z, e$ Z-d,ddZ.d-ddZ/G dd dZ0eeG dd de0Z1eeG d d! d!Z2d.d$d%Z3eeG d&d' d'e0e,Z4G d(d) d)Z5G d*d+ d+Z6dS )/zE
An implementation of the OpenSSH known_hosts database.

@since: 8.2
    )annotationsN)Error
a2b_base64
b2a_base64)closing)sha1)IOCallableIterableLiteral)implementer)HostKeyChangedInvalidEntryUserRejectedKey)IKnownHostEntry)BadKeyErrorFingerprintFormatsKey)defer)Deferred)Logger)nativeString)FilePath)secureRandom)FancyEqMixinsbytesreturnc                 C  s   t |  S )z
    Encode a binary string as base64 with no trailing newline.

    @param s: The string to encode.

    @return: The base64-encoded string.
    )r   strip)r    r   _/var/www/html/Trade-python/venv/lib/python3.10/site-packages/twisted/conch/client/knownhosts.py
_b64encode$      r!   string&tuple[bytes, bytes, Key, bytes | None]c           	      C  sz   |  dd}t|dkrt |\}}}| dd}t|dkr*|\}}|d}n|d }d}tt|}||||fS )a  
    Extract common elements of base64 keys from an entry in a hosts file.

    @param string: A known hosts file entry (a single line).

    @return: a 4-tuple of hostname data (L{bytes}), ssh key type (L{bytes}), key
        (L{Key}), and comment (L{bytes} or L{None}).  The hostname data is
        simply the beginning of the line up to the first occurrence of
        whitespace.
    N            
r   )splitlenr   rstripr   
fromStringr   )	r#   elements	hostnameskeyTypekeyAndCommentsplitkey	keyStringcommentkeyr   r   r    _extractCommon/   s   
r5   c                   @  s$   e Zd ZdZdd
dZdddZdS )
_BaseEntrya  
    Abstract base of both hashed and non-hashed entry objects, since they
    represent keys and key types the same way.

    @ivar keyType: The type of the key; either ssh-dss or ssh-rsa.
    @type keyType: L{bytes}

    @ivar publicKey: The server public key indicated by this line.
    @type publicKey: L{twisted.conch.ssh.keys.Key}

    @ivar comment: Trailing garbage after the key line.
    @type comment: L{bytes} or C{None}
    r/   r   	publicKeyr   r3   bytes | Noner   Nonec                 C  s   || _ || _|| _d S N)r/   r7   r3   )selfr/   r7   r3   r   r   r    __init__X   s   
z_BaseEntry.__init__	keyObjectboolc                 C  s   | j |k}|S )z
        Check to see if this entry matches a given key object.

        @param keyObject: A public key object to check.

        @return: C{True} if this entry's key matches C{keyObject}, C{False}
            otherwise.
        )r7   )r;   r=   resultr   r   r    
matchesKey]   s   
	z_BaseEntry.matchesKeyN)r/   r   r7   r   r3   r8   r   r9   )r=   r   r   r>   )__name__
__module____qualname____doc__r<   r@   r   r   r   r    r6   I   s    
r6   c                      sD   e Zd ZdZd fd
dZedddZdddZdddZ  Z	S )
PlainEntryz
    A L{PlainEntry} is a representation of a plain-text entry in a known_hosts
    file.

    @ivar _hostnames: the list of all host-names associated with this entry.
    r.   list[bytes]r/   r   r7   r   r3   r8   c                   s   || _ t ||| d S r:   )
_hostnamessuperr<   )r;   r.   r/   r7   r3   	__class__r   r    r<   s   s   zPlainEntry.__init__r#   r   c                 C  s(   t |\}}}}| |d|||}|S )a  
        Parse a plain-text entry in a known_hosts file, and return a
        corresponding L{PlainEntry}.

        @param string: a space-separated string formatted like "hostname
            key-type base64-key-data comment".

        @raise DecodeError: if the key is not valid encoded as valid base64.

        @raise InvalidEntry: if the entry does not have the right number of
            elements and is therefore invalid.

        @raise BadKeyError: if the key, once decoded from base64, is not
            actually an SSH key.

        @return: an IKnownHostEntry representing the hostname and key in the
            input line.

        @rtype: L{PlainEntry}
           ,)r5   r)   )clsr#   r.   r/   r4   r3   r;   r   r   r    r,   }   s   zPlainEntry.fromStringhostnamebytes | strr>   c                 C  s   t |tr
|d}|| jv S )a  
        Check to see if this entry matches a given hostname.

        @param hostname: A hostname or IP address literal to check against this
            entry.

        @return: C{True} if this entry is for the given hostname or IP address,
            C{False} otherwise.
        utf-8)
isinstancestrencoderG   r;   rM   r   r   r    matchesHost   s   



zPlainEntry.matchesHostc                 C  s>   d | j| jt| j g}| jdur|| j d |S )z
        Implement L{IKnownHostEntry.toString} by recording the comma-separated
        hostnames, key type, and base-64 encoded key.

        @return: The string representation of this entry, with unhashed hostname
            information.
        rK   N    )joinrG   r/   r!   r7   blobr3   appendr;   fieldsr   r   r    toString   s   
	

zPlainEntry.toString)r.   rF   r/   r   r7   r   r3   r8   )r#   r   r   rE   )rM   rN   r   r>   r   r   )
rA   rB   rC   rD   r<   classmethodr,   rT   r[   __classcell__r   r   rI   r    rE   j   s    

rE   c                   @  sF   e Zd ZU dZdZded< ddd	ZdddZdddZdddZ	dS )UnparsedEntryz
    L{UnparsedEntry} is an entry in a L{KnownHostsFile} which can't actually be
    parsed; therefore it matches no keys and no hosts.
    Nr9   r/   r#   r   r   c                 C  
   || _ dS )zv
        Create an unparsed entry from a line in a known_hosts file which cannot
        otherwise be parsed.
        N)_string)r;   r#   r   r   r    r<      s   
zUnparsedEntry.__init__rM   r>   c                 C     dS z'
        Always returns False.
        Fr   rS   r   r   r    rT         zUnparsedEntry.matchesHostr4   r   c                 C  rb   rc   r   )r;   r4   r   r   r    r@      rd   zUnparsedEntry.matchesKeyc                 C  s   | j dS )a  
        Returns the input line, without its newline if one was given.

        @return: The string representation of this entry, almost exactly as was
            used to initialize this entry but without a trailing newline.
        @rtype: L{bytes}
        r(   )ra   r+   r;   r   r   r    r[      r"   zUnparsedEntry.toString)r#   r   r   r9   rM   r   r   r>   )r4   r   r   r>   r\   )
rA   rB   rC   rD   r/   __annotations__r<   rT   r@   r[   r   r   r   r    r_      s   
 


r_   r4   rN   c                 C  s4   t j| td}t|tr|d}|| | S )z
    Return the SHA-1 HMAC hash of the given key and string.

    @param key: The HMAC key.

    @param string: The string to be hashed.

    @return: The keyed hash value.
    )	digestmodrO   )hmacHMACr   rP   rQ   rR   updatedigest)r4   r#   hashr   r   r    _hmacedString   s
   



rn   c                      sL   e Zd ZdZdZdZd fddZedddZdddZ	dddZ
  ZS )HashedEntrya  
    A L{HashedEntry} is a representation of an entry in a known_hosts file
    where the hostname has been hashed and salted.

    @ivar _hostSalt: the salt to combine with a hostname for hashing.

    @ivar _hostHash: the hashed representation of the hostname.

    @cvar MAGIC: the 'hash magic' string used to identify a hashed line in a
    known_hosts file as opposed to a plaintext one.
    s   |1|)	_hostSalt	_hostHashr/   r7   r3   hostSaltr   hostHashr/   r7   r   r3   r8   r   r9   c                   s    || _ || _t ||| d S r:   )rp   rq   rH   r<   )r;   rr   rs   r/   r7   r3   rI   r   r    r<     s   zHashedEntry.__init__r#   c           
      C  s^   t |\}}}}|t| jd d}t|dkrt |\}}| t|t||||}	|	S )a  
        Load a hashed entry from a string representing a line in a known_hosts
        file.

        @param string: A complete single line from a I{known_hosts} file,
            formatted as defined by OpenSSH.

        @raise DecodeError: if the key, the hostname, or the is not valid
            encoded as valid base64

        @raise InvalidEntry: if the entry does not have the right number of
            elements and is therefore invalid, or the host/hash portion
            contains more items than just the host and hash.

        @raise BadKeyError: if the key, once decoded from base64, is not
            actually an SSH key.

        @return: The newly created L{HashedEntry} instance, initialized with
            the information from C{string}.
        N   |r%   )r5   r*   MAGICr)   r   r   )
rL   r#   stuffr/   r4   r3   saltAndHashrr   rs   r;   r   r   r    r,     s   zHashedEntry.fromStringrM   r>   c                 C  s   t t| j|| jS )a  
        Implement L{IKnownHostEntry.matchesHost} to compare the hash of the
        input to the stored hash.

        @param hostname: A hostname or IP address literal to check against this
            entry.
        @type hostname: L{bytes}

        @return: C{True} if this entry is for the given hostname or IP address,
            C{False} otherwise.
        @rtype: L{bool}
        )ri   compare_digestrn   rp   rq   rS   r   r   r    rT   +  s   zHashedEntry.matchesHostc                 C  sR   | j dt| jt| jg | jt| j g}| jdur$|	| j d|S )z
        Implement L{IKnownHostEntry.toString} by base64-encoding the salt, host
        hash, and key.

        @return: The string representation of this entry, with the hostname part
            hashed.
        @rtype: L{bytes}
        rt   NrU   )
ru   rV   r!   rp   rq   r/   r7   rW   r3   rX   rY   r   r   r    r[   <  s   


zHashedEntry.toString)rr   r   rs   r   r/   r   r7   r   r3   r8   r   r9   )r#   r   r   ro   rf   r\   )rA   rB   rC   rD   ru   compareAttributesr<   r]   r,   rT   r[   r^   r   r   rI   r    ro      s    
ro   c                   @  sh   e Zd ZdZd#ddZed$dd	Zd%ddZd&ddZd'ddZ	d(ddZ
d)ddZed*d d!Zd"S )+KnownHostsFileaz  
    A structured representation of an OpenSSH-format ~/.ssh/known_hosts file.

    @ivar _added: A list of L{IKnownHostEntry} providers which have been added
        to this instance in memory but not yet saved.

    @ivar _clobber: A flag indicating whether the current contents of the save
        path will be disregarded and potentially overwritten or not.  If
        C{True}, this will be done.  If C{False}, entries in the save path will
        be read and new entries will be saved by appending rather than
        overwriting.
    @type _clobber: L{bool}

    @ivar _savePath: See C{savePath} parameter of L{__init__}.
    savePathFilePath[str]r   r9   c                 C  s   g | _ || _d| _dS )a$  
        Create a new, empty KnownHostsFile.

        Unless you want to erase the current contents of C{savePath}, you want
        to use L{KnownHostsFile.fromPath} instead.

        @param savePath: The L{FilePath} to which to save new entries.
        @type savePath: L{FilePath}
        TN)_added	_savePath_clobber)r;   r{   r   r   r    r<   a  s   

zKnownHostsFile.__init__c                 C  s   | j S )z<
        @see: C{savePath} parameter of L{__init__}
        )r~   re   r   r   r    r{   o  s   zKnownHostsFile.savePathIterable[IKnownHostEntry]c                 c  s    | j D ]}|V  q| jrdS z| j }W n
 ty    Y dS w |5 |D ])}z|tjr5t|}nt	|}W n t
ttfyK   t|}Y nw |V  q&W d   dS 1 s[w   Y  dS )aK  
        Iterate over the host entries in this file.

        @return: An iterable the elements of which provide L{IKnownHostEntry}.
            There is an element for each entry in the file as well as an element
            for each added but not yet saved entry.
        @rtype: iterable of L{IKnownHostEntry} providers
        N)r}   r   r~   openOSError
startswithro   ru   r,   rE   DecodeErrorr   r   r_   )r;   entryfpliner   r   r    iterentriesv  s.   
	
"zKnownHostsFile.iterentriesrM   r   r4   r   r>   c                 C  sx   t |  t| j D ].\}}|j| kr9||r9||r# dS |dk r,d}d}n|d }| j}t	|||qdS )a  
        Check for an entry with matching hostname and key.

        @param hostname: A hostname or IP address literal to check for.

        @param key: The public key to check for.

        @return: C{True} if the given hostname and key are present in this
            file, C{False} if they are not.

        @raise HostKeyChanged: if the host key found for the given hostname
            does not match the given key.
        Tr   Nr'   F)
	enumerater   r*   r}   r/   sshTyperT   r@   r~   r   )r;   rM   r4   lineidxr   r   pathr   r   r    
hasHostKey  s   
zKnownHostsFile.hasHostKeyui	ConsoleUIipDeferred[bool]c                   s0   t j }d fdd}||S )	a  
        Verify the given host key for the given IP and host, asking for
        confirmation from, and notifying, the given UI about changes to this
        file.

        @param ui: The user interface to request an IP address from.

        @param hostname: The hostname that the user requested to connect to.

        @param ip: The string representation of the IP address that is actually
        being connected to.

        @param key: The public key of the server.

        @return: a L{Deferred} that fires with True when the key has been
            verified, or fires with an errback when the key either cannot be
            verified or has changed.
        @rtype: L{Deferred}
        r?   r>   r   bool | Deferred[bool]c                   s   | r) s'd  d  d}|d    | S d fdd	} }|d
kr=d}dt t|jt	j
df }|t }||S )NzWarning: Permanently added the z host key for IP address 'z' to the list of known hosts.
rO   responser>   r   c                   s.   | r       | S t r:   )
addHostKeysaver   )r   )rM   r   r4   r;   r   r    promptResponse  s   zGKnownHostsFile.verifyHostKey.<locals>.gotHasKey.<locals>.promptResponseECECDSAzThe authenticity of host '%s (%s)' can't be established.
%s key fingerprint is SHA256:%s.
Are you sure you want to continue connecting (yes/no)? )format)r   r>   r   r>   )r   typedecodewarnrR   r   r   r   fingerprintr   SHA256_BASE64promptsysgetdefaultencodingaddCallback)r?   
addMessager   keytyper   proceedrM   r   r4   r;   r   r   r    	gotHasKey  s0   	
z/KnownHostsFile.verifyHostKey.<locals>.gotHasKeyN)r?   r>   r   r   )r   executer   r   )r;   r   rM   r   r4   hhkr   r   r   r    verifyHostKey  s   
+zKnownHostsFile.verifyHostKeyro   c                 C  s6   t d}| }t|t||||d}| j| |S )a  
        Add a new L{HashedEntry} to the key database.

        Note that you still need to call L{KnownHostsFile.save} if you wish
        these changes to be persisted.

        @param hostname: A hostname or IP address literal to associate with the
            new entry.
        @type hostname: L{bytes}

        @param key: The public key to associate with the new entry.
        @type key: L{Key}

        @return: The L{HashedEntry} that was added.
        @rtype: L{HashedEntry}
           N)r   r   ro   rn   r}   rX   )r;   rM   r4   saltr/   r   r   r   r    r     s
   zKnownHostsFile.addHostKeyc                 C  s   | j  }| s|  | jrdnd}| j |}| jr1|ddd | jD d  g | _W d   n1 s;w   Y  d| _dS )zM
        Save this L{KnownHostsFile} to the path it was loaded from.
        war(   c                 S  s   g | ]}|  qS r   )r[   ).0r   r   r   r    
<listcomp>  s    z'KnownHostsFile.save.<locals>.<listcomp>NF)	r~   parentisdirmakedirsr   r   r}   writerV   )r;   pmodehostsFileObjr   r   r    r     s   

zKnownHostsFile.saver   c                 C  s   | |}d|_ |S )a  
        Create a new L{KnownHostsFile}, potentially reading existing known
        hosts information from the given file.

        @param path: A path object to use for both reading contents from and
            later saving to.  If no file exists at this path, it is not an
            error; a L{KnownHostsFile} with no entries is returned.

        @return: A L{KnownHostsFile} initialized with entries from C{path}.
        F)r   )rL   r   
knownHostsr   r   r    fromPath   s   zKnownHostsFile.fromPathN)r{   r|   r   r9   )r   r|   )r   r   )rM   r   r4   r   r   r>   )
r   r   rM   r   r   r   r4   r   r   r   )rM   r   r4   r   r   ro   )r   r9   )r   r|   r   rz   )rA   rB   rC   rD   r<   propertyr{   r   r   r   r   r   r]   r   r   r   r   r    rz   P  s    




E
rz   c                   @  s.   e Zd ZdZdddZdddZdddZdS )r   z
    A UI object that can ask true/false questions and post notifications on the
    console, to be used during key verification.
    openerCallable[[], IO[bytes]]r   r9   c                 C  r`   )aA  
        @param opener: A no-argument callable which should open a console
            binary-mode file-like object to be used for reading and writing.
            This initializes the C{opener} attribute.
        @type opener: callable taking no arguments and returning a read/write
            file-like object
        N)r   )r;   r   r   r   r    r<   7  s   
zConsoleUI.__init__textr   r   c                   s"   t d} fdd}||S )a  
        Write the given text as a prompt to the console output, then read a
        result from the console input.

        @param text: Something to present to a user to solicit a yes or no
            response.
        @type text: L{bytes}

        @return: a L{Deferred} which fires with L{True} when the user answers
            'yes' and L{False} when the user answers 'no'.  It may errback if
            there were any I/O errors.
        Nc                   s~   t   /}| 	 |   }|dkr"	 W d    dS |dv r/	 W d    dS |d q1 s8w   Y  d S )NTs   yes>      no    Fs   Please type 'yes' or 'no': )r   r   r   readliner   lower)ignoredfanswerr;   r   r   r    bodyP  s   

	zConsoleUI.prompt.<locals>.body)r   succeedr   )r;   r   dr   r   r   r    r   A  s   

zConsoleUI.promptc                 C  s`   z t |  }|| W d   W dS 1 sw   Y  W dS  ty/   td Y dS w )z
        Notify the user (non-interactively) of the provided text, by writing it
        to the console.

        @param text: Some information the user is to be made aware of.
        NzFailed to write to console)r   r   r   	Exceptionlogfailure)r;   r   r   r   r   r    r   ^  s   &zConsoleUI.warnN)r   r   r   r9   )r   r   r   r   )r   r   r   r9   )rA   rB   rC   rD   r<   r   r   r   r   r   r    r   1  s
    


r   )r   r   r   r   )r#   r   r   r$   )r4   r   r#   rN   r   r   )7rD   
__future__r   ri   r   binasciir   r   r   r   
contextlibr   hashlibr   typingr   r	   r
   r   zope.interfacer   twisted.conch.errorr   r   r   twisted.conch.interfacesr   twisted.conch.ssh.keysr   r   r   twisted.internetr   twisted.internet.deferr   twisted.loggerr   twisted.python.compatr   twisted.python.filepathr   twisted.python.randbytesr   twisted.python.utilr   r   r!   r5   r6   rE   r_   rn   ro   rz   r   r   r   r   r    <module>   sB   

!L
&` b