
    YfO                    (   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 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 Z-d Z. G d d          Z/ ee           G d de/                      Z0 ee           G d d                      Z1d Z2 ee           G d de/e+                      Z3 G d d          Z4 G d  d!          Z5dS )"zE
An implementation of the OpenSSH known_hosts database.

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

    @param s: The string to encode.
    @type s: L{bytes}

    @return: The base64-encoded string.
    @rtype: L{bytes}
    )r   strip)ss    Q/var/www/html/env/lib/python3.11/site-packages/twisted/conch/client/knownhosts.py
_b64encoder   $   s     a==       c                f   |                      dd          }t          |          dk    rt                      |\  }}}|                     dd          }t          |          dk    r|\  }}|                    d          }n
|d         }d}t	          j        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).
    @type string: L{bytes}

    @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.
    @rtype: L{tuple}
    N            
r   )splitlenr   rstripr   
fromStringr   )	stringelements	hostnameskeyTypekeyAndCommentsplitkey	keyStringcommentkeys	            r   _extractCommonr3   1   s     ||D!$$H
8}}nn(0%Iw""4++H
8}}%	7..''QK	
.I..
/
/CgsG++r    c                      e Zd ZdZd Z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}
    c                0    || _         || _        || _        d S N)r-   	publicKeyr1   )selfr-   r8   r1   s       r   __init__z_BaseEntry.__init__\   s    "r    c                    | j         |k    S )a  
        Check to see if this entry matches a given key object.

        @param keyObject: A public key object to check.
        @type keyObject: L{Key}

        @return: C{True} if this entry's key matches C{keyObject}, C{False}
            otherwise.
        @rtype: L{bool}
        )r8   )r9   	keyObjects     r   
matchesKeyz_BaseEntry.matchesKeya   s     ~**r    N)__name__
__module____qualname____doc__r:   r=    r    r   r5   r5   M   s<           
+ + + + +r    r5   c                  L     e Zd ZdZd fd	Zedd            ZddZddZ x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-   bytesr8   r   r1   c                \    || _         t                                          |||           d S r7   )
_hostnamessuperr:   )r9   r,   r-   r8   r1   	__class__s        r   r:   zPlainEntry.__init__x   s.     (1)W55555r    r*   returnc                p    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}
           ,)r3   r&   )clsr*   r,   r-   r2   r1   r9   s          r   r)   zPlainEntry.fromString~   s@    , ,:&+A+A(	7Cs9??4(('3@@r    hostnamebytes | strboolc                h    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encoderH   r9   rO   s     r   matchesHostzPlainEntry.matchesHost   s4     h$$ 	0w//H4?**r    c                    d                     | j                  | j        t          | j                                                  g}| j        |                    | 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.
        rM   N    )joinrH   r-   r   r8   blobr1   appendr9   fieldss     r   toStringzPlainEntry.toString   sj     IIdo&&Lt~**,,--

 <#MM$,'''yy   r    )r,   rE   r-   rF   r8   r   r1   rF   )r*   rF   rK   rD   )rO   rP   rK   rQ   )rK   rF   )
r>   r?   r@   rA   r:   classmethodr)   rX   r`   __classcell__rJ   s   @r   rD   rD   o   s         6 6 6 6 6 6    [2+ + + +! ! ! ! ! ! ! !r    rD   c                  *    e Zd ZdZd Zd Zd Z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.
    c                    || _         dS )zv
        Create an unparsed entry from a line in a known_hosts file which cannot
        otherwise be parsed.
        N)_string)r9   r*   s     r   r:   zUnparsedEntry.__init__   s    
 r    c                    dS z'
        Always returns False.
        FrB   rW   s     r   rX   zUnparsedEntry.matchesHost   	     ur    c                    dS ri   rB   )r9   r2   s     r   r=   zUnparsedEntry.matchesKey   rj   r    c                6    | 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%   )rg   r(   r9   s    r   r`   zUnparsedEntry.toString   s     |""5)))r    N)r>   r?   r@   rA   r:   rX   r=   r`   rB   r    r   re   re      sZ         
      * * * * *r    re   c                    t          j        | t                    }t          |t                    r|                    d          }|                    |           |                                S )z
    Return the SHA-1 HMAC hash of the given key and string.

    @param key: The HMAC key.
    @type key: L{bytes}

    @param string: The string to be hashed.
    @type string: L{bytes}

    @return: The keyed hash value.
    @rtype: L{bytes}
    )	digestmodrS   )hmacHMACr   rT   rU   rV   updatedigest)r2   r*   hashs      r   _hmacedStringru      s[     9SD)))D&# (w''KK;;==r    c                  P     e Zd ZdZdZdZd fdZedd            Zd Z	d Z
 x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-   r8   r1   hostSaltrF   hostHashr-   r8   r   r1   bytes | NonerK   Nonec                j    || _         || _        t                                          |||           d S r7   )rx   ry   rI   r:   )r9   rz   r{   r-   r8   r1   rJ   s         r   r:   zHashedEntry.__init__  s5     "!)W55555r    r*   c                *   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"   )r3   r'   MAGICr&   r   r   )
rN   r*   stuffr-   r2   r1   saltAndHashrz   r{   r9   s
             r   r)   zHashedEntry.fromString  s    , (6f'='=$wWC	NN,,-33D99{q  .. ((s:h''H)=)=wWUUr    c                \    t          j        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}
        )rp   compare_digestru   rx   ry   rW   s     r   rX   zHashedEntry.matchesHost-  s,     "$.(33T^
 
 	
r    c                L   | j         d                    t          | j                  t          | j                  g          z   | j        t          | j                                                  g}| j        |	                    | 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}
        r   NrZ   )
r   r[   r   rx   ry   r-   r8   r\   r1   r]   r^   s     r   r`   zHashedEntry.toString>  s     JiiDN33Z5O5OPQQRLt~**,,--	
 <#MM$,'''yy   r    )rz   rF   r{   rF   r-   rF   r8   r   r1   r|   rK   r}   )r*   rF   rK   rw   )r>   r?   r@   rA   r   compareAttributesr:   ra   r)   rX   r`   rb   rc   s   @r   rw   rw      s        
 
 EU
