Even moar info fields

This commit is contained in:
Jeff Forcier 2014-02-26 12:55:58 -08:00
parent 79a69e88c3
commit 8ddaac24ae
2 changed files with 48 additions and 95 deletions

View File

@ -45,8 +45,7 @@ class HostKeys (UserDict.DictMixin):
Create a new HostKeys object, optionally loading keys from an OpenSSH Create a new HostKeys object, optionally loading keys from an OpenSSH
style host-key file. style host-key file.
:param filename: filename to load host keys from, or ``None`` :param str filename: filename to load host keys from, or ``None``
:type filename: str
""" """
# emulate a dict of { hostname: { keytype: PKey } } # emulate a dict of { hostname: { keytype: PKey } }
self._entries = [] self._entries = []
@ -58,12 +57,9 @@ class HostKeys (UserDict.DictMixin):
Add a host key entry to the table. Any existing entry for a Add a host key entry to the table. Any existing entry for a
``(hostname, keytype)`` pair will be replaced. ``(hostname, keytype)`` pair will be replaced.
:param hostname: the hostname (or IP) to add :param str hostname: the hostname (or IP) to add
:type hostname: str :param str keytype: key type (``"ssh-rsa"`` or ``"ssh-dss"``)
:param keytype: key type (``"ssh-rsa"`` or ``"ssh-dss"``) :param .PKey key: the key to add
:type keytype: str
:param key: the key to add
:type key: `.PKey`
""" """
for e in self._entries: for e in self._entries:
if (hostname in e.hostnames) and (e.key.get_name() == keytype): if (hostname in e.hostnames) and (e.key.get_name() == keytype):
@ -82,8 +78,7 @@ class HostKeys (UserDict.DictMixin):
not cleared. So multiple calls to `load` will just call `add`, not cleared. So multiple calls to `load` will just call `add`,
replacing any existing entries and adding new ones. replacing any existing entries and adding new ones.
:param filename: name of the file to read host keys from :param str filename: name of the file to read host keys from
:type filename: str
:raises IOError: if there was an error reading the file :raises IOError: if there was an error reading the file
""" """
@ -109,8 +104,7 @@ class HostKeys (UserDict.DictMixin):
loaded from a file originally). The single exception is that combined loaded from a file originally). The single exception is that combined
lines will be split into individual key lines, which is arguably a bug. lines will be split into individual key lines, which is arguably a bug.
:param filename: name of the file to write :param str filename: name of the file to write
:type filename: str
:raises IOError: if there was an error writing the file :raises IOError: if there was an error writing the file
@ -129,10 +123,8 @@ class HostKeys (UserDict.DictMixin):
``None`` is returned. Otherwise a dictionary of keytype to key is ``None`` is returned. Otherwise a dictionary of keytype to key is
returned. The keytype will be either ``"ssh-rsa"`` or ``"ssh-dss"``. returned. The keytype will be either ``"ssh-rsa"`` or ``"ssh-dss"``.
:param hostname: the hostname (or IP) to lookup :param str hostname: the hostname (or IP) to lookup
:type hostname: str :return: dict of `str` -> `.PKey` keys associated with this host (or ``None``)
:return: keys associated with this host (or ``None``)
:rtype: dict(str, `.PKey`)
""" """
class SubDict (UserDict.DictMixin): class SubDict (UserDict.DictMixin):
def __init__(self, hostname, entries, hostkeys): def __init__(self, hostname, entries, hostkeys):
@ -177,13 +169,10 @@ class HostKeys (UserDict.DictMixin):
Return True if the given key is associated with the given hostname Return True if the given key is associated with the given hostname
in this dictionary. in this dictionary.
:param hostname: hostname (or IP) of the SSH server :param str hostname: hostname (or IP) of the SSH server
:type hostname: str :param .PKey key: the key to check
:param key: the key to check :return:
:type key: `.PKey` ``True`` if the key is associated with the hostname; else ``False``
:return: ``True`` if the key is associated with the hostname; ``False``
if not
:rtype: bool
""" """
k = self.lookup(hostname) k = self.lookup(hostname)
if k is None: if k is None:
@ -240,12 +229,9 @@ class HostKeys (UserDict.DictMixin):
Return a "hashed" form of the hostname, as used by OpenSSH when storing Return a "hashed" form of the hostname, as used by OpenSSH when storing
hashed hostnames in the known_hosts file. hashed hostnames in the known_hosts file.
:param hostname: the hostname to hash :param str hostname: the hostname to hash
:type hostname: str :param str salt: optional salt to use when hashing (must be 20 bytes long)
:param salt: optional salt to use when hashing (must be 20 bytes long) :return: the hashed hostname as a `str`
:type salt: str
:return: the hashed hostname
:rtype: str
""" """
if salt is None: if salt is None:
salt = rng.read(SHA.digest_size) salt = rng.read(SHA.digest_size)
@ -287,8 +273,7 @@ class HostKeyEntry:
We don't bother to check for comments or empty lines. All of 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. that should be taken care of before sending the line to us.
:param line: a line from an OpenSSH known_hosts file :param str line: a line from an OpenSSH known_hosts file
:type line: str
""" """
log = get_logger('paramiko.hostkeys') log = get_logger('paramiko.hostkeys')
fields = line.split(' ') fields = line.split(' ')

