1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 Implementation of an SSH2 "message".
21 """
22
23 import struct
24
25 from paramiko import util
26 from paramiko.common import zero_byte, max_byte, one_byte, asbytes
27 from paramiko.py3compat import long, BytesIO, u, integer_types
28
29
31 """
32 An SSH2 message is a stream of bytes that encodes some combination of
33 strings, integers, bools, and infinite-precision integers (known in Python
34 as longs). This class builds or breaks down such a byte stream.
35
36 Normally you don't need to deal with anything this low-level, but it's
37 exposed for people implementing custom extensions, or features that
38 paramiko doesn't support yet.
39 """
40
41 big_int = long(0xff000000)
42
44 """
45 Create a new SSH2 message.
46
47 :param str content:
48 the byte stream to use as the message content (passed in only when
49 decomposing a message).
50 """
51 if content is not None:
52 self.packet = BytesIO(content)
53 else:
54 self.packet = BytesIO()
55
57 """
58 Return the byte stream content of this message, as a string/bytes obj.
59 """
60 return self.asbytes()
61
63 """
64 Returns a string representation of this object, for debugging.
65 """
66 return 'paramiko.Message(' + repr(self.packet.getvalue()) + ')'
67
69 """
70 Return the byte stream content of this Message, as bytes.
71 """
72 return self.packet.getvalue()
73
75 """
76 Rewind the message to the beginning as if no items had been parsed
77 out of it yet.
78 """
79 self.packet.seek(0)
80
81 - def get_remainder(self):
82 """
83 Return the bytes (as a `str`) of this message that haven't already been
84 parsed and returned.
85 """
86 position = self.packet.tell()
87 remainder = self.packet.read()
88 self.packet.seek(position)
89 return remainder
90
92 """
93 Returns the `str` bytes of this message that have been parsed and
94 returned. The string passed into a message's constructor can be
95 regenerated by concatenating ``get_so_far`` and `get_remainder`.
96 """
97 position = self.packet.tell()
98 self.rewind()
99 return self.packet.read(position)
100
102 """
103 Return the next ``n`` bytes of the message (as a `str`), without
104 decomposing into an int, decoded string, etc. Just the raw bytes are
105 returned. Returns a string of ``n`` zero bytes if there weren't ``n``
106 bytes remaining in the message.
107 """
108 b = self.packet.read(n)
109 max_pad_size = 1 << 20
110 if len(b) < n < max_pad_size:
111 return b + zero_byte * (n - len(b))
112 return b
113
115 """
116 Return the next byte of the message, without decomposing it. This
117 is equivalent to `get_bytes(1) <get_bytes>`.
118
119 :return:
120 the next (`str`) byte of the message, or ``'\000'`` if there aren't
121 any bytes remaining.
122 """
123 return self.get_bytes(1)
124
126 """
127 Fetch a boolean from the stream.
128 """
129 b = self.get_bytes(1)
130 return b != zero_byte
131
133 """
134 Fetch an int from the stream.
135
136 :return: a 32-bit unsigned `int`.
137 """
138 byte = self.get_bytes(1)
139 if byte == max_byte:
140 return util.inflate_long(self.get_binary())
141 byte += self.get_bytes(3)
142 return struct.unpack('>I', byte)[0]
143
145 """
146 Fetch an int from the stream.
147
148 @return: a 32-bit unsigned integer.
149 @rtype: int
150 """
151 return struct.unpack('>I', self.get_bytes(4))[0]
152
154 """
155 Fetch a 64-bit int from the stream.
156
157 :return: a 64-bit unsigned integer (`long`).
158 """
159 return struct.unpack('>Q', self.get_bytes(8))[0]
160
162 """
163 Fetch a long int (mpint) from the stream.
164
165 :return: an arbitrary-length integer (`long`).
166 """
167 return util.inflate_long(self.get_binary())
168
170 """
171 Fetch a `str` from the stream. This could be a byte string and may
172 contain unprintable characters. (It's not unheard of for a string to
173 contain another byte-stream message.)
174 """
175 return self.get_bytes(self.get_size())
176
177 - def get_text(self):
178 """
179 Fetch a string from the stream. This could be a byte string and may
180 contain unprintable characters. (It's not unheard of for a string to
181 contain another byte-stream Message.)
182
183 @return: a string.
184 @rtype: string
185 """
186 return u(self.get_bytes(self.get_size()))
187
188
190 """
191 Fetch a string from the stream. This could be a byte string and may
192 contain unprintable characters. (It's not unheard of for a string to
193 contain another byte-stream Message.)
194
195 @return: a string.
196 @rtype: string
197 """
198 return self.get_bytes(self.get_size())
199
201 """
202 Fetch a `list` of `strings <str>` from the stream.
203
204 These are trivially encoded as comma-separated values in a string.
205 """
206 return self.get_text().split(',')
207
209 """
210 Write bytes to the stream, without any formatting.
211
212 :param str b: bytes to add
213 """
214 self.packet.write(b)
215 return self
216
218 """
219 Write a single byte to the stream, without any formatting.
220
221 :param str b: byte to add
222 """
223 self.packet.write(b)
224 return self
225
237
239 """
240 Add an integer to the stream.
241
242 :param int n: integer to add
243 """
244 self.packet.write(struct.pack('>I', n))
245 return self
246
259
261 """
262 Add a 64-bit int to the stream.
263
264 :param long n: long int to add
265 """
266 self.packet.write(struct.pack('>Q', n))
267 return self
268
270 """
271 Add a long int to the stream, encoded as an infinite-precision
272 integer. This method only works on positive numbers.
273
274 :param long z: long int to add
275 """
276 self.add_string(util.deflate_long(z))
277 return self
278
280 """
281 Add a string to the stream.
282
283 :param str s: string to add
284 """
285 s = asbytes(s)
286 self.add_size(len(s))
287 self.packet.write(s)
288 return self
289
291 """
292 Add a list of strings to the stream. They are encoded identically to
293 a single string of values separated by commas. (Yes, really, that's
294 how SSH2 does it.)
295
296 :param list l: list of strings to add
297 """
298 self.add_string(','.join(l))
299 return self
300
310
311 - def add(self, *seq):
312 """
313 Add a sequence of items to the stream. The values are encoded based
314 on their type: str, int, bool, list, or long.
315
316 .. warning::
317 Longs are encoded non-deterministically. Don't use this method.
318
319 :param seq: the sequence of items
320 """
321 for item in seq:
322 self._add(item)
323