§
    Ètºf¡O  ã                  ó(  — 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    ú^/var/www/surfInsights/venv3-11/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�}„}˜ÒÐÝ‰nŒnÐØ(0Ñ%€Iˆw˜Ø×"Ò" 4¨Ñ+Ô+€HÝ
ˆ8�}„}˜ÒÐØ%Ñˆ	�7Ø—.’. Ñ'Ô'ˆˆà˜Q”Kˆ	ØˆÝ
Œ.� IÑ.Ô.Ñ
/Ô
/€CØ�g˜s GÐ+Ð+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Ñ(ˆ	�7˜C Øˆs�9—?’? 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   € ð �IŠI�d”oÑ&Ô&ØŒLÝ�t”~×*Ò*Ñ,Ô,Ñ-Ô-ð
ˆð
 Œ<Ð#Ø�MŠM˜$œ,Ñ'Ô'Ð'Ø�yŠy˜Ñ Ô Ð 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[   € õ Œ9�S¥DÐ)Ñ)Ô)€DÝ�&�#ÑÔð (Ø—’˜wÑ'Ô'ˆØ‡K‚K�ÑÔÐØ�;Š;‰=Œ=Ð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“   € õ, (6°fÑ'=Ô'=Ñ$ˆˆw˜˜WØ�C ¤	™NœNÐ,Ð,Ô-×3Ò3°DÑ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Ô3°T´^ñ
ô 
ð 	
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Ø�iŠi� D¤NÑ3Ô3µZÀÄÑ5OÔ5OÐPÑQÔQñRàŒLÝ�t”~×*Ò*Ñ,Ô,Ñ-Ô-ð	
ˆð Œ<Ð#Ø�MŠM˜$œ,Ñ'Ô'Ð'Ø�yŠy˜Ñ Ô Ð 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ØˆKˆKˆKˆKàŒ=ð 	ØˆFð	Ø”×$Ò$Ñ&Ô&ˆBˆBøÝð 	ð 	ð 	ØˆFˆFð	øøøð ð 		ð 		Øð ð �ð0Ø—’¥{Ô'8Ñ9Ô9ð <Ý +× 6Ò 6°tÑ <Ô <˜˜å *× 5Ò 5°dÑ ;Ô ;˜øøÝ#¥\µ;Ð?ð 0ð 0ð 0Ý)¨$Ñ/Ô/�E�E�Eð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ð 	<ð 	<‰NˆG�UØ× Ò  Ñ*Ô*ð <¨u¬}ÀÇÂÁÄÒ/MÐ/MØ×#Ò# CÑ(Ô(ð <Ø˜4˜4ð  ’{�{Ø#˜Ø#˜˜à&¨™{˜Ø#œ~˜Ý(¨°°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  ø€ Øð (;Ø—’ r¨3Ñ/Ô/ð  ð$¸#¿(º(¹*¼*ð $ð $Ø,.¯IªI©K¬Kð$ð $ð $ð ð
 —G’G˜J×-Ò-¨gÑ6Ô6Ñ7Ô7Ð7Ø—O’O B¨Ñ,Ô,Ð,Ø—I’I‘K”K�KØ�ð0ð 0ð 0ð 0ð 0ð 0ð 0ð 0ð 0ð  #Ÿxšx™zœz�à˜d’?�?Ø%�Gøõ % XÑ.Ô.Ð.Ð.Ý$ RÑ(Ô(Ð(Ð(Ø˜˜ØŸšÕ/AÔ/O˜ÑPÔPÐPÐPð	ð ð Ÿ)š) F§M¢Mµ#Ô2HÑ2JÔ2JÑ$KÔ$KÑLÔL�Ø×*Ò*¨>Ñ:Ô:Ð:r    )r¥   rQ   rK   r¦   )r   ÚexecuterŸ   r¸   )r9   r    rO   r¢   r2   Úhhkr¼   s   `````  r   ÚverifyHostKeyzKnownHostsFile.verifyHostKey¸  se   øøøøø€ õ, Œm˜DœO¨X°sÑ;Ô;ˆð)	;ð )	;ð )	;ð )	;ð )	;ð )	;ð )	;ð )	;ð )	;ð )	;ð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ÐJ°U §¢Ñ 0Ô 0ÐJÐJÐJr    NF)	rŽ   ÚparentÚisdirÚmakedirsr�   r’   r�   Úwriter[   )r9   ÚpÚmodeÚhostsFileObjs       r   r«   zKnownHostsFile.save  s	  € ð ŒN×!Ò!Ñ#Ô#ˆØ�wŠw‰yŒyð 	Ø�JŠJ‰LŒLˆLà)-¬Ð"? # #¸CˆØŒ^× Ò  Ñ&Ô&ð 	!¨,ØŒ{ð !Ø×"Ò"Ø—J’JÐJÐJ¸d¼kÐJÑJÔJÑKÔKÈeÑ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˜‘Y”Yˆ
Ø#ˆ
ÔØÐ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Ø—’˜‘”�ð@ØŸZšZ™\œ\×/Ò/Ñ1Ô1×7Ò7Ñ9Ô9�FØ Ò'Ð'Ø#ð	@ð 	@ð 	@ñ 	@ô 	@ð 	@ð 	@ð 	@ð   <Ð/Ð/Ø$ð	@ð 	@ð 	@ñ 	@ô 	@ð 	@ð 	@ð 	@ð ŸšÐ >Ñ?Ô?Ð?ð@ð	@ð 	@ð 	@ð 	@øøøð 	@ð 	@ð 	@ð 	@ð 	@ð 	@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Ý�KŠKÐ4Ñ5Ô5Ð5Ð5Ð5Ð5ð	6øøøs3   ‚!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Ø ,Ð ,Ð ,Ð ,Ð ,Ð ,à€f�h„h€ð
!ð 
!ð 
!ð,ð ,ð ,ð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    