o
    Òó·iôO  ã                   @  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.
    N)r   Ústrip)r   © r   úeC:\Users\psant\Downloads\PAF backend\school\venv\Lib\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ÚkeyTypeZkeyAndCommentZsplitkeyZ	keyStringÚcommentÚkeyr   r   r    Ú_extractCommon/   s   
r2   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   r0   úbytes | Noner   ÚNonec                 C  s   || _ || _|| _d S ©N)r/   r4   r0   )Úselfr/   r4   r0   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.
        N)r4   )r8   r:   Úresultr   r   r    Ú
matchesKey]   s   
	z_BaseEntry.matchesKeyN)r/   r   r4   r   r0   r5   r   r6   )r:   r   r   r;   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r9   r=   r   r   r   r    r3   I   s    
r3   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   r4   r   r0   r5   c                   s   || _ tƒ  |||¡ d S r7   )Ú
_hostnamesÚsuperr9   )r8   r.   r/   r4   r0   ©Ú	__class__r   r    r9   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}
        ó   ,N)r2   r)   )Úclsr#   r.   r/   r1   r0   r8   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-8N)Ú
isinstanceÚstrÚencoderD   ©r8   rJ   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.
        rH   Nó    )ÚjoinrD   r/   r!   r4   Úblobr0   Úappend©r8   Úfieldsr   r   r    ÚtoString¥   s   
	ý

zPlainEntry.toString)r.   rC   r/   r   r4   r   r0   r5   )r#   r   r   rB   )rJ   rK   r   r;   ©r   r   )
r>   r?   r@   rA   r9   Úclassmethodr,   rQ   rX   Ú__classcell__r   r   rF   r    rB   j   s    

rB   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.
    Nr6   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)r8   r#   r   r   r    r9   À   s   
