1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 L{Transport} handles the core SSH2 protocol.
21 """
22
23 import os
24 import socket
25 import string
26 import struct
27 import sys
28 import threading
29 import time
30 import weakref
31
32 from paramiko import util
33 from paramiko.auth_handler import AuthHandler
34 from paramiko.channel import Channel
35 from paramiko.common import *
36 from paramiko.compress import ZlibCompressor, ZlibDecompressor
37 from paramiko.dsskey import DSSKey
38 from paramiko.kex_gex import KexGex
39 from paramiko.kex_group1 import KexGroup1
40 from paramiko.message import Message
41 from paramiko.packet import Packetizer, NeedRekeyException
42 from paramiko.primes import ModulusPack
43 from paramiko.rsakey import RSAKey
44 from paramiko.server import ServerInterface
45 from paramiko.sftp_client import SFTPClient
46 from paramiko.ssh_exception import SSHException, BadAuthenticationType, ChannelException
47
48
49
50
51
52
53 from Crypto.Cipher import Blowfish, AES, DES3
54 from Crypto.Hash import SHA, MD5
55
56
57
58 _active_threads = []
62 import atexit
63 atexit.register(_join_lingering_threads)
64
65
67 """
68 Simple object containing the security preferences of an ssh transport.
69 These are tuples of acceptable ciphers, digests, key types, and key
70 exchange algorithms, listed in order of preference.
71
72 Changing the contents and/or order of these fields affects the underlying
73 L{Transport} (but only if you change them before starting the session).
74 If you try to add an algorithm that paramiko doesn't recognize,
75 C{ValueError} will be raised. If you try to assign something besides a
76 tuple to one of the fields, C{TypeError} will be raised.
77 """
78 __slots__ = [ 'ciphers', 'digests', 'key_types', 'kex', 'compression', '_transport' ]
79
82
84 """
85 Returns a string representation of this object, for debugging.
86
87 @rtype: str
88 """
89 return '<paramiko.SecurityOptions for %s>' % repr(self._transport)
90
93
96
99
102
105
106 - def _set(self, name, orig, x):
107 if type(x) is list:
108 x = tuple(x)
109 if type(x) is not tuple:
110 raise TypeError('expected tuple or list')
111 possible = getattr(self._transport, orig).keys()
112 forbidden = filter(lambda n: n not in possible, x)
113 if len(forbidden) > 0:
114 raise ValueError('unknown cipher')
115 setattr(self._transport, name, x)
116
118 self._set('_preferred_ciphers', '_cipher_info', x)
119
121 self._set('_preferred_macs', '_mac_info', x)
122
124 self._set('_preferred_keys', '_key_info', x)
125
127 self._set('_preferred_kex', '_kex_info', x)
128
130 self._set('_preferred_compression', '_compression_info', x)
131
132 ciphers = property(_get_ciphers, _set_ciphers, None,
133 "Symmetric encryption ciphers")
134 digests = property(_get_digests, _set_digests, None,
135 "Digest (one-way hash) algorithms")
136 key_types = property(_get_key_types, _set_key_types, None,
137 "Public-key algorithms")
138 kex = property(_get_kex, _set_kex, None, "Key exchange algorithms")
139 compression = property(_get_compression, _set_compression, None,
140 "Compression algorithms")
141
142
145
146 self._map = weakref.WeakValueDictionary()
147 self._lock = threading.Lock()
148
149 - def put(self, chanid, chan):
150 self._lock.acquire()
151 try:
152 self._map[chanid] = chan
153 finally:
154 self._lock.release()
155
156 - def get(self, chanid):
157 self._lock.acquire()
158 try:
159 return self._map.get(chanid, None)
160 finally:
161 self._lock.release()
162
164 self._lock.acquire()
165 try:
166 try:
167 del self._map[chanid]
168 except KeyError:
169 pass
170 finally:
171 self._lock.release()
172
174 self._lock.acquire()
175 try:
176 return self._map.values()
177 finally:
178 self._lock.release()
179
181 self._lock.acquire()
182 try:
183 return len(self._map)
184 finally:
185 self._lock.release()
186
187
189 """
190 An SSH Transport attaches to a stream (usually a socket), negotiates an
191 encrypted session, authenticates, and then creates stream tunnels, called
192 L{Channel}s, across the session. Multiple channels can be multiplexed
193 across a single session (and often are, in the case of port forwardings).
194 """
195
196 _PROTO_ID = '2.0'
197 _CLIENT_ID = 'paramiko_1.7.4'
198
199 _preferred_ciphers = ( 'aes128-cbc', 'blowfish-cbc', 'aes256-cbc', '3des-cbc' )
200 _preferred_macs = ( 'hmac-sha1', 'hmac-md5', 'hmac-sha1-96', 'hmac-md5-96' )
201 _preferred_keys = ( 'ssh-rsa', 'ssh-dss' )
202 _preferred_kex = ( 'diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1' )
203 _preferred_compression = ( 'none', )
204
205 _cipher_info = {
206 'blowfish-cbc': { 'class': Blowfish, 'mode': Blowfish.MODE_CBC, 'block-size': 8, 'key-size': 16 },
207 'aes128-cbc': { 'class': AES, 'mode': AES.MODE_CBC, 'block-size': 16, 'key-size': 16 },
208 'aes256-cbc': { 'class': AES, 'mode': AES.MODE_CBC, 'block-size': 16, 'key-size': 32 },
209 '3des-cbc': { 'class': DES3, 'mode': DES3.MODE_CBC, 'block-size': 8, 'key-size': 24 },
210 }
211
212 _mac_info = {
213 'hmac-sha1': { 'class': SHA, 'size': 20 },
214 'hmac-sha1-96': { 'class': SHA, 'size': 12 },
215 'hmac-md5': { 'class': MD5, 'size': 16 },
216 'hmac-md5-96': { 'class': MD5, 'size': 12 },
217 }
218
219 _key_info = {
220 'ssh-rsa': RSAKey,
221 'ssh-dss': DSSKey,
222 }
223
224 _kex_info = {
225 'diffie-hellman-group1-sha1': KexGroup1,
226 'diffie-hellman-group-exchange-sha1': KexGex,
227 }
228
229 _compression_info = {
230
231
232
233 'zlib@openssh.com': ( ZlibCompressor, ZlibDecompressor ),
234 'zlib': ( ZlibCompressor, ZlibDecompressor ),
235 'none': ( None, None ),
236 }
237
238
239 _modulus_pack = None
240
242 """
243 Create a new SSH session over an existing socket, or socket-like
244 object. This only creates the Transport object; it doesn't begin the
245 SSH session yet. Use L{connect} or L{start_client} to begin a client
246 session, or L{start_server} to begin a server session.
247
248 If the object is not actually a socket, it must have the following
249 methods:
250 - C{send(str)}: Writes from 1 to C{len(str)} bytes, and
251 returns an int representing the number of bytes written. Returns
252 0 or raises C{EOFError} if the stream has been closed.
253 - C{recv(int)}: Reads from 1 to C{int} bytes and returns them as a
254 string. Returns 0 or raises C{EOFError} if the stream has been
255 closed.
256 - C{close()}: Closes the socket.
257 - C{settimeout(n)}: Sets a (float) timeout on I/O operations.
258
259 For ease of use, you may also pass in an address (as a tuple) or a host
260 string as the C{sock} argument. (A host string is a hostname with an
261 optional port (separated by C{":"}) which will be converted into a
262 tuple of C{(hostname, port)}.) A socket will be connected to this
263 address and used for communication. Exceptions from the C{socket} call
264 may be thrown in this case.
265
266 @param sock: a socket or socket-like object to create the session over.
267 @type sock: socket
268 """
269 if type(sock) is str:
270
271 hl = sock.split(':', 1)
272 if len(hl) == 1:
273 sock = (hl[0], 22)
274 else:
275 sock = (hl[0], int(hl[1]))
276 if type(sock) is tuple:
277
278 hostname, port = sock
279 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
280 sock.connect((hostname, port))
281
282 threading.Thread.__init__(self)
283 self.randpool = randpool
284 self.sock = sock
285
286 try:
287
288
289
290 self.sock.settimeout(0.1)
291 except AttributeError:
292 pass
293
294
295 self.packetizer = Packetizer(sock)
296 self.local_version = 'SSH-' + self._PROTO_ID + '-' + self._CLIENT_ID
297 self.remote_version = ''
298 self.local_cipher = self.remote_cipher = ''
299 self.local_kex_init = self.remote_kex_init = None
300 self.local_mac = self.remote_mac = None
301 self.local_compression = self.remote_compression = None
302 self.session_id = None
303 self.host_key_type = None
304 self.host_key = None
305
306
307 self.kex_engine = None
308 self.H = None
309 self.K = None
310
311 self.active = False
312 self.initial_kex_done = False
313 self.in_kex = False
314 self.authenticated = False
315 self._expected_packet = tuple()
316 self.lock = threading.Lock()
317
318
319 self._channels = ChannelMap()
320 self.channel_events = { }
321 self.channels_seen = { }
322 self._channel_counter = 1
323 self.window_size = 65536
324 self.max_packet_size = 34816
325 self._x11_handler = None
326 self._tcp_handler = None
327
328 self.saved_exception = None
329 self.clear_to_send = threading.Event()
330 self.clear_to_send_lock = threading.Lock()
331 self.log_name = 'paramiko.transport'
332 self.logger = util.get_logger(self.log_name)
333 self.packetizer.set_log(self.logger)
334 self.auth_handler = None
335 self.global_response = None
336 self.completion_event = None
337 self.banner_timeout = 15
338
339
340 self.server_mode = False
341 self.server_object = None
342 self.server_key_dict = { }
343 self.server_accepts = [ ]
344 self.server_accept_cv = threading.Condition(self.lock)
345 self.subsystem_table = { }
346
348 """
349 Returns a string representation of this object, for debugging.
350
351 @rtype: str
352 """
353 out = '<paramiko.Transport at %s' % hex(long(id(self)) & 0xffffffffL)
354 if not self.active:
355 out += ' (unconnected)'
356 else:
357 if self.local_cipher != '':
358 out += ' (cipher %s, %d bits)' % (self.local_cipher,
359 self._cipher_info[self.local_cipher]['key-size'] * 8)
360 if self.is_authenticated():
361 out += ' (active; %d open channel(s))' % len(self._channels)
362 elif self.initial_kex_done:
363 out += ' (connected; awaiting auth)'
364 else:
365 out += ' (connecting)'
366 out += '>'
367 return out
368
370 """
371 Terminate this Transport without closing the session. On posix
372 systems, if a Transport is open during process forking, both parent
373 and child will share the underlying socket, but only one process can
374 use the connection (without corrupting the session). Use this method
375 to clean up a Transport object without disrupting the other process.
376
377 @since: 1.5.3
378 """
379 self.sock.close()
380 self.close()
381
383 """
384 Return a L{SecurityOptions} object which can be used to tweak the
385 encryption algorithms this transport will permit, and the order of
386 preference for them.
387
388 @return: an object that can be used to change the preferred algorithms
389 for encryption, digest (hash), public key, and key exchange.
390 @rtype: L{SecurityOptions}
391 """
392 return SecurityOptions(self)
393
395 """
396 Negotiate a new SSH2 session as a client. This is the first step after
397 creating a new L{Transport}. A separate thread is created for protocol
398 negotiation.
399
400 If an event is passed in, this method returns immediately. When
401 negotiation is done (successful or not), the given C{Event} will
402 be triggered. On failure, L{is_active} will return C{False}.
403
404 (Since 1.4) If C{event} is C{None}, this method will not return until
405 negotation is done. On success, the method returns normally.
406 Otherwise an SSHException is raised.
407
408 After a successful negotiation, you will usually want to authenticate,
409 calling L{auth_password <Transport.auth_password>} or
410 L{auth_publickey <Transport.auth_publickey>}.
411
412 @note: L{connect} is a simpler method for connecting as a client.
413
414 @note: After calling this method (or L{start_server} or L{connect}),
415 you should no longer directly read from or write to the original
416 socket object.
417
418 @param event: an event to trigger when negotiation is complete
419 (optional)
420 @type event: threading.Event
421
422 @raise SSHException: if negotiation fails (and no C{event} was passed
423 in)
424 """
425 self.active = True
426 if event is not None:
427
428 self.completion_event = event
429 self.start()
430 return
431
432
433 self.completion_event = event = threading.Event()
434 self.start()
435 while True:
436 event.wait(0.1)
437 if not self.active:
438 e = self.get_exception()
439 if e is not None:
440 raise e
441 raise SSHException('Negotiation failed.')
442 if event.isSet():
443 break
444
446 """
447 Negotiate a new SSH2 session as a server. This is the first step after
448 creating a new L{Transport} and setting up your server host key(s). A
449 separate thread is created for protocol negotiation.
450
451 If an event is passed in, this method returns immediately. When
452 negotiation is done (successful or not), the given C{Event} will
453 be triggered. On failure, L{is_active} will return C{False}.
454
455 (Since 1.4) If C{event} is C{None}, this method will not return until
456 negotation is done. On success, the method returns normally.
457 Otherwise an SSHException is raised.
458
459 After a successful negotiation, the client will need to authenticate.
460 Override the methods
461 L{get_allowed_auths <ServerInterface.get_allowed_auths>},
462 L{check_auth_none <ServerInterface.check_auth_none>},
463 L{check_auth_password <ServerInterface.check_auth_password>}, and
464 L{check_auth_publickey <ServerInterface.check_auth_publickey>} in the
465 given C{server} object to control the authentication process.
466
467 After a successful authentication, the client should request to open
468 a channel. Override
469 L{check_channel_request <ServerInterface.check_channel_request>} in the
470 given C{server} object to allow channels to be opened.
471
472 @note: After calling this method (or L{start_client} or L{connect}),
473 you should no longer directly read from or write to the original
474 socket object.
475
476 @param event: an event to trigger when negotiation is complete.
477 @type event: threading.Event
478 @param server: an object used to perform authentication and create
479 L{Channel}s.
480 @type server: L{server.ServerInterface}
481
482 @raise SSHException: if negotiation fails (and no C{event} was passed
483 in)
484 """
485 if server is None:
486 server = ServerInterface()
487 self.server_mode = True
488 self.server_object = server
489 self.active = True
490 if event is not None:
491
492 self.completion_event = event
493 self.start()
494 return
495
496
497 self.completion_event = event = threading.Event()
498 self.start()
499 while True:
500 event.wait(0.1)
501 if not self.active:
502 e = self.get_exception()
503 if e is not None:
504 raise e
505 raise SSHException('Negotiation failed.')
506 if event.isSet():
507 break
508
510 """
511 Add a host key to the list of keys used for server mode. When behaving
512 as a server, the host key is used to sign certain packets during the
513 SSH2 negotiation, so that the client can trust that we are who we say
514 we are. Because this is used for signing, the key must contain private
515 key info, not just the public half. Only one key of each type (RSA or
516 DSS) is kept.
517
518 @param key: the host key to add, usually an L{RSAKey <rsakey.RSAKey>} or
519 L{DSSKey <dsskey.DSSKey>}.
520 @type key: L{PKey <pkey.PKey>}
521 """
522 self.server_key_dict[key.get_name()] = key
523
525 """
526 Return the active host key, in server mode. After negotiating with the
527 client, this method will return the negotiated host key. If only one
528 type of host key was set with L{add_server_key}, that's the only key
529 that will ever be returned. But in cases where you have set more than
530 one type of host key (for example, an RSA key and a DSS key), the key
531 type will be negotiated by the client, and this method will return the
532 key of the type agreed on. If the host key has not been negotiated
533 yet, C{None} is returned. In client mode, the behavior is undefined.
534
535 @return: host key of the type negotiated by the client, or C{None}.
536 @rtype: L{PKey <pkey.PKey>}
537 """
538 try:
539 return self.server_key_dict[self.host_key_type]
540 except KeyError:
541 pass
542 return None
543
545 """
546 I{(optional)}
547 Load a file of prime moduli for use in doing group-exchange key
548 negotiation in server mode. It's a rather obscure option and can be
549 safely ignored.
550
551 In server mode, the remote client may request "group-exchange" key
552 negotiation, which asks the server to send a random prime number that
553 fits certain criteria. These primes are pretty difficult to compute,
554 so they can't be generated on demand. But many systems contain a file
555 of suitable primes (usually named something like C{/etc/ssh/moduli}).
556 If you call C{load_server_moduli} and it returns C{True}, then this
557 file of primes has been loaded and we will support "group-exchange" in
558 server mode. Otherwise server mode will just claim that it doesn't
559 support that method of key negotiation.
560
561 @param filename: optional path to the moduli file, if you happen to
562 know that it's not in a standard location.
563 @type filename: str
564 @return: True if a moduli file was successfully loaded; False
565 otherwise.
566 @rtype: bool
567
568 @note: This has no effect when used in client mode.
569 """
570 Transport._modulus_pack = ModulusPack(randpool)
571
572 file_list = [ '/etc/ssh/moduli', '/usr/local/etc/moduli' ]
573 if filename is not None:
574 file_list.insert(0, filename)
575 for fn in file_list:
576 try:
577 Transport._modulus_pack.read_file(fn)
578 return True
579 except IOError:
580 pass
581
582 Transport._modulus_pack = None
583 return False
584 load_server_moduli = staticmethod(load_server_moduli)
585
587 """
588 Close this session, and any open channels that are tied to it.
589 """
590 if not self.active:
591 return
592 self.active = False
593 self.packetizer.close()
594 self.join()
595 for chan in self._channels.values():
596 chan._unlink()
597
599 """
600 Return the host key of the server (in client mode).
601
602 @note: Previously this call returned a tuple of (key type, key string).
603 You can get the same effect by calling
604 L{PKey.get_name <pkey.PKey.get_name>} for the key type, and
605 C{str(key)} for the key string.
606
607 @raise SSHException: if no session is currently active.
608
609 @return: public key of the remote server
610 @rtype: L{PKey <pkey.PKey>}
611 """
612 if (not self.active) or (not self.initial_kex_done):
613 raise SSHException('No existing session')
614 return self.host_key
615
617 """
618 Return true if this session is active (open).
619
620 @return: True if the session is still active (open); False if the
621 session is closed
622 @rtype: bool
623 """
624 return self.active
625
627 """
628 Request a new channel to the server, of type C{"session"}. This
629 is just an alias for C{open_channel('session')}.
630
631 @return: a new L{Channel}
632 @rtype: L{Channel}
633
634 @raise SSHException: if the request is rejected or the session ends
635 prematurely
636 """
637 return self.open_channel('session')
638
640 """
641 Request a new channel to the client, of type C{"x11"}. This
642 is just an alias for C{open_channel('x11', src_addr=src_addr)}.
643
644 @param src_addr: the source address of the x11 server (port is the
645 x11 port, ie. 6010)
646 @type src_addr: (str, int)
647 @return: a new L{Channel}
648 @rtype: L{Channel}
649
650 @raise SSHException: if the request is rejected or the session ends
651 prematurely
652 """
653 return self.open_channel('x11', src_addr=src_addr)
654
656 """
657 Request a new channel back to the client, of type C{"forwarded-tcpip"}.
658 This is used after a client has requested port forwarding, for sending
659 incoming connections back to the client.
660
661 @param src_addr: originator's address
662 @param src_port: originator's port
663 @param dest_addr: local (server) connected address
664 @param dest_port: local (server) connected port
665 """
666 return self.open_channel('forwarded-tcpip', (dest_addr, dest_port), (src_addr, src_port))
667
668 - def open_channel(self, kind, dest_addr=None, src_addr=None):
669 """
670 Request a new channel to the server. L{Channel}s are socket-like
671 objects used for the actual transfer of data across the session.
672 You may only request a channel after negotiating encryption (using
673 L{connect} or L{start_client}) and authenticating.
674
675 @param kind: the kind of channel requested (usually C{"session"},
676 C{"forwarded-tcpip"}, C{"direct-tcpip"}, or C{"x11"})
677 @type kind: str
678 @param dest_addr: the destination address of this port forwarding,
679 if C{kind} is C{"forwarded-tcpip"} or C{"direct-tcpip"} (ignored
680 for other channel types)
681 @type dest_addr: (str, int)
682 @param src_addr: the source address of this port forwarding, if
683 C{kind} is C{"forwarded-tcpip"}, C{"direct-tcpip"}, or C{"x11"}
684 @type src_addr: (str, int)
685 @return: a new L{Channel} on success
686 @rtype: L{Channel}
687
688 @raise SSHException: if the request is rejected or the session ends
689 prematurely
690 """
691 chan = None
692 if not self.active:
693
694 return None
695 self.lock.acquire()
696 try:
697 chanid = self._next_channel()
698 m = Message()
699 m.add_byte(chr(MSG_CHANNEL_OPEN))
700 m.add_string(kind)
701 m.add_int(chanid)
702 m.add_int(self.window_size)
703 m.add_int(self.max_packet_size)
704 if (kind == 'forwarded-tcpip') or (kind == 'direct-tcpip'):
705 m.add_string(dest_addr[0])
706 m.add_int(dest_addr[1])
707 m.add_string(src_addr[0])
708 m.add_int(src_addr[1])
709 elif kind == 'x11':
710 m.add_string(src_addr[0])
711 m.add_int(src_addr[1])
712 chan = Channel(chanid)
713 self._channels.put(chanid, chan)
714 self.channel_events[chanid] = event = threading.Event()
715 self.channels_seen[chanid] = True
716 chan._set_transport(self)
717 chan._set_window(self.window_size, self.max_packet_size)
718 finally:
719 self.lock.release()
720 self._send_user_message(m)
721 while True:
722 event.wait(0.1);
723 if not self.active:
724 e = self.get_exception()
725 if e is None:
726 e = SSHException('Unable to open channel.')
727 raise e
728 if event.isSet():
729 break
730 chan = self._channels.get(chanid)
731 if chan is not None:
732 return chan
733 e = self.get_exception()
734 if e is None:
735 e = SSHException('Unable to open channel.')
736 raise e
737
739 """
740 Ask the server to forward TCP connections from a listening port on
741 the server, across this SSH session.
742
743 If a handler is given, that handler is called from a different thread
744 whenever a forwarded connection arrives. The handler parameters are::
745
746 handler(channel, (origin_addr, origin_port), (server_addr, server_port))
747
748 where C{server_addr} and C{server_port} are the address and port that
749 the server was listening on.
750
751 If no handler is set, the default behavior is to send new incoming
752 forwarded connections into the accept queue, to be picked up via
753 L{accept}.
754
755 @param address: the address to bind when forwarding
756 @type address: str
757 @param port: the port to forward, or 0 to ask the server to allocate
758 any port
759 @type port: int
760 @param handler: optional handler for incoming forwarded connections
761 @type handler: function(Channel, (str, int), (str, int))
762 @return: the port # allocated by the server
763 @rtype: int
764
765 @raise SSHException: if the server refused the TCP forward request
766 """
767 if not self.active:
768 raise SSHException('SSH session not active')
769 address = str(address)
770 port = int(port)
771 response = self.global_request('tcpip-forward', (address, port), wait=True)
772 if response is None:
773 raise SSHException('TCP forwarding request denied')
774 if port == 0:
775 port = response.get_int()
776 if handler is None:
777 def default_handler(channel, (src_addr, src_port), (dest_addr, dest_port)):
778 self._queue_incoming_channel(channel)
779 handler = default_handler
780 self._tcp_handler = handler
781 return port
782
784 """
785 Ask the server to cancel a previous port-forwarding request. No more
786 connections to the given address & port will be forwarded across this
787 ssh connection.
788
789 @param address: the address to stop forwarding
790 @type address: str
791 @param port: the port to stop forwarding
792 @type port: int
793 """
794 if not self.active:
795 return
796 self._tcp_handler = None
797 self.global_request('cancel-tcpip-forward', (address, port), wait=True)
798
800 """
801 Create an SFTP client channel from an open transport. On success,
802 an SFTP session will be opened with the remote host, and a new
803 SFTPClient object will be returned.
804
805 @return: a new L{SFTPClient} object, referring to an sftp session
806 (channel) across this transport
807 @rtype: L{SFTPClient}
808 """
809 return SFTPClient.from_transport(self)
810
812 """
813 Send a junk packet across the encrypted link. This is sometimes used
814 to add "noise" to a connection to confuse would-be attackers. It can
815 also be used as a keep-alive for long lived connections traversing
816 firewalls.
817
818 @param bytes: the number of random bytes to send in the payload of the
819 ignored packet -- defaults to a random number from 10 to 41.
820 @type bytes: int
821 """
822 m = Message()
823 m.add_byte(chr(MSG_IGNORE))
824 randpool.stir()
825 if bytes is None:
826 bytes = (ord(randpool.get_bytes(1)) % 32) + 10
827 m.add_bytes(randpool.get_bytes(bytes))
828 self._send_user_message(m)
829
831 """
832 Force this session to switch to new keys. Normally this is done
833 automatically after the session hits a certain number of packets or
834 bytes sent or received, but this method gives you the option of forcing
835 new keys whenever you want. Negotiating new keys causes a pause in
836 traffic both ways as the two sides swap keys and do computations. This
837 method returns when the session has switched to new keys.
838
839 @raise SSHException: if the key renegotiation failed (which causes the
840 session to end)
841 """
842 self.completion_event = threading.Event()
843 self._send_kex_init()
844 while True:
845 self.completion_event.wait(0.1)
846 if not self.active:
847 e = self.get_exception()
848 if e is not None:
849 raise e
850 raise SSHException('Negotiation failed.')
851 if self.completion_event.isSet():
852 break
853 return
854
856 """
857 Turn on/off keepalive packets (default is off). If this is set, after
858 C{interval} seconds without sending any data over the connection, a
859 "keepalive" packet will be sent (and ignored by the remote host). This
860 can be useful to keep connections alive over a NAT, for example.
861
862 @param interval: seconds to wait before sending a keepalive packet (or
863 0 to disable keepalives).
864 @type interval: int
865 """
866 self.packetizer.set_keepalive(interval,
867 lambda x=weakref.proxy(self): x.global_request('keepalive@lag.net', wait=False))
868
870 """
871 Make a global request to the remote host. These are normally
872 extensions to the SSH2 protocol.
873
874 @param kind: name of the request.
875 @type kind: str
876 @param data: an optional tuple containing additional data to attach
877 to the request.
878 @type data: tuple
879 @param wait: C{True} if this method should not return until a response
880 is received; C{False} otherwise.
881 @type wait: bool
882 @return: a L{Message} containing possible additional data if the
883 request was successful (or an empty L{Message} if C{wait} was
884 C{False}); C{None} if the request was denied.
885 @rtype: L{Message}
886 """
887 if wait:
888 self.completion_event = threading.Event()
889 m = Message()
890 m.add_byte(chr(MSG_GLOBAL_REQUEST))
891 m.add_string(kind)
892 m.add_boolean(wait)
893 if data is not None:
894 m.add(*data)
895 self._log(DEBUG, 'Sending global request "%s"' % kind)
896 self._send_user_message(m)
897 if not wait:
898 return None
899 while True:
900 self.completion_event.wait(0.1)
901 if not self.active:
902 return None
903 if self.completion_event.isSet():
904 break
905 return self.global_response
906
907 - def accept(self, timeout=None):
908 """
909 Return the next channel opened by the client over this transport, in
910 server mode. If no channel is opened before the given timeout, C{None}
911 is returned.
912
913 @param timeout: seconds to wait for a channel, or C{None} to wait
914 forever
915 @type timeout: int
916 @return: a new Channel opened by the client
917 @rtype: L{Channel}
918 """
919 self.lock.acquire()
920 try:
921 if len(self.server_accepts) > 0:
922 chan = self.server_accepts.pop(0)
923 else:
924 self.server_accept_cv.wait(timeout)
925 if len(self.server_accepts) > 0:
926 chan = self.server_accepts.pop(0)
927 else:
928
929 chan = None
930 finally:
931 self.lock.release()
932 return chan
933
934 - def connect(self, hostkey=None, username='', password=None, pkey=None):
935 """
936 Negotiate an SSH2 session, and optionally verify the server's host key
937 and authenticate using a password or private key. This is a shortcut
938 for L{start_client}, L{get_remote_server_key}, and
939 L{Transport.auth_password} or L{Transport.auth_publickey}. Use those
940 methods if you want more control.
941
942 You can use this method immediately after creating a Transport to
943 negotiate encryption with a server. If it fails, an exception will be
944 thrown. On success, the method will return cleanly, and an encrypted
945 session exists. You may immediately call L{open_channel} or
946 L{open_session} to get a L{Channel} object, which is used for data
947 transfer.
948
949 @note: If you fail to supply a password or private key, this method may
950 succeed, but a subsequent L{open_channel} or L{open_session} call may
951 fail because you haven't authenticated yet.
952
953 @param hostkey: the host key expected from the server, or C{None} if
954 you don't want to do host key verification.
955 @type hostkey: L{PKey<pkey.PKey>}
956 @param username: the username to authenticate as.
957 @type username: str
958 @param password: a password to use for authentication, if you want to
959 use password authentication; otherwise C{None}.
960 @type password: str
961 @param pkey: a private key to use for authentication, if you want to
962 use private key authentication; otherwise C{None}.
963 @type pkey: L{PKey<pkey.PKey>}
964
965 @raise SSHException: if the SSH2 negotiation fails, the host key
966 supplied by the server is incorrect, or authentication fails.
967 """
968 if hostkey is not None:
969 self._preferred_keys = [ hostkey.get_name() ]
970
971 self.start_client()
972
973
974 if (hostkey is not None):
975 key = self.get_remote_server_key()
976 if (key.get_name() != hostkey.get_name()) or (str(key) != str(hostkey)):
977 self._log(DEBUG, 'Bad host key from server')
978 self._log(DEBUG, 'Expected: %s: %s' % (hostkey.get_name(), repr(str(hostkey))))
979 self._log(DEBUG, 'Got : %s: %s' % (key.get_name(), repr(str(key))))
980 raise SSHException('Bad host key from server')
981 self._log(DEBUG, 'Host key verified (%s)' % hostkey.get_name())
982
983 if (pkey is not None) or (password is not None):
984 if password is not None:
985 self._log(DEBUG, 'Attempting password auth...')
986 self.auth_password(username, password)
987 else:
988 self._log(DEBUG, 'Attempting public-key auth...')
989 self.auth_publickey(username, pkey)
990
991 return
992
994 """
995 Return any exception that happened during the last server request.
996 This can be used to fetch more specific error information after using
997 calls like L{start_client}. The exception (if any) is cleared after
998 this call.
999
1000 @return: an exception, or C{None} if there is no stored exception.
1001 @rtype: Exception
1002
1003 @since: 1.1
1004 """
1005 self.lock.acquire()
1006 try:
1007 e = self.saved_exception
1008 self.saved_exception = None
1009 return e
1010 finally:
1011 self.lock.release()
1012
1014 """
1015 Set the handler class for a subsystem in server mode. If a request
1016 for this subsystem is made on an open ssh channel later, this handler
1017 will be constructed and called -- see L{SubsystemHandler} for more
1018 detailed documentation.
1019
1020 Any extra parameters (including keyword arguments) are saved and
1021 passed to the L{SubsystemHandler} constructor later.
1022
1023 @param name: name of the subsystem.
1024 @type name: str
1025 @param handler: subclass of L{SubsystemHandler} that handles this
1026 subsystem.
1027 @type handler: class
1028 """
1029 try:
1030 self.lock.acquire()
1031 self.subsystem_table[name] = (handler, larg, kwarg)
1032 finally:
1033 self.lock.release()
1034
1036 """
1037 Return true if this session is active and authenticated.
1038
1039 @return: True if the session is still open and has been authenticated
1040 successfully; False if authentication failed and/or the session is
1041 closed.
1042 @rtype: bool
1043 """
1044 return self.active and (self.auth_handler is not None) and self.auth_handler.is_authenticated()
1045
1047 """
1048 Return the username this connection is authenticated for. If the
1049 session is not authenticated (or authentication failed), this method
1050 returns C{None}.
1051
1052 @return: username that was authenticated, or C{None}.
1053 @rtype: string
1054 """
1055 if not self.active or (self.auth_handler is None):
1056 return None
1057 return self.auth_handler.get_username()
1058
1060 """
1061 Try to authenticate to the server using no authentication at all.
1062 This will almost always fail. It may be useful for determining the
1063 list of authentication types supported by the server, by catching the
1064 L{BadAuthenticationType} exception raised.
1065
1066 @param username: the username to authenticate as
1067 @type username: string
1068 @return: list of auth types permissible for the next stage of
1069 authentication (normally empty)
1070 @rtype: list
1071
1072 @raise BadAuthenticationType: if "none" authentication isn't allowed
1073 by the server for this user
1074 @raise SSHException: if the authentication failed due to a network
1075 error
1076
1077 @since: 1.5
1078 """
1079 if (not self.active) or (not self.initial_kex_done):
1080 raise SSHException('No existing session')
1081 my_event = threading.Event()
1082 self.auth_handler = AuthHandler(self)
1083 self.auth_handler.auth_none(username, my_event)
1084 return self.auth_handler.wait_for_response(my_event)
1085
1086 - def auth_password(self, username, password, event=None, fallback=True):
1087 """
1088 Authenticate to the server using a password. The username and password
1089 are sent over an encrypted link.
1090
1091 If an C{event} is passed in, this method will return immediately, and
1092 the event will be triggered once authentication succeeds or fails. On
1093 success, L{is_authenticated} will return C{True}. On failure, you may
1094 use L{get_exception} to get more detailed error information.
1095
1096 Since 1.1, if no event is passed, this method will block until the
1097 authentication succeeds or fails. On failure, an exception is raised.
1098 Otherwise, the method simply returns.
1099
1100 Since 1.5, if no event is passed and C{fallback} is C{True} (the
1101 default), if the server doesn't support plain password authentication
1102 but does support so-called "keyboard-interactive" mode, an attempt
1103 will be made to authenticate using this interactive mode. If it fails,
1104 the normal exception will be thrown as if the attempt had never been
1105 made. This is useful for some recent Gentoo and Debian distributions,
1106 which turn off plain password authentication in a misguided belief
1107 that interactive authentication is "more secure". (It's not.)
1108
1109 If the server requires multi-step authentication (which is very rare),
1110 this method will return a list of auth types permissible for the next
1111 step. Otherwise, in the normal case, an empty list is returned.
1112
1113 @param username: the username to authenticate as
1114 @type username: str
1115 @param password: the password to authenticate with
1116 @type password: str or unicode
1117 @param event: an event to trigger when the authentication attempt is
1118 complete (whether it was successful or not)
1119 @type event: threading.Event
1120 @param fallback: C{True} if an attempt at an automated "interactive"
1121 password auth should be made if the server doesn't support normal
1122 password auth
1123 @type fallback: bool
1124 @return: list of auth types permissible for the next stage of
1125 authentication (normally empty)
1126 @rtype: list
1127
1128 @raise BadAuthenticationType: if password authentication isn't
1129 allowed by the server for this user (and no event was passed in)
1130 @raise AuthenticationException: if the authentication failed (and no
1131 event was passed in)
1132 @raise SSHException: if there was a network error
1133 """
1134 if (not self.active) or (not self.initial_kex_done):
1135
1136 raise SSHException('No existing session')
1137 if event is None:
1138 my_event = threading.Event()
1139 else:
1140 my_event = event
1141 self.auth_handler = AuthHandler(self)
1142 self.auth_handler.auth_password(username, password, my_event)
1143 if event is not None:
1144
1145 return []
1146 try:
1147 return self.auth_handler.wait_for_response(my_event)
1148 except BadAuthenticationType, x:
1149
1150 if not fallback or ('keyboard-interactive' not in x.allowed_types):
1151 raise
1152 try:
1153 def handler(title, instructions, fields):
1154 if len(fields) > 1:
1155 raise SSHException('Fallback authentication failed.')
1156 if len(fields) == 0:
1157
1158
1159
1160
1161 return []
1162 return [ password ]
1163 return self.auth_interactive(username, handler)
1164 except SSHException, ignored:
1165
1166 raise x
1167 return None
1168
1170 """
1171 Authenticate to the server using a private key. The key is used to
1172 sign data from the server, so it must include the private part.
1173
1174 If an C{event} is passed in, this method will return immediately, and
1175 the event will be triggered once authentication succeeds or fails. On
1176 success, L{is_authenticated} will return C{True}. On failure, you may
1177 use L{get_exception} to get more detailed error information.
1178
1179 Since 1.1, if no event is passed, this method will block until the
1180 authentication succeeds or fails. On failure, an exception is raised.
1181 Otherwise, the method simply returns.
1182
1183 If the server requires multi-step authentication (which is very rare),
1184 this method will return a list of auth types permissible for the next
1185 step. Otherwise, in the normal case, an empty list is returned.
1186
1187 @param username: the username to authenticate as
1188 @type username: string
1189 @param key: the private key to authenticate with
1190 @type key: L{PKey <pkey.PKey>}
1191 @param event: an event to trigger when the authentication attempt is
1192 complete (whether it was successful or not)
1193 @type event: threading.Event
1194 @return: list of auth types permissible for the next stage of
1195 authentication (normally empty)
1196 @rtype: list
1197
1198 @raise BadAuthenticationType: if public-key authentication isn't
1199 allowed by the server for this user (and no event was passed in)
1200 @raise AuthenticationException: if the authentication failed (and no
1201 event was passed in)
1202 @raise SSHException: if there was a network error
1203 """
1204 if (not self.active) or (not self.initial_kex_done):
1205
1206 raise SSHException('No existing session')
1207 if event is None:
1208 my_event = threading.Event()
1209 else:
1210 my_event = event
1211 self.auth_handler = AuthHandler(self)
1212 self.auth_handler.auth_publickey(username, key, my_event)
1213 if event is not None:
1214
1215 return []
1216 return self.auth_handler.wait_for_response(my_event)
1217
1219 """
1220 Authenticate to the server interactively. A handler is used to answer
1221 arbitrary questions from the server. On many servers, this is just a
1222 dumb wrapper around PAM.
1223
1224 This method will block until the authentication succeeds or fails,
1225 peroidically calling the handler asynchronously to get answers to
1226 authentication questions. The handler may be called more than once
1227 if the server continues to ask questions.
1228
1229 The handler is expected to be a callable that will handle calls of the
1230 form: C{handler(title, instructions, prompt_list)}. The C{title} is
1231 meant to be a dialog-window title, and the C{instructions} are user
1232 instructions (both are strings). C{prompt_list} will be a list of
1233 prompts, each prompt being a tuple of C{(str, bool)}. The string is
1234 the prompt and the boolean indicates whether the user text should be
1235 echoed.
1236
1237 A sample call would thus be:
1238 C{handler('title', 'instructions', [('Password:', False)])}.
1239
1240 The handler should return a list or tuple of answers to the server's
1241 questions.
1242
1243 If the server requires multi-step authentication (which is very rare),
1244 this method will return a list of auth types permissible for the next
1245 step. Otherwise, in the normal case, an empty list is returned.
1246
1247 @param username: the username to authenticate as
1248 @type username: string
1249 @param handler: a handler for responding to server questions
1250 @type handler: callable
1251 @param submethods: a string list of desired submethods (optional)
1252 @type submethods: str
1253 @return: list of auth types permissible for the next stage of
1254 authentication (normally empty).
1255 @rtype: list
1256
1257 @raise BadAuthenticationType: if public-key authentication isn't
1258 allowed by the server for this user
1259 @raise AuthenticationException: if the authentication failed
1260 @raise SSHException: if there was a network error
1261
1262 @since: 1.5
1263 """
1264 if (not self.active) or (not self.initial_kex_done):
1265
1266 raise SSHException('No existing session')
1267 my_event = threading.Event()
1268 self.auth_handler = AuthHandler(self)
1269 self.auth_handler.auth_interactive(username, handler, my_event, submethods)
1270 return self.auth_handler.wait_for_response(my_event)
1271
1273 """
1274 Set the channel for this transport's logging. The default is
1275 C{"paramiko.transport"} but it can be set to anything you want.
1276 (See the C{logging} module for more info.) SSH Channels will log
1277 to a sub-channel of the one specified.
1278
1279 @param name: new channel name for logging
1280 @type name: str
1281
1282 @since: 1.1
1283 """
1284 self.log_name = name
1285 self.logger = util.get_logger(name)
1286 self.packetizer.set_log(self.logger)
1287
1289 """
1290 Return the channel name used for this transport's logging.
1291
1292 @return: channel name.
1293 @rtype: str
1294
1295 @since: 1.2
1296 """
1297 return self.log_name
1298
1300 """
1301 Turn on/off logging a hex dump of protocol traffic at DEBUG level in
1302 the logs. Normally you would want this off (which is the default),
1303 but if you are debugging something, it may be useful.
1304
1305 @param hexdump: C{True} to log protocol traffix (in hex) to the log;
1306 C{False} otherwise.
1307 @type hexdump: bool
1308 """
1309 self.packetizer.set_hexdump(hexdump)
1310
1312 """
1313 Return C{True} if the transport is currently logging hex dumps of
1314 protocol traffic.
1315
1316 @return: C{True} if hex dumps are being logged
1317 @rtype: bool
1318
1319 @since: 1.4
1320 """
1321 return self.packetizer.get_hexdump()
1322
1324 """
1325 Turn on/off compression. This will only have an affect before starting
1326 the transport (ie before calling L{connect}, etc). By default,
1327 compression is off since it negatively affects interactive sessions.
1328
1329 @param compress: C{True} to ask the remote client/server to compress
1330 traffic; C{False} to refuse compression
1331 @type compress: bool
1332
1333 @since: 1.5.2
1334 """
1335 if compress:
1336 self._preferred_compression = ( 'zlib@openssh.com', 'zlib', 'none' )
1337 else:
1338 self._preferred_compression = ( 'none', )
1339
1341 """
1342 Return the address of the remote side of this Transport, if possible.
1343 This is effectively a wrapper around C{'getpeername'} on the underlying
1344 socket. If the socket-like object has no C{'getpeername'} method,
1345 then C{("unknown", 0)} is returned.
1346
1347 @return: the address if the remote host, if known
1348 @rtype: tuple(str, int)
1349 """
1350 gp = getattr(self.sock, 'getpeername', None)
1351 if gp is None:
1352 return ('unknown', 0)
1353 return gp()
1354
1356 self.active = False
1357 self.packetizer.close()
1358
1359
1360
1361
1362
1363 - def _log(self, level, msg, *args):
1364 if issubclass(type(msg), list):
1365 for m in msg:
1366 self.logger.log(level, m)
1367 else:
1368 self.logger.log(level, msg, *args)
1369
1371 "used by KexGex to find primes for group exchange"
1372 return self._modulus_pack
1373
1375 "you are holding the lock"
1376 chanid = self._channel_counter
1377 while self._channels.get(chanid) is not None:
1378 self._channel_counter = (self._channel_counter + 1) & 0xffffff
1379 chanid = self._channel_counter
1380 self._channel_counter = (self._channel_counter + 1) & 0xffffff
1381 return chanid
1382
1384 "used by a Channel to remove itself from the active channel list"
1385 self._channels.delete(chanid)
1386
1388 self.packetizer.send_message(data)
1389
1391 """
1392 send a message, but block if we're in key negotiation. this is used
1393 for user-initiated requests.
1394 """
1395 while True:
1396 self.clear_to_send.wait(0.1)
1397 if not self.active:
1398 self._log(DEBUG, 'Dropping user packet because connection is dead.')
1399 return
1400 self.clear_to_send_lock.acquire()
1401 if self.clear_to_send.isSet():
1402 break
1403 self.clear_to_send_lock.release()
1404 try:
1405 self._send_message(data)
1406 finally:
1407 self.clear_to_send_lock.release()
1408
1410 "used by a kex object to set the K (root key) and H (exchange hash)"
1411 self.K = k
1412 self.H = h
1413 if self.session_id == None:
1414 self.session_id = h
1415
1417 "used by a kex object to register the next packet type it expects to see"
1418 self._expected_packet = tuple(ptypes)
1419
1421 key = self._key_info[self.host_key_type](Message(host_key))
1422 if key is None:
1423 raise SSHException('Unknown host key type')
1424 if not key.verify_ssh_sig(self.H, Message(sig)):
1425 raise SSHException('Signature verification (%s) failed. Boo. Robey should debug this.' % self.host_key_type)
1426 self.host_key = key
1427
1429 "id is 'A' - 'F' for the various keys used by ssh"
1430 m = Message()
1431 m.add_mpint(self.K)
1432 m.add_bytes(self.H)
1433 m.add_byte(id)
1434 m.add_bytes(self.session_id)
1435 out = sofar = SHA.new(str(m)).digest()
1436 while len(out) < nbytes:
1437 m = Message()
1438 m.add_mpint(self.K)
1439 m.add_bytes(self.H)
1440 m.add_bytes(sofar)
1441 digest = SHA.new(str(m)).digest()
1442 out += digest
1443 sofar += digest
1444 return out[:nbytes]
1445
1450
1452
1453 if handler is None:
1454
1455 def default_handler(channel, (src_addr, src_port)):
1456 self._queue_incoming_channel(channel)
1457 self._x11_handler = default_handler
1458 else:
1459 self._x11_handler = handler
1460
1462 self.lock.acquire()
1463 try:
1464 self.server_accepts.append(channel)
1465 self.server_accept_cv.notify()
1466 finally:
1467 self.lock.release()
1468
1470
1471
1472
1473
1474
1475
1476 _active_threads.append(self)
1477 if self.server_mode:
1478 self._log(DEBUG, 'starting thread (server mode): %s' % hex(long(id(self)) & 0xffffffffL))
1479 else:
1480 self._log(DEBUG, 'starting thread (client mode): %s' % hex(long(id(self)) & 0xffffffffL))
1481 try:
1482 self.packetizer.write_all(self.local_version + '\r\n')
1483 self._check_banner()
1484 self._send_kex_init()
1485 self._expect_packet(MSG_KEXINIT)
1486
1487 while self.active:
1488 if self.packetizer.need_rekey() and not self.in_kex:
1489 self._send_kex_init()
1490 try:
1491 ptype, m = self.packetizer.read_message()
1492 except NeedRekeyException:
1493 continue
1494 if ptype == MSG_IGNORE:
1495 continue
1496 elif ptype == MSG_DISCONNECT:
1497 self._parse_disconnect(m)
1498 self.active = False
1499 self.packetizer.close()
1500 break
1501 elif ptype == MSG_DEBUG:
1502 self._parse_debug(m)
1503 continue
1504 if len(self._expected_packet) > 0:
1505 if ptype not in self._expected_packet:
1506 raise SSHException('Expecting packet from %r, got %d' % (self._expected_packet, ptype))
1507 self._expected_packet = tuple()
1508 if (ptype >= 30) and (ptype <= 39):
1509 self.kex_engine.parse_next(ptype, m)
1510 continue
1511
1512 if ptype in self._handler_table:
1513 self._handler_table[ptype](self, m)
1514 elif ptype in self._channel_handler_table:
1515 chanid = m.get_int()
1516 chan = self._channels.get(chanid)
1517 if chan is not None:
1518 self._channel_handler_table[ptype](chan, m)
1519 elif chanid in self.channels_seen:
1520 self._log(DEBUG, 'Ignoring message for dead channel %d' % chanid)
1521 else:
1522 self._log(ERROR, 'Channel request for unknown channel %d' % chanid)
1523 self.active = False
1524 self.packetizer.close()
1525 elif (self.auth_handler is not None) and (ptype in self.auth_handler._handler_table):
1526 self.auth_handler._handler_table[ptype](self.auth_handler, m)
1527 else:
1528 self._log(WARNING, 'Oops, unhandled type %d' % ptype)
1529 msg = Message()
1530 msg.add_byte(chr(MSG_UNIMPLEMENTED))
1531 msg.add_int(m.seqno)
1532 self._send_message(msg)
1533 except SSHException, e:
1534 self._log(ERROR, 'Exception: ' + str(e))
1535 self._log(ERROR, util.tb_strings())
1536 self.saved_exception = e
1537 except EOFError, e:
1538 self._log(DEBUG, 'EOF in transport thread')
1539
1540 self.saved_exception = e
1541 except socket.error, e:
1542 if type(e.args) is tuple:
1543 emsg = '%s (%d)' % (e.args[1], e.args[0])
1544 else:
1545 emsg = e.args
1546 self._log(ERROR, 'Socket exception: ' + emsg)
1547 self.saved_exception = e
1548 except Exception, e:
1549 self._log(ERROR, 'Unknown exception: ' + str(e))
1550 self._log(ERROR, util.tb_strings())
1551 self.saved_exception = e
1552 _active_threads.remove(self)
1553 for chan in self._channels.values():
1554 chan._unlink()
1555 if self.active:
1556 self.active = False
1557 self.packetizer.close()
1558 if self.completion_event != None:
1559 self.completion_event.set()
1560 if self.auth_handler is not None:
1561 self.auth_handler.abort()
1562 for event in self.channel_events.values():
1563 event.set()
1564 try:
1565 self.lock.acquire()
1566 self.server_accept_cv.notify()
1567 finally:
1568 self.lock.release()
1569 self.sock.close()
1570
1571
1572
1573
1574
1576
1577 self.clear_to_send_lock.acquire()
1578 try:
1579 self.clear_to_send.clear()
1580 finally:
1581 self.clear_to_send_lock.release()
1582 if self.local_kex_init == None:
1583
1584 self._send_kex_init()
1585 self._parse_kex_init(m)
1586 self.kex_engine.start_kex()
1587
1589
1590 for i in range(5):
1591
1592
1593 if i == 0:
1594 timeout = self.banner_timeout
1595 else:
1596 timeout = 2
1597 try:
1598 buf = self.packetizer.readline(timeout)
1599 except Exception, x:
1600 raise SSHException('Error reading SSH protocol banner' + str(x))
1601 if buf[:4] == 'SSH-':
1602 break
1603 self._log(DEBUG, 'Banner: ' + buf)
1604 if buf[:4] != 'SSH-':
1605 raise SSHException('Indecipherable protocol version "' + buf + '"')
1606
1607 self.remote_version = buf
1608
1609 comment = ''
1610 i = string.find(buf, ' ')
1611 if i >= 0:
1612 comment = buf[i+1:]
1613 buf = buf[:i]
1614
1615 segs = buf.split('-', 2)
1616 if len(segs) < 3:
1617 raise SSHException('Invalid SSH banner')
1618 version = segs[1]
1619 client = segs[2]
1620 if version != '1.99' and version != '2.0':
1621 raise SSHException('Incompatible version (%s instead of 2.0)' % (version,))
1622 self._log(INFO, 'Connected (version %s, client %s)' % (version, client))
1623
1665
1667 cookie = m.get_bytes(16)
1668 kex_algo_list = m.get_list()
1669 server_key_algo_list = m.get_list()
1670 client_encrypt_algo_list = m.get_list()
1671 server_encrypt_algo_list = m.get_list()
1672 client_mac_algo_list = m.get_list()
1673 server_mac_algo_list = m.get_list()
1674 client_compress_algo_list = m.get_list()
1675 server_compress_algo_list = m.get_list()
1676 client_lang_list = m.get_list()
1677 server_lang_list = m.get_list()
1678 kex_follows = m.get_boolean()
1679 unused = m.get_int()
1680
1681 self._log(DEBUG, 'kex algos:' + str(kex_algo_list) + ' server key:' + str(server_key_algo_list) + \
1682 ' client encrypt:' + str(client_encrypt_algo_list) + \
1683 ' server encrypt:' + str(server_encrypt_algo_list) + \
1684 ' client mac:' + str(client_mac_algo_list) + \
1685 ' server mac:' + str(server_mac_algo_list) + \
1686 ' client compress:' + str(client_compress_algo_list) + \
1687 ' server compress:' + str(server_compress_algo_list) + \
1688 ' client lang:' + str(client_lang_list) + \
1689 ' server lang:' + str(server_lang_list) + \
1690 ' kex follows?' + str(kex_follows))
1691
1692
1693
1694 if self.server_mode:
1695 agreed_kex = filter(self._preferred_kex.__contains__, kex_algo_list)
1696 else:
1697 agreed_kex = filter(kex_algo_list.__contains__, self._preferred_kex)
1698 if len(agreed_kex) == 0:
1699 raise SSHException('Incompatible ssh peer (no acceptable kex algorithm)')
1700 self.kex_engine = self._kex_info[agreed_kex[0]](self)
1701
1702 if self.server_mode:
1703 available_server_keys = filter(self.server_key_dict.keys().__contains__,
1704 self._preferred_keys)
1705 agreed_keys = filter(available_server_keys.__contains__, server_key_algo_list)
1706 else:
1707 agreed_keys = filter(server_key_algo_list.__contains__, self._preferred_keys)
1708 if len(agreed_keys) == 0:
1709 raise SSHException('Incompatible ssh peer (no acceptable host key)')
1710 self.host_key_type = agreed_keys[0]
1711 if self.server_mode and (self.get_server_key() is None):
1712 raise SSHException('Incompatible ssh peer (can\'t match requested host key type)')
1713
1714 if self.server_mode:
1715 agreed_local_ciphers = filter(self._preferred_ciphers.__contains__,
1716 server_encrypt_algo_list)
1717 agreed_remote_ciphers = filter(self._preferred_ciphers.__contains__,
1718 client_encrypt_algo_list)
1719 else:
1720 agreed_local_ciphers = filter(client_encrypt_algo_list.__contains__,
1721 self._preferred_ciphers)
1722 agreed_remote_ciphers = filter(server_encrypt_algo_list.__contains__,
1723 self._preferred_ciphers)
1724 if (len(agreed_local_ciphers) == 0) or (len(agreed_remote_ciphers) == 0):
1725 raise SSHException('Incompatible ssh server (no acceptable ciphers)')
1726 self.local_cipher = agreed_local_ciphers[0]
1727 self.remote_cipher = agreed_remote_ciphers[0]
1728 self._log(DEBUG, 'Ciphers agreed: local=%s, remote=%s' % (self.local_cipher, self.remote_cipher))
1729
1730 if self.server_mode:
1731 agreed_remote_macs = filter(self._preferred_macs.__contains__, client_mac_algo_list)
1732 agreed_local_macs = filter(self._preferred_macs.__contains__, server_mac_algo_list)
1733 else:
1734 agreed_local_macs = filter(client_mac_algo_list.__contains__, self._preferred_macs)
1735 agreed_remote_macs = filter(server_mac_algo_list.__contains__, self._preferred_macs)
1736 if (len(agreed_local_macs) == 0) or (len(agreed_remote_macs) == 0):
1737 raise SSHException('Incompatible ssh server (no acceptable macs)')
1738 self.local_mac = agreed_local_macs[0]
1739 self.remote_mac = agreed_remote_macs[0]
1740
1741 if self.server_mode:
1742 agreed_remote_compression = filter(self._preferred_compression.__contains__, client_compress_algo_list)
1743 agreed_local_compression = filter(self._preferred_compression.__contains__, server_compress_algo_list)
1744 else:
1745 agreed_local_compression = filter(client_compress_algo_list.__contains__, self._preferred_compression)
1746 agreed_remote_compression = filter(server_compress_algo_list.__contains__, self._preferred_compression)
1747 if (len(agreed_local_compression) == 0) or (len(agreed_remote_compression) == 0):
1748 raise SSHException('Incompatible ssh server (no acceptable compression) %r %r %r' % (agreed_local_compression, agreed_remote_compression, self._preferred_compression))
1749 self.local_compression = agreed_local_compression[0]
1750 self.remote_compression = agreed_remote_compression[0]
1751
1752 self._log(DEBUG, 'using kex %s; server key type %s; cipher: local %s, remote %s; mac: local %s, remote %s; compression: local %s, remote %s' %
1753 (agreed_kex[0], self.host_key_type, self.local_cipher, self.remote_cipher, self.local_mac,
1754 self.remote_mac, self.local_compression, self.remote_compression))
1755
1756
1757
1758
1759
1760
1761 self.remote_kex_init = chr(MSG_KEXINIT) + m.get_so_far()
1762
1764 "switch on newly negotiated encryption parameters for inbound traffic"
1765 block_size = self._cipher_info[self.remote_cipher]['block-size']
1766 if self.server_mode:
1767 IV_in = self._compute_key('A', block_size)
1768 key_in = self._compute_key('C', self._cipher_info[self.remote_cipher]['key-size'])
1769 else:
1770 IV_in = self._compute_key('B', block_size)
1771 key_in = self._compute_key('D', self._cipher_info[self.remote_cipher]['key-size'])
1772 engine = self._get_cipher(self.remote_cipher, key_in, IV_in)
1773 mac_size = self._mac_info[self.remote_mac]['size']
1774 mac_engine = self._mac_info[self.remote_mac]['class']
1775
1776
1777 if self.server_mode:
1778 mac_key = self._compute_key('E', mac_engine.digest_size)
1779 else:
1780 mac_key = self._compute_key('F', mac_engine.digest_size)
1781 self.packetizer.set_inbound_cipher(engine, block_size, mac_engine, mac_size, mac_key)
1782 compress_in = self._compression_info[self.remote_compression][1]
1783 if (compress_in is not None) and ((self.remote_compression != 'zlib@openssh.com') or self.authenticated):
1784 self._log(DEBUG, 'Switching on inbound compression ...')
1785 self.packetizer.set_inbound_compressor(compress_in())
1786
1788 "switch on newly negotiated encryption parameters for outbound traffic"
1789 m = Message()
1790 m.add_byte(chr(MSG_NEWKEYS))
1791 self._send_message(m)
1792 block_size = self._cipher_info[self.local_cipher]['block-size']
1793 if self.server_mode:
1794 IV_out = self._compute_key('B', block_size)
1795 key_out = self._compute_key('D', self._cipher_info[self.local_cipher]['key-size'])
1796 else:
1797 IV_out = self._compute_key('A', block_size)
1798 key_out = self._compute_key('C', self._cipher_info[self.local_cipher]['key-size'])
1799 engine = self._get_cipher(self.local_cipher, key_out, IV_out)
1800 mac_size = self._mac_info[self.local_mac]['size']
1801 mac_engine = self._mac_info[self.local_mac]['class']
1802
1803
1804 if self.server_mode:
1805 mac_key = self._compute_key('F', mac_engine.digest_size)
1806 else:
1807 mac_key = self._compute_key('E', mac_engine.digest_size)
1808 self.packetizer.set_outbound_cipher(engine, block_size, mac_engine, mac_size, mac_key)
1809 compress_out = self._compression_info[self.local_compression][0]
1810 if (compress_out is not None) and ((self.local_compression != 'zlib@openssh.com') or self.authenticated):
1811 self._log(DEBUG, 'Switching on outbound compression ...')
1812 self.packetizer.set_outbound_compressor(compress_out())
1813 if not self.packetizer.need_rekey():
1814 self.in_kex = False
1815
1816 self._expect_packet(MSG_NEWKEYS)
1817
1819 self.authenticated = True
1820
1821 if self.local_compression == 'zlib@openssh.com':
1822 compress_out = self._compression_info[self.local_compression][0]
1823 self._log(DEBUG, 'Switching on outbound compression ...')
1824 self.packetizer.set_outbound_compressor(compress_out())
1825 if self.remote_compression == 'zlib@openssh.com':
1826 compress_in = self._compression_info[self.remote_compression][1]
1827 self._log(DEBUG, 'Switching on inbound compression ...')
1828 self.packetizer.set_inbound_compressor(compress_in())
1829
1831 self._log(DEBUG, 'Switch to new keys ...')
1832 self._activate_inbound()
1833
1834 self.local_kex_init = self.remote_kex_init = None
1835 self.K = None
1836 self.kex_engine = None
1837 if self.server_mode and (self.auth_handler is None):
1838
1839 self.auth_handler = AuthHandler(self)
1840 if not self.initial_kex_done:
1841
1842 self.initial_kex_done = True
1843
1844 if self.completion_event != None:
1845 self.completion_event.set()
1846
1847 if not self.packetizer.need_rekey():
1848 self.in_kex = False
1849 self.clear_to_send_lock.acquire()
1850 try:
1851 self.clear_to_send.set()
1852 finally:
1853 self.clear_to_send_lock.release()
1854 return
1855
1857 code = m.get_int()
1858 desc = m.get_string()
1859 self._log(INFO, 'Disconnect (code %d): %s' % (code, desc))
1860
1893
1895 self._log(DEBUG, 'Global request successful.')
1896 self.global_response = m
1897 if self.completion_event is not None:
1898 self.completion_event.set()
1899
1901 self._log(DEBUG, 'Global request denied.')
1902 self.global_response = None
1903 if self.completion_event is not None:
1904 self.completion_event.set()
1905
1907 chanid = m.get_int()
1908 server_chanid = m.get_int()
1909 server_window_size = m.get_int()
1910 server_max_packet_size = m.get_int()
1911 chan = self._channels.get(chanid)
1912 if chan is None:
1913 self._log(WARNING, 'Success for unrequested channel! [??]')
1914 return
1915 self.lock.acquire()
1916 try:
1917 chan._set_remote_channel(server_chanid, server_window_size, server_max_packet_size)
1918 self._log(INFO, 'Secsh channel %d opened.' % chanid)
1919 if chanid in self.channel_events:
1920 self.channel_events[chanid].set()
1921 del self.channel_events[chanid]
1922 finally:
1923 self.lock.release()
1924 return
1925
1927 chanid = m.get_int()
1928 reason = m.get_int()
1929 reason_str = m.get_string()
1930 lang = m.get_string()
1931 reason_text = CONNECTION_FAILED_CODE.get(reason, '(unknown code)')
1932 self._log(INFO, 'Secsh channel %d open FAILED: %s: %s' % (chanid, reason_str, reason_text))
1933 self.lock.acquire()
1934 try:
1935 self.saved_exception = ChannelException(reason, reason_text)
1936 if chanid in self.channel_events:
1937 self._channels.delete(chanid)
1938 if chanid in self.channel_events:
1939 self.channel_events[chanid].set()
1940 del self.channel_events[chanid]
1941 finally:
1942 self.lock.release()
1943 return
1944
1946 kind = m.get_string()
1947 chanid = m.get_int()
1948 initial_window_size = m.get_int()
1949 max_packet_size = m.get_int()
1950 reject = False
1951 if (kind == 'x11') and (self._x11_handler is not None):
1952 origin_addr = m.get_string()
1953 origin_port = m.get_int()
1954 self._log(DEBUG, 'Incoming x11 connection from %s:%d' % (origin_addr, origin_port))
1955 self.lock.acquire()
1956 try:
1957 my_chanid = self._next_channel()
1958 finally:
1959 self.lock.release()
1960 elif (kind == 'forwarded-tcpip') and (self._tcp_handler is not None):
1961 server_addr = m.get_string()
1962 server_port = m.get_int()
1963 origin_addr = m.get_string()
1964 origin_port = m.get_int()
1965 self._log(DEBUG, 'Incoming tcp forwarded connection from %s:%d' % (origin_addr, origin_port))
1966 self.lock.acquire()
1967 try:
1968 my_chanid = self._next_channel()
1969 finally:
1970 self.lock.release()
1971 elif not self.server_mode:
1972 self._log(DEBUG, 'Rejecting "%s" channel request from server.' % kind)
1973 reject = True
1974 reason = OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
1975 else:
1976 self.lock.acquire()
1977 try:
1978 my_chanid = self._next_channel()
1979 finally:
1980 self.lock.release()
1981 if kind == 'direct-tcpip':
1982
1983 dest_addr = m.get_string()
1984 dest_port = m.get_int()
1985 origin_addr = m.get_string()
1986 origin_port = m.get_int()
1987 reason = self.server_object.check_channel_direct_tcpip_request(
1988 my_chanid, (origin_addr, origin_port),
1989 (dest_addr, dest_port))
1990 else:
1991 reason = self.server_object.check_channel_request(kind, my_chanid)
1992 if reason != OPEN_SUCCEEDED:
1993 self._log(DEBUG, 'Rejecting "%s" channel request from client.' % kind)
1994 reject = True
1995 if reject:
1996 msg = Message()
1997 msg.add_byte(chr(MSG_CHANNEL_OPEN_FAILURE))
1998 msg.add_int(chanid)
1999 msg.add_int(reason)
2000 msg.add_string('')
2001 msg.add_string('en')
2002 self._send_message(msg)
2003 return
2004
2005 chan = Channel(my_chanid)
2006 self.lock.acquire()
2007 try:
2008 self._channels.put(my_chanid, chan)
2009 self.channels_seen[my_chanid] = True
2010 chan._set_transport(self)
2011 chan._set_window(self.window_size, self.max_packet_size)
2012 chan._set_remote_channel(chanid, initial_window_size, max_packet_size)
2013 finally:
2014 self.lock.release()
2015 m = Message()
2016 m.add_byte(chr(MSG_CHANNEL_OPEN_SUCCESS))
2017 m.add_int(chanid)
2018 m.add_int(my_chanid)
2019 m.add_int(self.window_size)
2020 m.add_int(self.max_packet_size)
2021 self._send_message(m)
2022 self._log(INFO, 'Secsh channel %d (%s) opened.', my_chanid, kind)
2023 if kind == 'x11':
2024 self._x11_handler(chan, (origin_addr, origin_port))
2025 elif kind == 'forwarded-tcpip':
2026 chan.origin_addr = (origin_addr, origin_port)
2027 self._tcp_handler(chan, (origin_addr, origin_port), (server_addr, server_port))
2028 else:
2029 self._queue_incoming_channel(chan)
2030
2036
2038 try:
2039 self.lock.acquire()
2040 if name not in self.subsystem_table:
2041 return (None, [], {})
2042 return self.subsystem_table[name]
2043 finally:
2044 self.lock.release()
2045
2046 _handler_table = {
2047 MSG_NEWKEYS: _parse_newkeys,
2048 MSG_GLOBAL_REQUEST: _parse_global_request,
2049 MSG_REQUEST_SUCCESS: _parse_request_success,
2050 MSG_REQUEST_FAILURE: _parse_request_failure,
2051 MSG_CHANNEL_OPEN_SUCCESS: _parse_channel_open_success,
2052 MSG_CHANNEL_OPEN_FAILURE: _parse_channel_open_failure,
2053 MSG_CHANNEL_OPEN: _parse_channel_open,
2054 MSG_KEXINIT: _negotiate_keys,
2055 }
2056
2057 _channel_handler_table = {
2058 MSG_CHANNEL_SUCCESS: Channel._request_success,
2059 MSG_CHANNEL_FAILURE: Channel._request_failed,
2060 MSG_CHANNEL_DATA: Channel._feed,
2061 MSG_CHANNEL_EXTENDED_DATA: Channel._feed_extended,
2062 MSG_CHANNEL_WINDOW_ADJUST: Channel._window_adjust,
2063 MSG_CHANNEL_REQUEST: Channel._handle_request,
2064 MSG_CHANNEL_EOF: Channel._handle_eof,
2065 MSG_CHANNEL_CLOSE: Channel._handle_close,
2066 }
2067