message.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. # Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
  2. #
  3. # This file is part of paramiko.
  4. #
  5. # Paramiko is free software; you can redistribute it and/or modify it under the
  6. # terms of the GNU Lesser General Public License as published by the Free
  7. # Software Foundation; either version 2.1 of the License, or (at your option)
  8. # any later version.
  9. #
  10. # Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
  11. # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  13. # details.
  14. #
  15. # You should have received a copy of the GNU Lesser General Public License
  16. # along with Paramiko; if not, write to the Free Software Foundation, Inc.,
  17. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. """
  19. Implementation of an SSH2 "message".
  20. """
  21. import struct
  22. from paramiko import util
  23. from paramiko.common import zero_byte, max_byte, one_byte, asbytes
  24. from paramiko.py3compat import long, BytesIO, u, integer_types
  25. class Message(object):
  26. """
  27. An SSH2 message is a stream of bytes that encodes some combination of
  28. strings, integers, bools, and infinite-precision integers (known in Python
  29. as longs). This class builds or breaks down such a byte stream.
  30. Normally you don't need to deal with anything this low-level, but it's
  31. exposed for people implementing custom extensions, or features that
  32. paramiko doesn't support yet.
  33. """
  34. big_int = long(0xff000000)
  35. def __init__(self, content=None):
  36. """
  37. Create a new SSH2 message.
  38. :param str content:
  39. the byte stream to use as the message content (passed in only when
  40. decomposing a message).
  41. """
  42. if content is not None:
  43. self.packet = BytesIO(content)
  44. else:
  45. self.packet = BytesIO()
  46. def __str__(self):
  47. """
  48. Return the byte stream content of this message, as a string/bytes obj.
  49. """
  50. return self.asbytes()
  51. def __repr__(self):
  52. """
  53. Returns a string representation of this object, for debugging.
  54. """
  55. return "paramiko.Message(" + repr(self.packet.getvalue()) + ")"
  56. def asbytes(self):
  57. """
  58. Return the byte stream content of this Message, as bytes.
  59. """
  60. return self.packet.getvalue()
  61. def rewind(self):
  62. """
  63. Rewind the message to the beginning as if no items had been parsed
  64. out of it yet.
  65. """
  66. self.packet.seek(0)
  67. def get_remainder(self):
  68. """
  69. Return the bytes (as a `str`) of this message that haven't already been
  70. parsed and returned.
  71. """
  72. position = self.packet.tell()
  73. remainder = self.packet.read()
  74. self.packet.seek(position)
  75. return remainder
  76. def get_so_far(self):
  77. """
  78. Returns the `str` bytes of this message that have been parsed and
  79. returned. The string passed into a message's constructor can be
  80. regenerated by concatenating ``get_so_far`` and `get_remainder`.
  81. """
  82. position = self.packet.tell()
  83. self.rewind()
  84. return self.packet.read(position)
  85. def get_bytes(self, n):
  86. """
  87. Return the next ``n`` bytes of the message (as a `str`), without
  88. decomposing into an int, decoded string, etc. Just the raw bytes are
  89. returned. Returns a string of ``n`` zero bytes if there weren't ``n``
  90. bytes remaining in the message.
  91. """
  92. b = self.packet.read(n)
  93. max_pad_size = 1 << 20 # Limit padding to 1 MB
  94. if len(b) < n < max_pad_size:
  95. return b + zero_byte * (n - len(b))
  96. return b
  97. def get_byte(self):
  98. """
  99. Return the next byte of the message, without decomposing it. This
  100. is equivalent to `get_bytes(1) <get_bytes>`.
  101. :return:
  102. the next (`str`) byte of the message, or ``'\000'`` if there aren't
  103. any bytes remaining.
  104. """
  105. return self.get_bytes(1)
  106. def get_boolean(self):
  107. """
  108. Fetch a boolean from the stream.
  109. """
  110. b = self.get_bytes(1)
  111. return b != zero_byte
  112. def get_adaptive_int(self):
  113. """
  114. Fetch an int from the stream.
  115. :return: a 32-bit unsigned `int`.
  116. """
  117. byte = self.get_bytes(1)
  118. if byte == max_byte:
  119. return util.inflate_long(self.get_binary())
  120. byte += self.get_bytes(3)
  121. return struct.unpack(">I", byte)[0]
  122. def get_int(self):
  123. """
  124. Fetch an int from the stream.
  125. """
  126. return struct.unpack(">I", self.get_bytes(4))[0]
  127. def get_int64(self):
  128. """
  129. Fetch a 64-bit int from the stream.
  130. :return: a 64-bit unsigned integer (`long`).
  131. """
  132. return struct.unpack(">Q", self.get_bytes(8))[0]
  133. def get_mpint(self):
  134. """
  135. Fetch a long int (mpint) from the stream.
  136. :return: an arbitrary-length integer (`long`).
  137. """
  138. return util.inflate_long(self.get_binary())
  139. def get_string(self):
  140. """
  141. Fetch a `str` from the stream. This could be a byte string and may
  142. contain unprintable characters. (It's not unheard of for a string to
  143. contain another byte-stream message.)
  144. """
  145. return self.get_bytes(self.get_int())
  146. def get_text(self):
  147. """
  148. Fetch a Unicode string from the stream.
  149. """
  150. return u(self.get_string())
  151. def get_binary(self):
  152. """
  153. Fetch a string from the stream. This could be a byte string and may
  154. contain unprintable characters. (It's not unheard of for a string to
  155. contain another byte-stream Message.)
  156. """
  157. return self.get_bytes(self.get_int())
  158. def get_list(self):
  159. """
  160. Fetch a list of `strings <str>` from the stream.
  161. These are trivially encoded as comma-separated values in a string.
  162. """
  163. return self.get_text().split(",")
  164. def add_bytes(self, b):
  165. """
  166. Write bytes to the stream, without any formatting.
  167. :param str b: bytes to add
  168. """
  169. self.packet.write(b)
  170. return self
  171. def add_byte(self, b):
  172. """
  173. Write a single byte to the stream, without any formatting.
  174. :param str b: byte to add
  175. """
  176. self.packet.write(b)
  177. return self
  178. def add_boolean(self, b):
  179. """
  180. Add a boolean value to the stream.
  181. :param bool b: boolean value to add
  182. """
  183. if b:
  184. self.packet.write(one_byte)
  185. else:
  186. self.packet.write(zero_byte)
  187. return self
  188. def add_int(self, n):
  189. """
  190. Add an integer to the stream.
  191. :param int n: integer to add
  192. """
  193. self.packet.write(struct.pack(">I", n))
  194. return self
  195. def add_adaptive_int(self, n):
  196. """
  197. Add an integer to the stream.
  198. :param int n: integer to add
  199. """
  200. if n >= Message.big_int:
  201. self.packet.write(max_byte)
  202. self.add_string(util.deflate_long(n))
  203. else:
  204. self.packet.write(struct.pack(">I", n))
  205. return self
  206. def add_int64(self, n):
  207. """
  208. Add a 64-bit int to the stream.
  209. :param long n: long int to add
  210. """
  211. self.packet.write(struct.pack(">Q", n))
  212. return self
  213. def add_mpint(self, z):
  214. """
  215. Add a long int to the stream, encoded as an infinite-precision
  216. integer. This method only works on positive numbers.
  217. :param long z: long int to add
  218. """
  219. self.add_string(util.deflate_long(z))
  220. return self
  221. def add_string(self, s):
  222. """
  223. Add a string to the stream.
  224. :param str s: string to add
  225. """
  226. s = asbytes(s)
  227. self.add_int(len(s))
  228. self.packet.write(s)
  229. return self
  230. def add_list(self, l): # noqa: E741
  231. """
  232. Add a list of strings to the stream. They are encoded identically to
  233. a single string of values separated by commas. (Yes, really, that's
  234. how SSH2 does it.)
  235. :param l: list of strings to add
  236. """
  237. self.add_string(",".join(l))
  238. return self
  239. def _add(self, i):
  240. if type(i) is bool:
  241. return self.add_boolean(i)
  242. elif isinstance(i, integer_types):
  243. return self.add_adaptive_int(i)
  244. elif type(i) is list:
  245. return self.add_list(i)
  246. else:
  247. return self.add_string(i)
  248. def add(self, *seq):
  249. """
  250. Add a sequence of items to the stream. The values are encoded based
  251. on their type: str, int, bool, list, or long.
  252. .. warning::
  253. Longs are encoded non-deterministically. Don't use this method.
  254. :param seq: the sequence of items
  255. """
  256. for item in seq:
  257. self._add(item)