zUnparsedEntry.__init__rJ   r;   c                 C  ó   dS ©z'
        Always returns False.
        FNr   rP   r   r   r    rQ   Ç   ó   zUnparsedEntry.matchesHostr1   r   c                 C  r_   r`   r   )r8   r1   r   r   r    r=   Í   ra   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(   N)r^   r+   ©r8   r   r   r    rX   Ó   r"   zUnparsedEntry.toString)r#   r   r   r6   ©rJ   r   r   r;   )r1   r   r   r;   rY   )
r>   r?   r@   rA   r/   Ú__annotations__r9   rQ   r=   rX   r   r   r   r    r\   ·   s   
 


r\   r1   rK   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.
    )Ú	digestmodrL   N)ÚhmacÚHMACr   rM   rN   rO   ÚupdateÚdigest)r1   r#   Úhashr   r   r    Ú_hmacedStringÞ   s
   



rk   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/   r4   r0   ÚhostSaltr   ÚhostHashr/   r4   r   r0   r5   r   r6   c                   s    || _ || _tƒ  |||¡ d S r7   )rm   rn   rE   r9   )r8   ro   rp   r/   r4   r0   rF   r   r    r9     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%   )r2   r*   ÚMAGICr)   r   r   )
rI   r#   Ústuffr/   r1   r0   ZsaltAndHashro   rp   r8   r   r   r    r,     s   zHashedEntry.fromStringrJ   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}
        N)rf   Úcompare_digestrk   rm   rn   rP   r   r   r    rQ   +  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}
        rq   NrR   )
rr   rS   r!   rm   rn   r/   r4   rT   r0   rU   rV   r   r   r    rX   <  s   
ÿü

zHashedEntry.toString)ro   r   rp   r   r/   r   r4   r   r0   r5   r   r6   )r#   r   r   rl   rc   rY   )r>   r?   r@   rA   rr   ZcompareAttributesr9   rZ   r,   rQ   rX   r[   r   r   rF   r    rl   ï   s    
rl   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   r6   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)r8   rv   r   r   r    r9   a  s   

zKnownHostsFile.__init__c                 C  s   | j S )z<
        @see: C{savePath} parameter of L{__init__}
        N)ry   rb   r   r   r    rv   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)rx   rz   ry   ÚopenÚOSErrorÚ
startswithrl   rr   r,   rB   ÚDecodeErrorr   r   r\   )r8   ÚentryÚfpÚliner   r   r    Úiterentriesv  s.   €
	ÿ
€ÿø"ÿzKnownHostsFile.iterentriesrJ   r   r1   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*   rx   r/   ÚsshTyperQ   r=   ry   r   )r8   rJ   r1   Z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.
rL   Úresponser;   r   c                   s.   | rˆ  ˆ ˆ¡ ˆ  ˆˆ¡ ˆ ¡  | S tƒ ‚r7   )Ú
addHostKeyÚsaver   )r�   )rJ   rŠ   r1   r8   r   r    ÚpromptResponseÙ  s   zGKnownHostsFile.verifyHostKey.<locals>.gotHasKey.<locals>.promptResponseZECZECDSAz‘The 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ÚwarnrO   rŽ   r�   r   Úfingerprintr   ZSHA256_BASE64ÚpromptÚsysÚgetdefaultencodingÚaddCallback)r<   Z
addMessager�   Zkeytyper–   Úproceed©rJ   rŠ   r1   r8   rˆ   r   r    Ú	gotHasKeyË  s0   ÿÿ	üüÿ
z/KnownHostsFile.verifyHostKey.<locals>.gotHasKeyN)r<   r;   r   rŒ   )r   Úexecuter‡   r™   )r8   rˆ   rJ   rŠ   r1   Zhhkrœ   r   r›   r    ÚverifyHostKey³  s   
+zKnownHostsFile.verifyHostKeyrl   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…   rl   rk   rx   rU   )r8   rJ   r1   Z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   )rX   )Ú.0r€   r   r   r    Ú
<listcomp>  s    z'KnownHostsFile.save.<locals>.<listcomp>NF)	ry   ÚparentÚisdirÚmakedirsrz   r|   rx   ÚwriterS   )r8   ÚpÚmodeZ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}.
        FN)rz   )rI   r†   Z
knownHostsr   r   r    ÚfromPath   s   zKnownHostsFile.fromPathN)rv   rw   r   r6   )r   rw   )r   r{   )rJ   r   r1   r   r   r;   )
rˆ   r‰   rJ   r   rŠ   r   r1   r   r   r‹   )rJ   r   r1   r   r   rl   )r   r6   )r†   rw   r   ru   )r>   r?   r@   rA   r9   Úpropertyrv   rƒ   r‡   rž   rŽ   r�   rZ   rª   r   r   r   r    ru   P  s    




E
ru   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   r6   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¬   )r8   r¬   r   r   r    r9   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>   ó    s   noFs   Please type 'yes' or 'no': )r   r¬   r§   Úreadliner   Úlower)ZignoredÚfZanswer©r8   r®   r   r    ÚbodyP  s   
ûù
	ùþzConsoleUI.prompt.<locals>.body)r   Zsucceedr™   )r8   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ÚlogZfailure)r8   r®   r²   r   r   r    r”   ^  s   &ÿÿzConsoleUI.warnN)r¬   r­   r   r6   )r®   r   r   r‹   )r®   r   r   r6   )r>   r?   r@   rA   r9   r–   r”   r   r   r   r    r‰   1  s
    


r‰   )r   r   r   r   )r#   r   r   r$   )r1   r   r#   rK   r   r   )7rA   Ú
__future__r   rf   r—   Úbinasciir   r   r   r   Ú
contextlibr   Úhashlibr   Útypingr   r	   r
   r   Zzope.interfacer   Ztwisted.conch.errorr   r   r   Ztwisted.conch.interfacesr   Ztwisted.conch.ssh.keysr   r   r   Ztwisted.internetr   Ztwisted.internet.deferr   Ztwisted.loggerr   Ztwisted.python.compatr   Ztwisted.python.filepathr   Ztwisted.python.randbytesr   Ztwisted.python.utilr   r·   r!   r2   r3   rB   r\   rk   rl   ru   r‰   r   r   r   r    Ú<module>   sB   

!L
&` b