3 ›äL]É3ã@sòddlZddlZddlZejdd…dkr8ddlmZn ddlmZddlmZddl m Z ddl m Z m Z mZmZddlmZdd lmZdd lmZmZdd lmZdd lmZdd lmZGdd„deƒZGdd„deƒZGdd„dƒZ dS)éNéé)ÚMutableMapping)Úsha1)ÚHMAC)ÚbÚuÚ encodebytesÚ decodebytes)ÚDSSKey)ÚRSAKey)Ú get_loggerÚconstant_time_bytes_eq)ÚECDSAKey)Ú Ed25519Key)Ú SSHExceptionc@s˜eZdZdZd#dd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dd„Z dd„Z dd„Zdd„Zdd„Zdd„Zdd „Zed$d!d"„ƒZdS)%ÚHostKeysaZ Representation of an OpenSSH-style "known hosts" file. Host keys can be read from one or more files, and then individual hosts can be looked up to verify server keys during SSH negotiation. A `.HostKeys` object can be treated like a dict; any dict lookup is equivalent to calling `lookup`. .. versionadded:: 1.5.3 NcCsg|_|dk r|j|ƒdS)z¿ Create a new HostKeys object, optionally loading keys from an OpenSSH style host-key file. :param str filename: filename to load host keys from, or ``None`` N)Ú_entriesÚload)ÚselfÚfilename©rú7/tmp/pip-install-wfra5znf/paramiko/paramiko/hostkeys.pyÚ__init__5szHostKeys.__init__cCsJx0|jD]&}||jkr|jjƒ|kr||_dSqW|jjt|g|ƒƒdS)a. Add a host key entry to the table. Any existing entry for a ``(hostname, keytype)`` pair will be replaced. :param str hostname: the hostname (or IP) to add :param str keytype: key type (``"ssh-rsa"`` or ``"ssh-dss"``) :param .PKey key: the key to add N)rÚ hostnamesÚkeyÚget_nameÚappendÚ HostKeyEntry)rÚhostnameÚkeytyperÚerrrÚaddAs z HostKeys.addcCsÈt|dƒ�´}x¬t|dƒD]ž\}}|jƒ}t|ƒdks|ddkrBqytj||ƒ}Wntk rhwYnX|dk r|j}x&|D]}|j||j ƒr~|jj |ƒq~Wt|jƒr|j j |ƒqWWdQRXdS)a] Read a file of known SSH host keys, in the format used by OpenSSH. This type of file unfortunately doesn't exist on Windows, but on posix, it will usually be stored in ``os.path.expanduser("~/.ssh/known_hosts")``. If this method is called multiple times, the host keys are merged, not cleared. So multiple calls to `load` will just call `add`, replacing any existing entries and adding new ones. :param str filename: name of the file to read host keys from :raises: ``IOError`` -- if there was an error reading the file Úrérú#N) ÚopenÚ enumerateÚstripÚlenrÚ from_linerrÚcheckrÚremoverr)rrÚfÚlinenoÚliner!Z _hostnamesÚhrrrrPs    z HostKeys.loadc Cs@t|dƒ�,}x$|jD]}|jƒ}|r|j|ƒqWWdQRXdS)aç Save host keys into a file, in the format used by OpenSSH. The order of keys in the file will be preserved when possible (if these keys were loaded from a file originally). The single exception is that combined lines will be split into individual key lines, which is arguably a bug. :param str filename: name of the file to write :raises: ``IOError`` -- if there was an error writing the file .. versionadded:: 1.6.1 ÚwN)r&rÚto_lineÚwrite)rrr-r!r/rrrÚsaveps  z HostKeys.savecsZG‡fdd„dtƒ}g}x$|jD]}|jˆ|ƒr |j|ƒq Wt|ƒdkrNdS|ˆ||ƒS)a’ Find a hostkey entry for a given hostname or IP. If no entry is found, ``None`` is returned. Otherwise a dictionary of keytype to key is returned. The keytype will be either ``"ssh-rsa"`` or ``"ssh-dss"``. :param str hostname: the hostname (or IP) to lookup :return: dict of `str` -> `.PKey` keys associated with this host (or ``None``) csHeZdZdd„Zdd„Zdd„Zdd„Zd d „Z‡fd d „Zd d„Z dS)z HostKeys.lookup..SubDictcSs||_||_||_dS)N)Z _hostnamerÚ _hostkeys)rrÚentriesZhostkeysrrrr�sz)HostKeys.lookup..SubDict.__init__cssx|jƒD] }|Vq WdS)N)Úkeys)rÚkrrrÚ__iter__”sz)HostKeys.lookup..SubDict.__iter__cSs t|jƒƒS)N)r)r7)rrrrÚ__len__˜sz(HostKeys.lookup..SubDict.__len__cSs:x4t|jƒD]}|jjƒ|kr |jj|ƒq Wt|ƒ‚dS)N)Úlistrrrr,ÚKeyError)rrr!rrrÚ __delitem__›sz,HostKeys.lookup..SubDict.__delitem__cSs0x"|jD]}|jjƒ|kr|jSqWt|ƒ‚dS)N)rrrr<)rrr!rrrÚ __getitem__¢s  z,HostKeys.lookup..SubDict.__getitem__cs\xV|jD]&}|jdkrq|jjƒ|kr||_PqWtˆg|ƒ}|jj|ƒ|jjj|ƒdS)N)rrrrrr5)rrÚvalr!)rrrÚ __setitem__¨s    z,HostKeys.lookup..SubDict.__setitem__cSsdd„|jDƒS)NcSs g|]}|jdk r|jjƒ‘qS)N)rr)Ú.0r!rrrú ¸sz9HostKeys.lookup..SubDict.keys..)r)rrrrr7¶sz%HostKeys.lookup..SubDict.keysN) Ú__name__Ú __module__Ú __qualname__rr9r:r=r>r@r7r)rrrÚSubDictŽs rFrN)rrÚ_hostname_matchesrr))rrrFr6r!r)rrÚlookupƒs /   zHostKeys.lookupcCsHxB|jD]8}||ks<|jdƒr|jdƒ rt|j||ƒ|ƒrdSqWdS)zl Tests whether ``hostname`` string matches given SubDict ``entry``. :returns bool: z|1|TF)rÚ startswithrÚ hash_host)rrÚentryr0rrrrGÅs   zHostKeys._hostname_matchescCsB|j|ƒ}|dkrdS|j|jƒdƒ}|dkr2dS|jƒ|jƒkS)a= Return True if the given key is associated with the given hostname in this dictionary. :param str hostname: hostname (or IP) of the SSH server :param .PKey key: the key to check :return: ``True`` if the key is associated with the hostname; else ``False`` NF)rHÚgetrZasbytes)rrrr8Zhost_keyrrrr+Õs zHostKeys.checkcCs g|_dS)z; Remove all host keys from the dictionary. N)r)rrrrÚclearçszHostKeys.clearccsx|jƒD] }|Vq WdS)N)r7)rr8rrrr9íszHostKeys.__iter__cCs t|jƒƒS)N)r)r7)rrrrr:ñszHostKeys.__len__cCs|j|ƒ}|dkrt|ƒ‚|S)N)rHr<)rrÚretrrrr>ôs zHostKeys.__getitem__cCsNd}x(t|jƒD]\}}|j||ƒr|}PqW|dkr>t|ƒ‚|jj|ƒdS)N)r'rrGr<Úpop)rrÚindexÚirKrrrr=ús zHostKeys.__delitem__cCs�t|ƒdkr$|jjt|gdƒƒdSxf|jƒD]Z}d}x4|jD]*}||jkr>|jjƒ|kr>|||_d}q>W|s.|jjt|g||ƒƒq.WdS)NrFT)r)rrrr7rrr)rrrKZkey_typeÚfoundr!rrrr@s   zHostKeys.__setitem__cCs:g}x0|jD]&}x |jD]}||kr|j|ƒqWq W|S)N)rrr)rrNr!r0rrrr7s   z HostKeys.keyscCs*g}x |jƒD]}|j|j|ƒƒqW|S)N)r7rrH)rrNr8rrrÚvaluesszHostKeys.valuescCsŒ|dkrtjtƒjƒ}n$|jdƒr0|jdƒd}tt|ƒƒ}t|ƒtƒjksPt ‚t |t|ƒtƒj ƒ}dj t t|ƒƒt t|ƒƒƒ}|jddƒS)aM Return a "hashed" form of the hostname, as used by OpenSSH when storing hashed hostnames in the known_hosts file. :param str hostname: the hostname to hash :param str salt: optional salt to use when hashing (must be 20 bytes long) :return: the hashed hostname as a `str` Nz|1|ú|rz|1|{}|{}Ú Ú)ÚosÚurandomrÚ digest_sizerIÚsplitr rr)ÚAssertionErrorrÚdigestÚformatrr Úreplace)rZsaltÚhmacZhostkeyrrrrJ"s   zHostKeys.hash_host)N)N)rCrDrEÚ__doc__rr"rr4rHrGr+rMr9r:r>r=r@r7rSÚ staticmethodrJrrrrr)s$   B  rc@seZdZdd„ZdS)ÚInvalidHostKeycCs||_||_||f|_dS)N)r/ÚexcÚargs)rr/rcrrrr:szInvalidHostKey.__init__N)rCrDrErrrrrrb9srbc@s8eZdZdZd dd„Zed dd„ƒZdd„Zd d „ZdS) rzJ Representation of a line in an OpenSSH-style "known hosts" file. NcCs"|dk o|dk |_||_||_dS)N)Úvalidrr)rrrrrrrEszHostKeyEntry.__init__c Cstdƒ}|jdƒ}t|ƒdkr8d}|j|j||ƒƒdS|dd…}|\}}}|jdƒ}y†t|ƒ}|dkrztt|ƒd�}nb|d kr’tt|ƒd�}nJ|t j ƒkr°t t|ƒd d �}n,|d krÈt t|ƒd�}n|jd j|ƒƒdSWn0t j k �r} zt|| ƒ‚WYdd} ~ XnX|||ƒS)aå Parses the given line of text to find the names for the host, the type of key, and the key data. The line is expected to be in the format used by the OpenSSH known_hosts file. Lines are expected to not have leading or trailing whitespace. We don't bother to check for comments or empty lines. All of that should be taken care of before sending the line to us. :param str line: a line from an OpenSSH known_hosts file zparamiko.hostkeysú rz8Not enough fields found in known_hosts in line {} ({!r})Nú,zssh-rsa)Údatazssh-dssF)rhZvalidate_pointz ssh-ed25519zUnable to handle key of type {})r rZr)Úinfor]rr r r rZ supported_key_format_identifiersrÚbinasciiÚErrorrb) Úclsr/r.ÚlogÚfieldsÚmsgÚnamesr rr!rrrr*Js0       zHostKeyEntry.from_linecCs,|jr(djdj|jƒ|jjƒ|jjƒƒSdS)z¦ Returns a string in OpenSSH known_hosts file format, or None if the object is not in a valid state. A trailing newline is included. z {} {} {} rgN)rer]ÚjoinrrrZ get_base64)rrrrr2xs   zHostKeyEntry.to_linecCsdj|j|jƒS)Nz)r]rr)rrrrÚ__repr__†szHostKeyEntry.__repr__)NN)N) rCrDrEr`rÚ classmethodr*r2rrrrrrr@s   -r)rr)!rjrWÚsysÚ version_infoÚcollections.abcrÚ collectionsÚhashlibrr_rZparamiko.py3compatrrr r Zparamiko.dsskeyr Zparamiko.rsakeyr Z paramiko.utilr rZparamiko.ecdsakeyrZparamiko.ed25519keyrZparamiko.ssh_exceptionrrÚ ExceptionrbrrrrrÚs&