6 
6 
6 
6 
6 
6    [:
 
 
"! ! ! ! ! ! !r    rw   c                  n    e Zd ZdZddZedd            Zd Zd	 ZddZ	ddZ
ddZe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]rK   r}   c                0    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)r9   r   s     r   r:   zKnownHostsFile.__init__c  s     .0!r    c                    | j         S )z<
        @see: C{savePath} parameter of L{__init__}
        )r   rm   s    r   r   zKnownHostsFile.savePathq  s    
 ~r    c              #    K   | j         D ]}|V  | j        rdS 	 | j                                        }n# t          $ r Y dS w xY w|5  |D ]}	 |                    t          j                  rt                              |          }nt                              |          }n,# t          t          t          f$ r t          |          }Y nw xY w|V  	 ddd           dS # 1 swxY 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
startswithrw   r   r)   rD   DecodeErrorr   r   re   )r9   entryfplines       r   iterentrieszKnownHostsFile.iterentriesx  sr      [ 	 	EKKKK= 	F	$$&&BB 	 	 	FF	  		 		  0{'899 < + 6 6t < < * 5 5d ; ;#\;? 0 0 0)$//EEE0		 		 		 		 		 		 		 		 		 		 		 		 		 		 		 		 		 		sF   5 
AAC"AB#"C"#&C	C"CC""C&)C&c                `   t          |                                 t          | j                             D ]w\  }}|                    |          r]|j        |                                k    r@|                    |          r dS |dk     rd}d}n|dz   }| j        }t          |||          xdS )a  
        Check for an entry with matching hostname and key.

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

        @param key: The public key to check for.
        @type key: L{Key}

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

        @raise HostKeyChanged: if the host key found for the given hostname
            does not match the given key.
        Tr   Nr$   F)
	enumerater   r'   r   rX   r-   sshTyper=   r   r   )r9   rO   r2   lineidxr   r   paths          r   
hasHostKeyzKnownHostsFile.hasHostKey  s    " ((8(8(:(:S=M=M<MNN 	< 	<NGU  ** <u}/M/M##C(( <44 {{##&{#~(d;;;ur    ui	ConsoleUIrO   rF   ipr2   r   Deferred[bool]c                     t          j         j                  }d f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}
        resultrQ   rK   bool | Deferred[bool]c           
        | r	                               sd                                 d                                 d}
                    |                    d                     	                               	                                 | S d	fd}                                }|d	k    rd
}dt                    dt                    d|d                    t          j
                  d	}
                    |                    t          j                                        }|                    |          S )NzWarning: Permanently added the z host key for IP address 'z' to the list of known hosts.
rS   responserQ   rK   c                    | rB                                                                                                 | S t                      r7   )
addHostKeysaver   )r   rO   r   r2   r9   s    r   promptResponsezGKnownHostsFile.verifyHostKey.<locals>.gotHasKey.<locals>.promptResponse  sQ     0#666C000		'-///r    ECECDSAzThe authenticity of host 'z (z)' can't be established.
z key fingerprint is SHA256:)formatz9.
Are you sure you want to continue connecting (yes/no)? )r   rQ   rK   rQ   )r   typedecodewarnrV   r   r   r   fingerprintr   SHA256_BASE64promptsysgetdefaultencodingaddCallback)r   
addMessager   keytyper   proceedrO   r   r2   r9   r   s         r   	gotHasKeyz/KnownHostsFile.verifyHostKey.<locals>.gotHasKey  sx    (;r3//  $#((** $ $,.IIKK$ $ $ 
 GGJ--g66777OOB,,,IIKKK0 0 0 0 0 0 0 0 0  #xxzzd??%G %X....$R((((/A/OPPPP	  ))FMM#2H2J2J$K$KLL**>:::r    )r   rQ   rK   r   )r   executer   r   )r9   r   rO   r   r2   hhkr   s   `````  r   verifyHostKeyzKnownHostsFile.verifyHostKey  se    , mDOXs;;)	; )	; )	; )	; )	; )	; )	; )	; )	; )	;V y)))r    rw   c                    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   rw   ru   r   r]   )r9   rO   r2   saltr-   r   s         r   r   zKnownHostsFile.addHostKey  sX    " B++--D-h"?"?#tTT5!!!r    c                   | j                                         }|                                s|                                 | j        rdnd}| j                             |          5 }| j        rA|                    d                    d | j        D                       dz              g | _        ddd           n# 1 swxY w Y   d| _        dS )zM
        Save this L{KnownHostsFile} to the path it was loaded from.
        war%   c                6    g | ]}|                                 S rB   )r`   ).0r   s     r   
<listcomp>z'KnownHostsFile.save.<locals>.<listcomp>   s"    JJJU 0 0JJJr    NF)	r   parentisdirmakedirsr   r   r   writer[   )r9   pmodehostsFileObjs       r   r   zKnownHostsFile.save  s	    N!!##wwyy 	JJLLL)-"?##C^  && 	!,{ !""JJJJdkJJJKKeS   !	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! s   'A	B<<C C r   c                *     | |          }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   )rN   r   
knownHostss      r   fromPathzKnownHostsFile.fromPath%  s     SYY
#
r    N)r   r   rK   r}   )rK   r   )
r   r   rO   rF   r   rF   r2   r   rK   r   )rO   rF   r2   r   rK   rw   )rK   r}   )r   r   rK   r   )r>   r?   r@   rA   r:   propertyr   r   r   r   r   r   ra   r   rB   r    r   r   r   R  s                 X  >  BC* C* C* C*J   .   "    [  r    r   c                  *    e Zd ZdZddZdd	Z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]]c                    || _         dS )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   )r9   r   s     r   r:   zConsoleUI.__init__<  s     r    textrF   rK   r   c                d     t          j        d          } f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                v   t                                                    5 }|                               	 |                                                                                                }|dk    r	 d d d            dS |dv r	 d d d            dS |                    d           t# 1 swxY w Y   d S )NTs   yes>      nor    Fs   Please type 'yes' or 'no': )r   r   r   readliner   lower)ignoredfanswerr9   r   s      r   bodyzConsoleUI.prompt.<locals>.bodyU  s0   '' 	@1@ZZ\\//117799F''#	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@  <//$	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@  >???@	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@s   AB.B.B..B25B2)r   succeedr   )r9   r   dr   s   ``  r   r   zConsoleUI.promptF  sM     M$
	@ 
	@ 
	@ 
	@ 
	@ 
	@ }}T"""r    r}   c                    	 t          |                                           5 }|                    |           ddd           dS # 1 swxY w Y   dS # t          $ r t                              d           Y dS w xY 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)r9   r   r   s      r   r   zConsoleUI.warnc  s    	6'' 1                  	6 	6 	6KK4555555	6s3   !A AA A

A A
A $A;:A;N)r   r   )r   rF   rK   r   )r   rF   rK   r}   )r>   r?   r@   rA   r:   r   r   rB   r    r   r   r   6  sZ         
   # # # #:6 6 6 6 6 6r    r   )6rA   
__future__r   rp   r   binasciir   r   r   r   
contextlibr   hashlibr   typingr	   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   r3   r5   rD   re   ru   rw   r   r   rB   r    r   <module>r      s  
  # " " " " "  



 A A A A A A A A A A             ( ( ( ( ( ( ( ( ( ( & & & & & & M M M M M M M M M M 4 4 4 4 4 4 G G G G G G G G G G " " " " " " + + + + + + ! ! ! ! ! ! . . . . . . , , , , , , 1 1 1 1 1 1 , , , , , ,fhh
! 
! 
!, , ,8+ + + + + + + +D _E! E! E! E! E! E! E! E!P _!* !* !* !* !* !* !* !*H  ( _]! ]! ]! ]! ]!*l ]! ]! ]!@a a a a a a a aH86 86 86 86 86 86 86 86 86 86r    