View File

@ -41,9 +41,9 @@ class Message (object):
""" """
Create a new SSH2 message. Create a new SSH2 message.
:param content: the byte stream to use as the message content (passed :param str content:
in only when decomposing a message). the byte stream to use as the message content (passed in only when
:type content: string decomposing a message).
""" """
if content != None: if content != None:
self.packet = cStringIO.StringIO(content) self.packet = cStringIO.StringIO(content)
@ -53,17 +53,12 @@ class Message (object):
def __str__(self): def __str__(self):
""" """
Return the byte stream content of this message, as a string. Return the byte stream content of this message, as a string.
:return: the contents of this message.
:rtype: string
""" """
return self.packet.getvalue() return self.packet.getvalue()
def __repr__(self): def __repr__(self):
""" """
Returns a string representation of this object, for debugging. Returns a string representation of this object, for debugging.
:rtype: string
""" """
return 'paramiko.Message(' + repr(self.packet.getvalue()) + ')' return 'paramiko.Message(' + repr(self.packet.getvalue()) + ')'
@ -76,11 +71,8 @@ class Message (object):
def get_remainder(self): def get_remainder(self):
""" """
Return the bytes of this message that haven't already been parsed and Return the bytes (as a `str`) of this message that haven't already been
returned. parsed and returned.
:return: a string of the bytes not parsed yet.
:rtype: string
""" """
position = self.packet.tell() position = self.packet.tell()
remainder = self.packet.read() remainder = self.packet.read()
@ -89,12 +81,9 @@ class Message (object):
def get_so_far(self): def get_so_far(self):
""" """
Returns the bytes of this message that have been parsed and returned. Returns the `str` bytes of this message that have been parsed and
The string passed into a message's constructor can be regenerated by returned. The string passed into a message's constructor can be
concatenating ``get_so_far`` and `get_remainder`. regenerated by concatenating ``get_so_far`` and `get_remainder`.
:return: a string of the bytes parsed so far.
:rtype: string
""" """
position = self.packet.tell() position = self.packet.tell()
self.rewind() self.rewind()
@ -102,12 +91,10 @@ class Message (object):
def get_bytes(self, n): def get_bytes(self, n):
""" """
Return the next ``n`` bytes of the message, without decomposing into Return the next ``n`` bytes of the message (as a `str`), without
an int, string, etc. Just the raw bytes are returned. decomposing into an int, decoded string, etc. Just the raw bytes are
returned. Returns a string of ``n`` zero bytes if there weren't ``n``
:return: a string of the next ``n`` bytes of the message, or a string bytes remaining in the message.
of ``n`` zero bytes, if there aren't ``n`` bytes remaining.
:rtype: string
""" """
b = self.packet.read(n) b = self.packet.read(n)
max_pad_size = 1<<20 # Limit padding to 1 MB max_pad_size = 1<<20 # Limit padding to 1 MB
@ -120,18 +107,15 @@ class Message (object):
Return the next byte of the message, without decomposing it. This Return the next byte of the message, without decomposing it. This
is equivalent to `get_bytes(1) <get_bytes>`. is equivalent to `get_bytes(1) <get_bytes>`.
:return: the next byte of the message, or ``'\000'`` if there aren't :return:
the next (`str`) byte of the message, or ``'\000'`` if there aren't
any bytes remaining. any bytes remaining.
:rtype: string
""" """
return self.get_bytes(1) return self.get_bytes(1)
def get_boolean(self): def get_boolean(self):
""" """
Fetch a boolean from the stream. Fetch a boolean from the stream.
:return: ``True`` or ``False`` (from the message).
:rtype: bool
""" """
b = self.get_bytes(1) b = self.get_bytes(1)
return b != '\x00' return b != '\x00'
@ -140,8 +124,7 @@ class Message (object):
""" """
Fetch an int from the stream. Fetch an int from the stream.
:return: a 32-bit unsigned integer. :return: a 32-bit unsigned `int`.
:rtype: int
""" """
return struct.unpack('>I', self.get_bytes(4))[0] return struct.unpack('>I', self.get_bytes(4))[0]
@ -149,8 +132,7 @@ class Message (object):
""" """
Fetch a 64-bit int from the stream. Fetch a 64-bit int from the stream.
:return: a 64-bit unsigned integer. :return: a 64-bit unsigned integer (`long`).
:rtype: long
""" """
return struct.unpack('>Q', self.get_bytes(8))[0] return struct.unpack('>Q', self.get_bytes(8))[0]
@ -158,29 +140,23 @@ class Message (object):
""" """
Fetch a long int (mpint) from the stream. Fetch a long int (mpint) from the stream.
:return: an arbitrary-length integer. :return: an arbitrary-length integer (`long`).
:rtype: long
""" """
return util.inflate_long(self.get_string()) return util.inflate_long(self.get_string())
def get_string(self): def get_string(self):
""" """
Fetch a string from the stream. This could be a byte string and may Fetch a `str` from the stream. This could be a byte string and may
contain unprintable characters. (It's not unheard of for a string to contain unprintable characters. (It's not unheard of for a string to
contain another byte-stream message.) contain another byte-stream message.)
:return: a string.
:rtype: string
""" """
return self.get_bytes(self.get_int()) return self.get_bytes(self.get_int())
def get_list(self): def get_list(self):
""" """
Fetch a list of strings from the stream. These are trivially encoded Fetch a `list` of `strings <str>` from the stream.
as comma-separated values in a string.
These are trivially encoded as comma-separated values in a string.
:return: a list of strings.
:rtype: list of strings
""" """
return self.get_string().split(',') return self.get_string().split(',')
@ -188,8 +164,7 @@ class Message (object):
""" """
Write bytes to the stream, without any formatting. Write bytes to the stream, without any formatting.
:param b: bytes to add :param str b: bytes to add
:type b: str
""" """
self.packet.write(b) self.packet.write(b)
return self return self
@ -198,8 +173,7 @@ class Message (object):
""" """
Write a single byte to the stream, without any formatting. Write a single byte to the stream, without any formatting.
:param b: byte to add :param str b: byte to add
:type b: str
""" """
self.packet.write(b) self.packet.write(b)
return self return self
@ -208,8 +182,7 @@ class Message (object):
""" """
Add a boolean value to the stream. Add a boolean value to the stream.
:param b: boolean value to add :param bool b: boolean value to add
:type b: bool
""" """
if b: if b:
self.add_byte('\x01') self.add_byte('\x01')
@ -221,8 +194,7 @@ class Message (object):
""" """
Add an integer to the stream. Add an integer to the stream.
:param n: integer to add :param int n: integer to add
:type n: int
""" """
self.packet.write(struct.pack('>I', n)) self.packet.write(struct.pack('>I', n))
return self return self
@ -231,8 +203,7 @@ class Message (object):
""" """
Add a 64-bit int to the stream. Add a 64-bit int to the stream.
:param n: long int to add :param long n: long int to add
:type n: long
""" """
self.packet.write(struct.pack('>Q', n)) self.packet.write(struct.pack('>Q', n))
return self return self
@ -242,8 +213,7 @@ class Message (object):
Add a long int to the stream, encoded as an infinite-precision Add a long int to the stream, encoded as an infinite-precision
integer. This method only works on positive numbers. integer. This method only works on positive numbers.
:param z: long int to add :param long z: long int to add
:type z: long
""" """
self.add_string(util.deflate_long(z)) self.add_string(util.deflate_long(z))
return self return self
@ -252,8 +222,7 @@ class Message (object):
""" """
Add a string to the stream. Add a string to the stream.
:param s: string to add :param str s: string to add
:type s: str
""" """
self.add_int(len(s)) self.add_int(len(s))
self.packet.write(s) self.packet.write(s)
@ -265,8 +234,7 @@ class Message (object):
a single string of values separated by commas. (Yes, really, that's a single string of values separated by commas. (Yes, really, that's
how SSH2 does it.) how SSH2 does it.)
:param l: list of strings to add :param list l: list of strings to add
:type l: list(str)
""" """
self.add_string(','.join(l)) self.add_string(','.join(l))
return self return self
@ -292,11 +260,11 @@ class Message (object):
""" """
Add a sequence of items to the stream. The values are encoded based Add a sequence of items to the stream. The values are encoded based
on their type: str, int, bool, list, or long. on their type: str, int, bool, list, or long.
.. warning::
Longs are encoded non-deterministically. Don't use this method.
:param seq: the sequence of items :param seq: the sequence of items
:type seq: sequence
@bug: longs are encoded non-deterministically. Don't use this method.
""" """
for item in seq: for item in seq:
self._add(item) self._add(item)