Coverage for /pythoncovmergedfiles/medio/medio/src/paramiko/paramiko/transport.py: 15%

1298 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-26 06:36 +0000

1# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com> 

2# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com> 

3# 

4# This file is part of paramiko. 

5# 

6# Paramiko is free software; you can redistribute it and/or modify it under the 

7# terms of the GNU Lesser General Public License as published by the Free 

8# Software Foundation; either version 2.1 of the License, or (at your option) 

9# any later version. 

10# 

11# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY 

12# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 

13# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 

14# details. 

15# 

16# You should have received a copy of the GNU Lesser General Public License 

17# along with Paramiko; if not, write to the Free Software Foundation, Inc., 

18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 

19 

20""" 

21Core protocol implementation 

22""" 

23 

24import os 

25import socket 

26import sys 

27import threading 

28import time 

29import weakref 

30from hashlib import md5, sha1, sha256, sha512 

31 

32from cryptography.hazmat.backends import default_backend 

33from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes 

34 

35import paramiko 

36from paramiko import util 

37from paramiko.auth_handler import AuthHandler 

38from paramiko.ssh_gss import GSSAuth 

39from paramiko.channel import Channel 

40from paramiko.common import ( 

41 xffffffff, 

42 cMSG_CHANNEL_OPEN, 

43 cMSG_IGNORE, 

44 cMSG_GLOBAL_REQUEST, 

45 DEBUG, 

46 MSG_KEXINIT, 

47 MSG_IGNORE, 

48 MSG_DISCONNECT, 

49 MSG_DEBUG, 

50 ERROR, 

51 WARNING, 

52 cMSG_UNIMPLEMENTED, 

53 INFO, 

54 cMSG_KEXINIT, 

55 cMSG_NEWKEYS, 

56 MSG_NEWKEYS, 

57 cMSG_REQUEST_SUCCESS, 

58 cMSG_REQUEST_FAILURE, 

59 CONNECTION_FAILED_CODE, 

60 OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED, 

61 OPEN_SUCCEEDED, 

62 cMSG_CHANNEL_OPEN_FAILURE, 

63 cMSG_CHANNEL_OPEN_SUCCESS, 

64 MSG_GLOBAL_REQUEST, 

65 MSG_REQUEST_SUCCESS, 

66 MSG_REQUEST_FAILURE, 

67 MSG_CHANNEL_OPEN_SUCCESS, 

68 MSG_CHANNEL_OPEN_FAILURE, 

69 MSG_CHANNEL_OPEN, 

70 MSG_CHANNEL_SUCCESS, 

71 MSG_CHANNEL_FAILURE, 

72 MSG_CHANNEL_DATA, 

73 MSG_CHANNEL_EXTENDED_DATA, 

74 MSG_CHANNEL_WINDOW_ADJUST, 

75 MSG_CHANNEL_REQUEST, 

76 MSG_CHANNEL_EOF, 

77 MSG_CHANNEL_CLOSE, 

78 MIN_WINDOW_SIZE, 

79 MIN_PACKET_SIZE, 

80 MAX_WINDOW_SIZE, 

81 DEFAULT_WINDOW_SIZE, 

82 DEFAULT_MAX_PACKET_SIZE, 

83 HIGHEST_USERAUTH_MESSAGE_ID, 

84 MSG_UNIMPLEMENTED, 

85 MSG_NAMES, 

86 MSG_EXT_INFO, 

87 cMSG_EXT_INFO, 

88 byte_ord, 

89) 

90from paramiko.compress import ZlibCompressor, ZlibDecompressor 

91from paramiko.dsskey import DSSKey 

92from paramiko.ed25519key import Ed25519Key 

93from paramiko.kex_curve25519 import KexCurve25519 

94from paramiko.kex_gex import KexGex, KexGexSHA256 

95from paramiko.kex_group1 import KexGroup1 

96from paramiko.kex_group14 import KexGroup14, KexGroup14SHA256 

97from paramiko.kex_group16 import KexGroup16SHA512 

98from paramiko.kex_ecdh_nist import KexNistp256, KexNistp384, KexNistp521 

99from paramiko.kex_gss import KexGSSGex, KexGSSGroup1, KexGSSGroup14 

100from paramiko.message import Message 

101from paramiko.packet import Packetizer, NeedRekeyException 

102from paramiko.primes import ModulusPack 

103from paramiko.rsakey import RSAKey 

104from paramiko.ecdsakey import ECDSAKey 

105from paramiko.server import ServerInterface 

106from paramiko.sftp_client import SFTPClient 

107from paramiko.ssh_exception import ( 

108 SSHException, 

109 BadAuthenticationType, 

110 ChannelException, 

111 IncompatiblePeer, 

112 ProxyCommandFailure, 

113) 

114from paramiko.util import ( 

115 ClosingContextManager, 

116 clamp_value, 

117 b, 

118) 

119 

120 

121# for thread cleanup 

122_active_threads = [] 

123 

124 

125def _join_lingering_threads(): 

126 for thr in _active_threads: 

127 thr.stop_thread() 

128 

129 

130import atexit 

131 

132atexit.register(_join_lingering_threads) 

133 

134 

135class Transport(threading.Thread, ClosingContextManager): 

136 """ 

137 An SSH Transport attaches to a stream (usually a socket), negotiates an 

138 encrypted session, authenticates, and then creates stream tunnels, called 

139 `channels <.Channel>`, across the session. Multiple channels can be 

140 multiplexed across a single session (and often are, in the case of port 

141 forwardings). 

142 

143 Instances of this class may be used as context managers. 

144 """ 

145 

146 _ENCRYPT = object() 

147 _DECRYPT = object() 

148 

149 _PROTO_ID = "2.0" 

150 _CLIENT_ID = "paramiko_{}".format(paramiko.__version__) 

151 

152 # These tuples of algorithm identifiers are in preference order; do not 

153 # reorder without reason! 

154 # NOTE: if you need to modify these, we suggest leveraging the 

155 # `disabled_algorithms` constructor argument (also available in SSHClient) 

156 # instead of monkeypatching or subclassing. 

157 _preferred_ciphers = ( 

158 "aes128-ctr", 

159 "aes192-ctr", 

160 "aes256-ctr", 

161 "aes128-cbc", 

162 "aes192-cbc", 

163 "aes256-cbc", 

164 "3des-cbc", 

165 ) 

166 _preferred_macs = ( 

167 "hmac-sha2-256", 

168 "hmac-sha2-512", 

169 "hmac-sha2-256-etm@openssh.com", 

170 "hmac-sha2-512-etm@openssh.com", 

171 "hmac-sha1", 

172 "hmac-md5", 

173 "hmac-sha1-96", 

174 "hmac-md5-96", 

175 ) 

176 # ~= HostKeyAlgorithms in OpenSSH land 

177 _preferred_keys = ( 

178 "ssh-ed25519", 

179 "ecdsa-sha2-nistp256", 

180 "ecdsa-sha2-nistp384", 

181 "ecdsa-sha2-nistp521", 

182 "rsa-sha2-512", 

183 "rsa-sha2-256", 

184 "ssh-rsa", 

185 "ssh-dss", 

186 ) 

187 # ~= PubKeyAcceptedAlgorithms 

188 _preferred_pubkeys = ( 

189 "ssh-ed25519", 

190 "ecdsa-sha2-nistp256", 

191 "ecdsa-sha2-nistp384", 

192 "ecdsa-sha2-nistp521", 

193 "rsa-sha2-512", 

194 "rsa-sha2-256", 

195 "ssh-rsa", 

196 "ssh-dss", 

197 ) 

198 _preferred_kex = ( 

199 "ecdh-sha2-nistp256", 

200 "ecdh-sha2-nistp384", 

201 "ecdh-sha2-nistp521", 

202 "diffie-hellman-group16-sha512", 

203 "diffie-hellman-group-exchange-sha256", 

204 "diffie-hellman-group14-sha256", 

205 "diffie-hellman-group-exchange-sha1", 

206 "diffie-hellman-group14-sha1", 

207 "diffie-hellman-group1-sha1", 

208 ) 

209 if KexCurve25519.is_available(): 

210 _preferred_kex = ("curve25519-sha256@libssh.org",) + _preferred_kex 

211 _preferred_gsskex = ( 

212 "gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==", 

213 "gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==", 

214 "gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==", 

215 ) 

216 _preferred_compression = ("none",) 

217 

218 _cipher_info = { 

219 "aes128-ctr": { 

220 "class": algorithms.AES, 

221 "mode": modes.CTR, 

222 "block-size": 16, 

223 "key-size": 16, 

224 }, 

225 "aes192-ctr": { 

226 "class": algorithms.AES, 

227 "mode": modes.CTR, 

228 "block-size": 16, 

229 "key-size": 24, 

230 }, 

231 "aes256-ctr": { 

232 "class": algorithms.AES, 

233 "mode": modes.CTR, 

234 "block-size": 16, 

235 "key-size": 32, 

236 }, 

237 "aes128-cbc": { 

238 "class": algorithms.AES, 

239 "mode": modes.CBC, 

240 "block-size": 16, 

241 "key-size": 16, 

242 }, 

243 "aes192-cbc": { 

244 "class": algorithms.AES, 

245 "mode": modes.CBC, 

246 "block-size": 16, 

247 "key-size": 24, 

248 }, 

249 "aes256-cbc": { 

250 "class": algorithms.AES, 

251 "mode": modes.CBC, 

252 "block-size": 16, 

253 "key-size": 32, 

254 }, 

255 "3des-cbc": { 

256 "class": algorithms.TripleDES, 

257 "mode": modes.CBC, 

258 "block-size": 8, 

259 "key-size": 24, 

260 }, 

261 } 

262 

263 _mac_info = { 

264 "hmac-sha1": {"class": sha1, "size": 20}, 

265 "hmac-sha1-96": {"class": sha1, "size": 12}, 

266 "hmac-sha2-256": {"class": sha256, "size": 32}, 

267 "hmac-sha2-256-etm@openssh.com": {"class": sha256, "size": 32}, 

268 "hmac-sha2-512": {"class": sha512, "size": 64}, 

269 "hmac-sha2-512-etm@openssh.com": {"class": sha512, "size": 64}, 

270 "hmac-md5": {"class": md5, "size": 16}, 

271 "hmac-md5-96": {"class": md5, "size": 12}, 

272 } 

273 

274 _key_info = { 

275 # TODO: at some point we will want to drop this as it's no longer 

276 # considered secure due to using SHA-1 for signatures. OpenSSH 8.8 no 

277 # longer supports it. Question becomes at what point do we want to 

278 # prevent users with older setups from using this? 

279 "ssh-rsa": RSAKey, 

280 "ssh-rsa-cert-v01@openssh.com": RSAKey, 

281 "rsa-sha2-256": RSAKey, 

282 "rsa-sha2-256-cert-v01@openssh.com": RSAKey, 

283 "rsa-sha2-512": RSAKey, 

284 "rsa-sha2-512-cert-v01@openssh.com": RSAKey, 

285 "ssh-dss": DSSKey, 

286 "ssh-dss-cert-v01@openssh.com": DSSKey, 

287 "ecdsa-sha2-nistp256": ECDSAKey, 

288 "ecdsa-sha2-nistp256-cert-v01@openssh.com": ECDSAKey, 

289 "ecdsa-sha2-nistp384": ECDSAKey, 

290 "ecdsa-sha2-nistp384-cert-v01@openssh.com": ECDSAKey, 

291 "ecdsa-sha2-nistp521": ECDSAKey, 

292 "ecdsa-sha2-nistp521-cert-v01@openssh.com": ECDSAKey, 

293 "ssh-ed25519": Ed25519Key, 

294 "ssh-ed25519-cert-v01@openssh.com": Ed25519Key, 

295 } 

296 

297 _kex_info = { 

298 "diffie-hellman-group1-sha1": KexGroup1, 

299 "diffie-hellman-group14-sha1": KexGroup14, 

300 "diffie-hellman-group-exchange-sha1": KexGex, 

301 "diffie-hellman-group-exchange-sha256": KexGexSHA256, 

302 "diffie-hellman-group14-sha256": KexGroup14SHA256, 

303 "diffie-hellman-group16-sha512": KexGroup16SHA512, 

304 "gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==": KexGSSGroup1, 

305 "gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==": KexGSSGroup14, 

306 "gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==": KexGSSGex, 

307 "ecdh-sha2-nistp256": KexNistp256, 

308 "ecdh-sha2-nistp384": KexNistp384, 

309 "ecdh-sha2-nistp521": KexNistp521, 

310 } 

311 if KexCurve25519.is_available(): 

312 _kex_info["curve25519-sha256@libssh.org"] = KexCurve25519 

313 

314 _compression_info = { 

315 # zlib@openssh.com is just zlib, but only turned on after a successful 

316 # authentication. openssh servers may only offer this type because 

317 # they've had troubles with security holes in zlib in the past. 

318 "zlib@openssh.com": (ZlibCompressor, ZlibDecompressor), 

319 "zlib": (ZlibCompressor, ZlibDecompressor), 

320 "none": (None, None), 

321 } 

322 

323 _modulus_pack = None 

324 _active_check_timeout = 0.1 

325 

326 def __init__( 

327 self, 

328 sock, 

329 default_window_size=DEFAULT_WINDOW_SIZE, 

330 default_max_packet_size=DEFAULT_MAX_PACKET_SIZE, 

331 gss_kex=False, 

332 gss_deleg_creds=True, 

333 disabled_algorithms=None, 

334 server_sig_algs=True, 

335 ): 

336 """ 

337 Create a new SSH session over an existing socket, or socket-like 

338 object. This only creates the `.Transport` object; it doesn't begin 

339 the SSH session yet. Use `connect` or `start_client` to begin a client 

340 session, or `start_server` to begin a server session. 

341 

342 If the object is not actually a socket, it must have the following 

343 methods: 

344 

345 - ``send(bytes)``: Writes from 1 to ``len(bytes)`` bytes, and returns 

346 an int representing the number of bytes written. Returns 

347 0 or raises ``EOFError`` if the stream has been closed. 

348 - ``recv(int)``: Reads from 1 to ``int`` bytes and returns them as a 

349 string. Returns 0 or raises ``EOFError`` if the stream has been 

350 closed. 

351 - ``close()``: Closes the socket. 

352 - ``settimeout(n)``: Sets a (float) timeout on I/O operations. 

353 

354 For ease of use, you may also pass in an address (as a tuple) or a host 

355 string as the ``sock`` argument. (A host string is a hostname with an 

356 optional port (separated by ``":"``) which will be converted into a 

357 tuple of ``(hostname, port)``.) A socket will be connected to this 

358 address and used for communication. Exceptions from the ``socket`` 

359 call may be thrown in this case. 

360 

361 .. note:: 

362 Modifying the the window and packet sizes might have adverse 

363 effects on your channels created from this transport. The default 

364 values are the same as in the OpenSSH code base and have been 

365 battle tested. 

366 

367 :param socket sock: 

368 a socket or socket-like object to create the session over. 

369 :param int default_window_size: 

370 sets the default window size on the transport. (defaults to 

371 2097152) 

372 :param int default_max_packet_size: 

373 sets the default max packet size on the transport. (defaults to 

374 32768) 

375 :param bool gss_kex: 

376 Whether to enable GSSAPI key exchange when GSSAPI is in play. 

377 Default: ``False``. 

378 :param bool gss_deleg_creds: 

379 Whether to enable GSSAPI credential delegation when GSSAPI is in 

380 play. Default: ``True``. 

381 :param dict disabled_algorithms: 

382 If given, must be a dictionary mapping algorithm type to an 

383 iterable of algorithm identifiers, which will be disabled for the 

384 lifetime of the transport. 

385 

386 Keys should match the last word in the class' builtin algorithm 

387 tuple attributes, such as ``"ciphers"`` to disable names within 

388 ``_preferred_ciphers``; or ``"kex"`` to disable something defined 

389 inside ``_preferred_kex``. Values should exactly match members of 

390 the matching attribute. 

391 

392 For example, if you need to disable 

393 ``diffie-hellman-group16-sha512`` key exchange (perhaps because 

394 your code talks to a server which implements it differently from 

395 Paramiko), specify ``disabled_algorithms={"kex": 

396 ["diffie-hellman-group16-sha512"]}``. 

397 :param bool server_sig_algs: 

398 Whether to send an extra message to compatible clients, in server 

399 mode, with a list of supported pubkey algorithms. Default: 

400 ``True``. 

401 

402 .. versionchanged:: 1.15 

403 Added the ``default_window_size`` and ``default_max_packet_size`` 

404 arguments. 

405 .. versionchanged:: 1.15 

406 Added the ``gss_kex`` and ``gss_deleg_creds`` kwargs. 

407 .. versionchanged:: 2.6 

408 Added the ``disabled_algorithms`` kwarg. 

409 .. versionchanged:: 2.9 

410 Added the ``server_sig_algs`` kwarg. 

411 """ 

412 self.active = False 

413 self.hostname = None 

414 self.server_extensions = {} 

415 

416 if isinstance(sock, str): 

417 # convert "host:port" into (host, port) 

418 hl = sock.split(":", 1) 

419 self.hostname = hl[0] 

420 if len(hl) == 1: 

421 sock = (hl[0], 22) 

422 else: 

423 sock = (hl[0], int(hl[1])) 

424 if type(sock) is tuple: 

425 # connect to the given (host, port) 

426 hostname, port = sock 

427 self.hostname = hostname 

428 reason = "No suitable address family" 

429 addrinfos = socket.getaddrinfo( 

430 hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM 

431 ) 

432 for family, socktype, proto, canonname, sockaddr in addrinfos: 

433 if socktype == socket.SOCK_STREAM: 

434 af = family 

435 # addr = sockaddr 

436 sock = socket.socket(af, socket.SOCK_STREAM) 

437 try: 

438 sock.connect((hostname, port)) 

439 except socket.error as e: 

440 reason = str(e) 

441 else: 

442 break 

443 else: 

444 raise SSHException( 

445 "Unable to connect to {}: {}".format(hostname, reason) 

446 ) 

447 # okay, normal socket-ish flow here... 

448 threading.Thread.__init__(self) 

449 self.daemon = True 

450 self.sock = sock 

451 # we set the timeout so we can check self.active periodically to 

452 # see if we should bail. socket.timeout exception is never propagated. 

453 self.sock.settimeout(self._active_check_timeout) 

454 

455 # negotiated crypto parameters 

456 self.packetizer = Packetizer(sock) 

457 self.local_version = "SSH-" + self._PROTO_ID + "-" + self._CLIENT_ID 

458 self.remote_version = "" 

459 self.local_cipher = self.remote_cipher = "" 

460 self.local_kex_init = self.remote_kex_init = None 

461 self.local_mac = self.remote_mac = None 

462 self.local_compression = self.remote_compression = None 

463 self.session_id = None 

464 self.host_key_type = None 

465 self.host_key = None 

466 

467 # GSS-API / SSPI Key Exchange 

468 self.use_gss_kex = gss_kex 

469 # This will be set to True if GSS-API Key Exchange was performed 

470 self.gss_kex_used = False 

471 self.kexgss_ctxt = None 

472 self.gss_host = None 

473 if self.use_gss_kex: 

474 self.kexgss_ctxt = GSSAuth("gssapi-keyex", gss_deleg_creds) 

475 self._preferred_kex = self._preferred_gsskex + self._preferred_kex 

476 

477 # state used during negotiation 

478 self.kex_engine = None 

479 self.H = None 

480 self.K = None 

481 

482 self.initial_kex_done = False 

483 self.in_kex = False 

484 self.authenticated = False 

485 self._expected_packet = tuple() 

486 # synchronization (always higher level than write_lock) 

487 self.lock = threading.Lock() 

488 

489 # tracking open channels 

490 self._channels = ChannelMap() 

491 self.channel_events = {} # (id -> Event) 

492 self.channels_seen = {} # (id -> True) 

493 self._channel_counter = 0 

494 self.default_max_packet_size = default_max_packet_size 

495 self.default_window_size = default_window_size 

496 self._forward_agent_handler = None 

497 self._x11_handler = None 

498 self._tcp_handler = None 

499 

500 self.saved_exception = None 

501 self.clear_to_send = threading.Event() 

502 self.clear_to_send_lock = threading.Lock() 

503 self.clear_to_send_timeout = 30.0 

504 self.log_name = "paramiko.transport" 

505 self.logger = util.get_logger(self.log_name) 

506 self.packetizer.set_log(self.logger) 

507 self.auth_handler = None 

508 # response Message from an arbitrary global request 

509 self.global_response = None 

510 # user-defined event callbacks 

511 self.completion_event = None 

512 # how long (seconds) to wait for the SSH banner 

513 self.banner_timeout = 15 

514 # how long (seconds) to wait for the handshake to finish after SSH 

515 # banner sent. 

516 self.handshake_timeout = 15 

517 # how long (seconds) to wait for the auth response. 

518 self.auth_timeout = 30 

519 # how long (seconds) to wait for opening a channel 

520 self.channel_timeout = 60 * 60 

521 self.disabled_algorithms = disabled_algorithms or {} 

522 self.server_sig_algs = server_sig_algs 

523 

524 # server mode: 

525 self.server_mode = False 

526 self.server_object = None 

527 self.server_key_dict = {} 

528 self.server_accepts = [] 

529 self.server_accept_cv = threading.Condition(self.lock) 

530 self.subsystem_table = {} 

531 

532 def _filter_algorithm(self, type_): 

533 default = getattr(self, "_preferred_{}".format(type_)) 

534 return tuple( 

535 x 

536 for x in default 

537 if x not in self.disabled_algorithms.get(type_, []) 

538 ) 

539 

540 @property 

541 def preferred_ciphers(self): 

542 return self._filter_algorithm("ciphers") 

543 

544 @property 

545 def preferred_macs(self): 

546 return self._filter_algorithm("macs") 

547 

548 @property 

549 def preferred_keys(self): 

550 # Interleave cert variants here; resistant to various background 

551 # overwriting of _preferred_keys, and necessary as hostkeys can't use 

552 # the logic pubkey auth does re: injecting/checking for certs at 

553 # runtime 

554 filtered = self._filter_algorithm("keys") 

555 return tuple( 

556 filtered 

557 + tuple("{}-cert-v01@openssh.com".format(x) for x in filtered) 

558 ) 

559 

560 @property 

561 def preferred_pubkeys(self): 

562 return self._filter_algorithm("pubkeys") 

563 

564 @property 

565 def preferred_kex(self): 

566 return self._filter_algorithm("kex") 

567 

568 @property 

569 def preferred_compression(self): 

570 return self._filter_algorithm("compression") 

571 

572 def __repr__(self): 

573 """ 

574 Returns a string representation of this object, for debugging. 

575 """ 

576 id_ = hex(id(self) & xffffffff) 

577 out = "<paramiko.Transport at {}".format(id_) 

578 if not self.active: 

579 out += " (unconnected)" 

580 else: 

581 if self.local_cipher != "": 

582 out += " (cipher {}, {:d} bits)".format( 

583 self.local_cipher, 

584 self._cipher_info[self.local_cipher]["key-size"] * 8, 

585 ) 

586 if self.is_authenticated(): 

587 out += " (active; {} open channel(s))".format( 

588 len(self._channels) 

589 ) 

590 elif self.initial_kex_done: 

591 out += " (connected; awaiting auth)" 

592 else: 

593 out += " (connecting)" 

594 out += ">" 

595 return out 

596 

597 def atfork(self): 

598 """ 

599 Terminate this Transport without closing the session. On posix 

600 systems, if a Transport is open during process forking, both parent 

601 and child will share the underlying socket, but only one process can 

602 use the connection (without corrupting the session). Use this method 

603 to clean up a Transport object without disrupting the other process. 

604 

605 .. versionadded:: 1.5.3 

606 """ 

607 self.sock.close() 

608 self.close() 

609 

610 def get_security_options(self): 

611 """ 

612 Return a `.SecurityOptions` object which can be used to tweak the 

613 encryption algorithms this transport will permit (for encryption, 

614 digest/hash operations, public keys, and key exchanges) and the order 

615 of preference for them. 

616 """ 

617 return SecurityOptions(self) 

618 

619 def set_gss_host(self, gss_host, trust_dns=True, gssapi_requested=True): 

620 """ 

621 Normalize/canonicalize ``self.gss_host`` depending on various factors. 

622 

623 :param str gss_host: 

624 The explicitly requested GSS-oriented hostname to connect to (i.e. 

625 what the host's name is in the Kerberos database.) Defaults to 

626 ``self.hostname`` (which will be the 'real' target hostname and/or 

627 host portion of given socket object.) 

628 :param bool trust_dns: 

629 Indicates whether or not DNS is trusted; if true, DNS will be used 

630 to canonicalize the GSS hostname (which again will either be 

631 ``gss_host`` or the transport's default hostname.) 

632 (Defaults to True due to backwards compatibility.) 

633 :param bool gssapi_requested: 

634 Whether GSSAPI key exchange or authentication was even requested. 

635 If not, this is a no-op and nothing happens 

636 (and ``self.gss_host`` is not set.) 

637 (Defaults to True due to backwards compatibility.) 

638 :returns: ``None``. 

639 """ 

640 # No GSSAPI in play == nothing to do 

641 if not gssapi_requested: 

642 return 

643 # Obtain the correct host first - did user request a GSS-specific name 

644 # to use that is distinct from the actual SSH target hostname? 

645 if gss_host is None: 

646 gss_host = self.hostname 

647 # Finally, canonicalize via DNS if DNS is trusted. 

648 if trust_dns and gss_host is not None: 

649 gss_host = socket.getfqdn(gss_host) 

650 # And set attribute for reference later. 

651 self.gss_host = gss_host 

652 

653 def start_client(self, event=None, timeout=None): 

654 """ 

655 Negotiate a new SSH2 session as a client. This is the first step after 

656 creating a new `.Transport`. A separate thread is created for protocol 

657 negotiation. 

658 

659 If an event is passed in, this method returns immediately. When 

660 negotiation is done (successful or not), the given ``Event`` will 

661 be triggered. On failure, `is_active` will return ``False``. 

662 

663 (Since 1.4) If ``event`` is ``None``, this method will not return until 

664 negotiation is done. On success, the method returns normally. 

665 Otherwise an SSHException is raised. 

666 

667 After a successful negotiation, you will usually want to authenticate, 

668 calling `auth_password <Transport.auth_password>` or 

669 `auth_publickey <Transport.auth_publickey>`. 

670 

671 .. note:: `connect` is a simpler method for connecting as a client. 

672 

673 .. note:: 

674 After calling this method (or `start_server` or `connect`), you 

675 should no longer directly read from or write to the original socket 

676 object. 

677 

678 :param .threading.Event event: 

679 an event to trigger when negotiation is complete (optional) 

680 

681 :param float timeout: 

682 a timeout, in seconds, for SSH2 session negotiation (optional) 

683 

684 :raises: 

685 `.SSHException` -- if negotiation fails (and no ``event`` was 

686 passed in) 

687 """ 

688 self.active = True 

689 if event is not None: 

690 # async, return immediately and let the app poll for completion 

691 self.completion_event = event 

692 self.start() 

693 return 

694 

695 # synchronous, wait for a result 

696 self.completion_event = event = threading.Event() 

697 self.start() 

698 max_time = time.time() + timeout if timeout is not None else None 

699 while True: 

700 event.wait(0.1) 

701 if not self.active: 

702 e = self.get_exception() 

703 if e is not None: 

704 raise e 

705 raise SSHException("Negotiation failed.") 

706 if event.is_set() or ( 

707 timeout is not None and time.time() >= max_time 

708 ): 

709 break 

710 

711 def start_server(self, event=None, server=None): 

712 """ 

713 Negotiate a new SSH2 session as a server. This is the first step after 

714 creating a new `.Transport` and setting up your server host key(s). A 

715 separate thread is created for protocol negotiation. 

716 

717 If an event is passed in, this method returns immediately. When 

718 negotiation is done (successful or not), the given ``Event`` will 

719 be triggered. On failure, `is_active` will return ``False``. 

720 

721 (Since 1.4) If ``event`` is ``None``, this method will not return until 

722 negotiation is done. On success, the method returns normally. 

723 Otherwise an SSHException is raised. 

724 

725 After a successful negotiation, the client will need to authenticate. 

726 Override the methods `get_allowed_auths 

727 <.ServerInterface.get_allowed_auths>`, `check_auth_none 

728 <.ServerInterface.check_auth_none>`, `check_auth_password 

729 <.ServerInterface.check_auth_password>`, and `check_auth_publickey 

730 <.ServerInterface.check_auth_publickey>` in the given ``server`` object 

731 to control the authentication process. 

732 

733 After a successful authentication, the client should request to open a 

734 channel. Override `check_channel_request 

735 <.ServerInterface.check_channel_request>` in the given ``server`` 

736 object to allow channels to be opened. 

737 

738 .. note:: 

739 After calling this method (or `start_client` or `connect`), you 

740 should no longer directly read from or write to the original socket 

741 object. 

742 

743 :param .threading.Event event: 

744 an event to trigger when negotiation is complete. 

745 :param .ServerInterface server: 

746 an object used to perform authentication and create `channels 

747 <.Channel>` 

748 

749 :raises: 

750 `.SSHException` -- if negotiation fails (and no ``event`` was 

751 passed in) 

752 """ 

753 if server is None: 

754 server = ServerInterface() 

755 self.server_mode = True 

756 self.server_object = server 

757 self.active = True 

758 if event is not None: 

759 # async, return immediately and let the app poll for completion 

760 self.completion_event = event 

761 self.start() 

762 return 

763 

764 # synchronous, wait for a result 

765 self.completion_event = event = threading.Event() 

766 self.start() 

767 while True: 

768 event.wait(0.1) 

769 if not self.active: 

770 e = self.get_exception() 

771 if e is not None: 

772 raise e 

773 raise SSHException("Negotiation failed.") 

774 if event.is_set(): 

775 break 

776 

777 def add_server_key(self, key): 

778 """ 

779 Add a host key to the list of keys used for server mode. When behaving 

780 as a server, the host key is used to sign certain packets during the 

781 SSH2 negotiation, so that the client can trust that we are who we say 

782 we are. Because this is used for signing, the key must contain private 

783 key info, not just the public half. Only one key of each type (RSA or 

784 DSS) is kept. 

785 

786 :param .PKey key: 

787 the host key to add, usually an `.RSAKey` or `.DSSKey`. 

788 """ 

789 self.server_key_dict[key.get_name()] = key 

790 # Handle SHA-2 extensions for RSA by ensuring that lookups into 

791 # self.server_key_dict will yield this key for any of the algorithm 

792 # names. 

793 if isinstance(key, RSAKey): 

794 self.server_key_dict["rsa-sha2-256"] = key 

795 self.server_key_dict["rsa-sha2-512"] = key 

796 

797 def get_server_key(self): 

798 """ 

799 Return the active host key, in server mode. After negotiating with the 

800 client, this method will return the negotiated host key. If only one 

801 type of host key was set with `add_server_key`, that's the only key 

802 that will ever be returned. But in cases where you have set more than 

803 one type of host key (for example, an RSA key and a DSS key), the key 

804 type will be negotiated by the client, and this method will return the 

805 key of the type agreed on. If the host key has not been negotiated 

806 yet, ``None`` is returned. In client mode, the behavior is undefined. 

807 

808 :return: 

809 host key (`.PKey`) of the type negotiated by the client, or 

810 ``None``. 

811 """ 

812 try: 

813 return self.server_key_dict[self.host_key_type] 

814 except KeyError: 

815 pass 

816 return None 

817 

818 @staticmethod 

819 def load_server_moduli(filename=None): 

820 """ 

821 (optional) 

822 Load a file of prime moduli for use in doing group-exchange key 

823 negotiation in server mode. It's a rather obscure option and can be 

824 safely ignored. 

825 

826 In server mode, the remote client may request "group-exchange" key 

827 negotiation, which asks the server to send a random prime number that 

828 fits certain criteria. These primes are pretty difficult to compute, 

829 so they can't be generated on demand. But many systems contain a file 

830 of suitable primes (usually named something like ``/etc/ssh/moduli``). 

831 If you call `load_server_moduli` and it returns ``True``, then this 

832 file of primes has been loaded and we will support "group-exchange" in 

833 server mode. Otherwise server mode will just claim that it doesn't 

834 support that method of key negotiation. 

835 

836 :param str filename: 

837 optional path to the moduli file, if you happen to know that it's 

838 not in a standard location. 

839 :return: 

840 True if a moduli file was successfully loaded; False otherwise. 

841 

842 .. note:: This has no effect when used in client mode. 

843 """ 

844 Transport._modulus_pack = ModulusPack() 

845 # places to look for the openssh "moduli" file 

846 file_list = ["/etc/ssh/moduli", "/usr/local/etc/moduli"] 

847 if filename is not None: 

848 file_list.insert(0, filename) 

849 for fn in file_list: 

850 try: 

851 Transport._modulus_pack.read_file(fn) 

852 return True 

853 except IOError: 

854 pass 

855 # none succeeded 

856 Transport._modulus_pack = None 

857 return False 

858 

859 def close(self): 

860 """ 

861 Close this session, and any open channels that are tied to it. 

862 """ 

863 if not self.active: 

864 return 

865 self.stop_thread() 

866 for chan in list(self._channels.values()): 

867 chan._unlink() 

868 self.sock.close() 

869 

870 def get_remote_server_key(self): 

871 """ 

872 Return the host key of the server (in client mode). 

873 

874 .. note:: 

875 Previously this call returned a tuple of ``(key type, key 

876 string)``. You can get the same effect by calling `.PKey.get_name` 

877 for the key type, and ``str(key)`` for the key string. 

878 

879 :raises: `.SSHException` -- if no session is currently active. 

880 

881 :return: public key (`.PKey`) of the remote server 

882 """ 

883 if (not self.active) or (not self.initial_kex_done): 

884 raise SSHException("No existing session") 

885 return self.host_key 

886 

887 def is_active(self): 

888 """ 

889 Return true if this session is active (open). 

890 

891 :return: 

892 True if the session is still active (open); False if the session is 

893 closed 

894 """ 

895 return self.active 

896 

897 def open_session( 

898 self, window_size=None, max_packet_size=None, timeout=None 

899 ): 

900 """ 

901 Request a new channel to the server, of type ``"session"``. This is 

902 just an alias for calling `open_channel` with an argument of 

903 ``"session"``. 

904 

905 .. note:: Modifying the the window and packet sizes might have adverse 

906 effects on the session created. The default values are the same 

907 as in the OpenSSH code base and have been battle tested. 

908 

909 :param int window_size: 

910 optional window size for this session. 

911 :param int max_packet_size: 

912 optional max packet size for this session. 

913 

914 :return: a new `.Channel` 

915 

916 :raises: 

917 `.SSHException` -- if the request is rejected or the session ends 

918 prematurely 

919 

920 .. versionchanged:: 1.13.4/1.14.3/1.15.3 

921 Added the ``timeout`` argument. 

922 .. versionchanged:: 1.15 

923 Added the ``window_size`` and ``max_packet_size`` arguments. 

924 """ 

925 return self.open_channel( 

926 "session", 

927 window_size=window_size, 

928 max_packet_size=max_packet_size, 

929 timeout=timeout, 

930 ) 

931 

932 def open_x11_channel(self, src_addr=None): 

933 """ 

934 Request a new channel to the client, of type ``"x11"``. This 

935 is just an alias for ``open_channel('x11', src_addr=src_addr)``. 

936 

937 :param tuple src_addr: 

938 the source address (``(str, int)``) of the x11 server (port is the 

939 x11 port, ie. 6010) 

940 :return: a new `.Channel` 

941 

942 :raises: 

943 `.SSHException` -- if the request is rejected or the session ends 

944 prematurely 

945 """ 

946 return self.open_channel("x11", src_addr=src_addr) 

947 

948 def open_forward_agent_channel(self): 

949 """ 

950 Request a new channel to the client, of type 

951 ``"auth-agent@openssh.com"``. 

952 

953 This is just an alias for ``open_channel('auth-agent@openssh.com')``. 

954 

955 :return: a new `.Channel` 

956 

957 :raises: `.SSHException` -- 

958 if the request is rejected or the session ends prematurely 

959 """ 

960 return self.open_channel("auth-agent@openssh.com") 

961 

962 def open_forwarded_tcpip_channel(self, src_addr, dest_addr): 

963 """ 

964 Request a new channel back to the client, of type ``forwarded-tcpip``. 

965 

966 This is used after a client has requested port forwarding, for sending 

967 incoming connections back to the client. 

968 

969 :param src_addr: originator's address 

970 :param dest_addr: local (server) connected address 

971 """ 

972 return self.open_channel("forwarded-tcpip", dest_addr, src_addr) 

973 

974 def open_channel( 

975 self, 

976 kind, 

977 dest_addr=None, 

978 src_addr=None, 

979 window_size=None, 

980 max_packet_size=None, 

981 timeout=None, 

982 ): 

983 """ 

984 Request a new channel to the server. `Channels <.Channel>` are 

985 socket-like objects used for the actual transfer of data across the 

986 session. You may only request a channel after negotiating encryption 

987 (using `connect` or `start_client`) and authenticating. 

988 

989 .. note:: Modifying the the window and packet sizes might have adverse 

990 effects on the channel created. The default values are the same 

991 as in the OpenSSH code base and have been battle tested. 

992 

993 :param str kind: 

994 the kind of channel requested (usually ``"session"``, 

995 ``"forwarded-tcpip"``, ``"direct-tcpip"``, or ``"x11"``) 

996 :param tuple dest_addr: 

997 the destination address (address + port tuple) of this port 

998 forwarding, if ``kind`` is ``"forwarded-tcpip"`` or 

999 ``"direct-tcpip"`` (ignored for other channel types) 

1000 :param src_addr: the source address of this port forwarding, if 

1001 ``kind`` is ``"forwarded-tcpip"``, ``"direct-tcpip"``, or ``"x11"`` 

1002 :param int window_size: 

1003 optional window size for this session. 

1004 :param int max_packet_size: 

1005 optional max packet size for this session. 

1006 :param float timeout: 

1007 optional timeout opening a channel, default 3600s (1h) 

1008 

1009 :return: a new `.Channel` on success 

1010 

1011 :raises: 

1012 `.SSHException` -- if the request is rejected, the session ends 

1013 prematurely or there is a timeout opening a channel 

1014 

1015 .. versionchanged:: 1.15 

1016 Added the ``window_size`` and ``max_packet_size`` arguments. 

1017 """ 

1018 if not self.active: 

1019 raise SSHException("SSH session not active") 

1020 timeout = self.channel_timeout if timeout is None else timeout 

1021 self.lock.acquire() 

1022 try: 

1023 window_size = self._sanitize_window_size(window_size) 

1024 max_packet_size = self._sanitize_packet_size(max_packet_size) 

1025 chanid = self._next_channel() 

1026 m = Message() 

1027 m.add_byte(cMSG_CHANNEL_OPEN) 

1028 m.add_string(kind) 

1029 m.add_int(chanid) 

1030 m.add_int(window_size) 

1031 m.add_int(max_packet_size) 

1032 if (kind == "forwarded-tcpip") or (kind == "direct-tcpip"): 

1033 m.add_string(dest_addr[0]) 

1034 m.add_int(dest_addr[1]) 

1035 m.add_string(src_addr[0]) 

1036 m.add_int(src_addr[1]) 

1037 elif kind == "x11": 

1038 m.add_string(src_addr[0]) 

1039 m.add_int(src_addr[1]) 

1040 chan = Channel(chanid) 

1041 self._channels.put(chanid, chan) 

1042 self.channel_events[chanid] = event = threading.Event() 

1043 self.channels_seen[chanid] = True 

1044 chan._set_transport(self) 

1045 chan._set_window(window_size, max_packet_size) 

1046 finally: 

1047 self.lock.release() 

1048 self._send_user_message(m) 

1049 start_ts = time.time() 

1050 while True: 

1051 event.wait(0.1) 

1052 if not self.active: 

1053 e = self.get_exception() 

1054 if e is None: 

1055 e = SSHException("Unable to open channel.") 

1056 raise e 

1057 if event.is_set(): 

1058 break 

1059 elif start_ts + timeout < time.time(): 

1060 raise SSHException("Timeout opening channel.") 

1061 chan = self._channels.get(chanid) 

1062 if chan is not None: 

1063 return chan 

1064 e = self.get_exception() 

1065 if e is None: 

1066 e = SSHException("Unable to open channel.") 

1067 raise e 

1068 

1069 def request_port_forward(self, address, port, handler=None): 

1070 """ 

1071 Ask the server to forward TCP connections from a listening port on 

1072 the server, across this SSH session. 

1073 

1074 If a handler is given, that handler is called from a different thread 

1075 whenever a forwarded connection arrives. The handler parameters are:: 

1076 

1077 handler( 

1078 channel, 

1079 (origin_addr, origin_port), 

1080 (server_addr, server_port), 

1081 ) 

1082 

1083 where ``server_addr`` and ``server_port`` are the address and port that 

1084 the server was listening on. 

1085 

1086 If no handler is set, the default behavior is to send new incoming 

1087 forwarded connections into the accept queue, to be picked up via 

1088 `accept`. 

1089 

1090 :param str address: the address to bind when forwarding 

1091 :param int port: 

1092 the port to forward, or 0 to ask the server to allocate any port 

1093 :param callable handler: 

1094 optional handler for incoming forwarded connections, of the form 

1095 ``func(Channel, (str, int), (str, int))``. 

1096 

1097 :return: the port number (`int`) allocated by the server 

1098 

1099 :raises: 

1100 `.SSHException` -- if the server refused the TCP forward request 

1101 """ 

1102 if not self.active: 

1103 raise SSHException("SSH session not active") 

1104 port = int(port) 

1105 response = self.global_request( 

1106 "tcpip-forward", (address, port), wait=True 

1107 ) 

1108 if response is None: 

1109 raise SSHException("TCP forwarding request denied") 

1110 if port == 0: 

1111 port = response.get_int() 

1112 if handler is None: 

1113 

1114 def default_handler(channel, src_addr, dest_addr_port): 

1115 # src_addr, src_port = src_addr_port 

1116 # dest_addr, dest_port = dest_addr_port 

1117 self._queue_incoming_channel(channel) 

1118 

1119 handler = default_handler 

1120 self._tcp_handler = handler 

1121 return port 

1122 

1123 def cancel_port_forward(self, address, port): 

1124 """ 

1125 Ask the server to cancel a previous port-forwarding request. No more 

1126 connections to the given address & port will be forwarded across this 

1127 ssh connection. 

1128 

1129 :param str address: the address to stop forwarding 

1130 :param int port: the port to stop forwarding 

1131 """ 

1132 if not self.active: 

1133 return 

1134 self._tcp_handler = None 

1135 self.global_request("cancel-tcpip-forward", (address, port), wait=True) 

1136 

1137 def open_sftp_client(self): 

1138 """ 

1139 Create an SFTP client channel from an open transport. On success, an 

1140 SFTP session will be opened with the remote host, and a new 

1141 `.SFTPClient` object will be returned. 

1142 

1143 :return: 

1144 a new `.SFTPClient` referring to an sftp session (channel) across 

1145 this transport 

1146 """ 

1147 return SFTPClient.from_transport(self) 

1148 

1149 def send_ignore(self, byte_count=None): 

1150 """ 

1151 Send a junk packet across the encrypted link. This is sometimes used 

1152 to add "noise" to a connection to confuse would-be attackers. It can 

1153 also be used as a keep-alive for long lived connections traversing 

1154 firewalls. 

1155 

1156 :param int byte_count: 

1157 the number of random bytes to send in the payload of the ignored 

1158 packet -- defaults to a random number from 10 to 41. 

1159 """ 

1160 m = Message() 

1161 m.add_byte(cMSG_IGNORE) 

1162 if byte_count is None: 

1163 byte_count = (byte_ord(os.urandom(1)) % 32) + 10 

1164 m.add_bytes(os.urandom(byte_count)) 

1165 self._send_user_message(m) 

1166 

1167 def renegotiate_keys(self): 

1168 """ 

1169 Force this session to switch to new keys. Normally this is done 

1170 automatically after the session hits a certain number of packets or 

1171 bytes sent or received, but this method gives you the option of forcing 

1172 new keys whenever you want. Negotiating new keys causes a pause in 

1173 traffic both ways as the two sides swap keys and do computations. This 

1174 method returns when the session has switched to new keys. 

1175 

1176 :raises: 

1177 `.SSHException` -- if the key renegotiation failed (which causes 

1178 the session to end) 

1179 """ 

1180 self.completion_event = threading.Event() 

1181 self._send_kex_init() 

1182 while True: 

1183 self.completion_event.wait(0.1) 

1184 if not self.active: 

1185 e = self.get_exception() 

1186 if e is not None: 

1187 raise e 

1188 raise SSHException("Negotiation failed.") 

1189 if self.completion_event.is_set(): 

1190 break 

1191 return 

1192 

1193 def set_keepalive(self, interval): 

1194 """ 

1195 Turn on/off keepalive packets (default is off). If this is set, after 

1196 ``interval`` seconds without sending any data over the connection, a 

1197 "keepalive" packet will be sent (and ignored by the remote host). This 

1198 can be useful to keep connections alive over a NAT, for example. 

1199 

1200 :param int interval: 

1201 seconds to wait before sending a keepalive packet (or 

1202 0 to disable keepalives). 

1203 """ 

1204 

1205 def _request(x=weakref.proxy(self)): 

1206 return x.global_request("keepalive@lag.net", wait=False) 

1207 

1208 self.packetizer.set_keepalive(interval, _request) 

1209 

1210 def global_request(self, kind, data=None, wait=True): 

1211 """ 

1212 Make a global request to the remote host. These are normally 

1213 extensions to the SSH2 protocol. 

1214 

1215 :param str kind: name of the request. 

1216 :param tuple data: 

1217 an optional tuple containing additional data to attach to the 

1218 request. 

1219 :param bool wait: 

1220 ``True`` if this method should not return until a response is 

1221 received; ``False`` otherwise. 

1222 :return: 

1223 a `.Message` containing possible additional data if the request was 

1224 successful (or an empty `.Message` if ``wait`` was ``False``); 

1225 ``None`` if the request was denied. 

1226 """ 

1227 if wait: 

1228 self.completion_event = threading.Event() 

1229 m = Message() 

1230 m.add_byte(cMSG_GLOBAL_REQUEST) 

1231 m.add_string(kind) 

1232 m.add_boolean(wait) 

1233 if data is not None: 

1234 m.add(*data) 

1235 self._log(DEBUG, 'Sending global request "{}"'.format(kind)) 

1236 self._send_user_message(m) 

1237 if not wait: 

1238 return None 

1239 while True: 

1240 self.completion_event.wait(0.1) 

1241 if not self.active: 

1242 return None 

1243 if self.completion_event.is_set(): 

1244 break 

1245 return self.global_response 

1246 

1247 def accept(self, timeout=None): 

1248 """ 

1249 Return the next channel opened by the client over this transport, in 

1250 server mode. If no channel is opened before the given timeout, 

1251 ``None`` is returned. 

1252 

1253 :param int timeout: 

1254 seconds to wait for a channel, or ``None`` to wait forever 

1255 :return: a new `.Channel` opened by the client 

1256 """ 

1257 self.lock.acquire() 

1258 try: 

1259 if len(self.server_accepts) > 0: 

1260 chan = self.server_accepts.pop(0) 

1261 else: 

1262 self.server_accept_cv.wait(timeout) 

1263 if len(self.server_accepts) > 0: 

1264 chan = self.server_accepts.pop(0) 

1265 else: 

1266 # timeout 

1267 chan = None 

1268 finally: 

1269 self.lock.release() 

1270 return chan 

1271 

1272 def connect( 

1273 self, 

1274 hostkey=None, 

1275 username="", 

1276 password=None, 

1277 pkey=None, 

1278 gss_host=None, 

1279 gss_auth=False, 

1280 gss_kex=False, 

1281 gss_deleg_creds=True, 

1282 gss_trust_dns=True, 

1283 ): 

1284 """ 

1285 Negotiate an SSH2 session, and optionally verify the server's host key 

1286 and authenticate using a password or private key. This is a shortcut 

1287 for `start_client`, `get_remote_server_key`, and 

1288 `Transport.auth_password` or `Transport.auth_publickey`. Use those 

1289 methods if you want more control. 

1290 

1291 You can use this method immediately after creating a Transport to 

1292 negotiate encryption with a server. If it fails, an exception will be 

1293 thrown. On success, the method will return cleanly, and an encrypted 

1294 session exists. You may immediately call `open_channel` or 

1295 `open_session` to get a `.Channel` object, which is used for data 

1296 transfer. 

1297 

1298 .. note:: 

1299 If you fail to supply a password or private key, this method may 

1300 succeed, but a subsequent `open_channel` or `open_session` call may 

1301 fail because you haven't authenticated yet. 

1302 

1303 :param .PKey hostkey: 

1304 the host key expected from the server, or ``None`` if you don't 

1305 want to do host key verification. 

1306 :param str username: the username to authenticate as. 

1307 :param str password: 

1308 a password to use for authentication, if you want to use password 

1309 authentication; otherwise ``None``. 

1310 :param .PKey pkey: 

1311 a private key to use for authentication, if you want to use private 

1312 key authentication; otherwise ``None``. 

1313 :param str gss_host: 

1314 The target's name in the kerberos database. Default: hostname 

1315 :param bool gss_auth: 

1316 ``True`` if you want to use GSS-API authentication. 

1317 :param bool gss_kex: 

1318 Perform GSS-API Key Exchange and user authentication. 

1319 :param bool gss_deleg_creds: 

1320 Whether to delegate GSS-API client credentials. 

1321 :param gss_trust_dns: 

1322 Indicates whether or not the DNS is trusted to securely 

1323 canonicalize the name of the host being connected to (default 

1324 ``True``). 

1325 

1326 :raises: `.SSHException` -- if the SSH2 negotiation fails, the host key 

1327 supplied by the server is incorrect, or authentication fails. 

1328 

1329 .. versionchanged:: 2.3 

1330 Added the ``gss_trust_dns`` argument. 

1331 """ 

1332 if hostkey is not None: 

1333 # TODO: a more robust implementation would be to ask each key class 

1334 # for its nameS plural, and just use that. 

1335 # TODO: that could be used in a bunch of other spots too 

1336 if isinstance(hostkey, RSAKey): 

1337 self._preferred_keys = [ 

1338 "rsa-sha2-512", 

1339 "rsa-sha2-256", 

1340 "ssh-rsa", 

1341 ] 

1342 else: 

1343 self._preferred_keys = [hostkey.get_name()] 

1344 

1345 self.set_gss_host( 

1346 gss_host=gss_host, 

1347 trust_dns=gss_trust_dns, 

1348 gssapi_requested=gss_kex or gss_auth, 

1349 ) 

1350 

1351 self.start_client() 

1352 

1353 # check host key if we were given one 

1354 # If GSS-API Key Exchange was performed, we are not required to check 

1355 # the host key. 

1356 if (hostkey is not None) and not gss_kex: 

1357 key = self.get_remote_server_key() 

1358 if ( 

1359 key.get_name() != hostkey.get_name() 

1360 or key.asbytes() != hostkey.asbytes() 

1361 ): 

1362 self._log(DEBUG, "Bad host key from server") 

1363 self._log( 

1364 DEBUG, 

1365 "Expected: {}: {}".format( 

1366 hostkey.get_name(), repr(hostkey.asbytes()) 

1367 ), 

1368 ) 

1369 self._log( 

1370 DEBUG, 

1371 "Got : {}: {}".format( 

1372 key.get_name(), repr(key.asbytes()) 

1373 ), 

1374 ) 

1375 raise SSHException("Bad host key from server") 

1376 self._log( 

1377 DEBUG, "Host key verified ({})".format(hostkey.get_name()) 

1378 ) 

1379 

1380 if (pkey is not None) or (password is not None) or gss_auth or gss_kex: 

1381 if gss_auth: 

1382 self._log( 

1383 DEBUG, "Attempting GSS-API auth... (gssapi-with-mic)" 

1384 ) # noqa 

1385 self.auth_gssapi_with_mic( 

1386 username, self.gss_host, gss_deleg_creds 

1387 ) 

1388 elif gss_kex: 

1389 self._log(DEBUG, "Attempting GSS-API auth... (gssapi-keyex)") 

1390 self.auth_gssapi_keyex(username) 

1391 elif pkey is not None: 

1392 self._log(DEBUG, "Attempting public-key auth...") 

1393 self.auth_publickey(username, pkey) 

1394 else: 

1395 self._log(DEBUG, "Attempting password auth...") 

1396 self.auth_password(username, password) 

1397 

1398 return 

1399 

1400 def get_exception(self): 

1401 """ 

1402 Return any exception that happened during the last server request. 

1403 This can be used to fetch more specific error information after using 

1404 calls like `start_client`. The exception (if any) is cleared after 

1405 this call. 

1406 

1407 :return: 

1408 an exception, or ``None`` if there is no stored exception. 

1409 

1410 .. versionadded:: 1.1 

1411 """ 

1412 self.lock.acquire() 

1413 try: 

1414 e = self.saved_exception 

1415 self.saved_exception = None 

1416 return e 

1417 finally: 

1418 self.lock.release() 

1419 

1420 def set_subsystem_handler(self, name, handler, *args, **kwargs): 

1421 """ 

1422 Set the handler class for a subsystem in server mode. If a request 

1423 for this subsystem is made on an open ssh channel later, this handler 

1424 will be constructed and called -- see `.SubsystemHandler` for more 

1425 detailed documentation. 

1426 

1427 Any extra parameters (including keyword arguments) are saved and 

1428 passed to the `.SubsystemHandler` constructor later. 

1429 

1430 :param str name: name of the subsystem. 

1431 :param handler: 

1432 subclass of `.SubsystemHandler` that handles this subsystem. 

1433 """ 

1434 try: 

1435 self.lock.acquire() 

1436 self.subsystem_table[name] = (handler, args, kwargs) 

1437 finally: 

1438 self.lock.release() 

1439 

1440 def is_authenticated(self): 

1441 """ 

1442 Return true if this session is active and authenticated. 

1443 

1444 :return: 

1445 True if the session is still open and has been authenticated 

1446 successfully; False if authentication failed and/or the session is 

1447 closed. 

1448 """ 

1449 return ( 

1450 self.active 

1451 and self.auth_handler is not None 

1452 and self.auth_handler.is_authenticated() 

1453 ) 

1454 

1455 def get_username(self): 

1456 """ 

1457 Return the username this connection is authenticated for. If the 

1458 session is not authenticated (or authentication failed), this method 

1459 returns ``None``. 

1460 

1461 :return: username that was authenticated (a `str`), or ``None``. 

1462 """ 

1463 if not self.active or (self.auth_handler is None): 

1464 return None 

1465 return self.auth_handler.get_username() 

1466 

1467 def get_banner(self): 

1468 """ 

1469 Return the banner supplied by the server upon connect. If no banner is 

1470 supplied, this method returns ``None``. 

1471 

1472 :returns: server supplied banner (`str`), or ``None``. 

1473 

1474 .. versionadded:: 1.13 

1475 """ 

1476 if not self.active or (self.auth_handler is None): 

1477 return None 

1478 return self.auth_handler.banner 

1479 

1480 def auth_none(self, username): 

1481 """ 

1482 Try to authenticate to the server using no authentication at all. 

1483 This will almost always fail. It may be useful for determining the 

1484 list of authentication types supported by the server, by catching the 

1485 `.BadAuthenticationType` exception raised. 

1486 

1487 :param str username: the username to authenticate as 

1488 :return: 

1489 list of auth types permissible for the next stage of 

1490 authentication (normally empty) 

1491 

1492 :raises: 

1493 `.BadAuthenticationType` -- if "none" authentication isn't allowed 

1494 by the server for this user 

1495 :raises: 

1496 `.SSHException` -- if the authentication failed due to a network 

1497 error 

1498 

1499 .. versionadded:: 1.5 

1500 """ 

1501 if (not self.active) or (not self.initial_kex_done): 

1502 raise SSHException("No existing session") 

1503 my_event = threading.Event() 

1504 self.auth_handler = AuthHandler(self) 

1505 self.auth_handler.auth_none(username, my_event) 

1506 return self.auth_handler.wait_for_response(my_event) 

1507 

1508 def auth_password(self, username, password, event=None, fallback=True): 

1509 """ 

1510 Authenticate to the server using a password. The username and password 

1511 are sent over an encrypted link. 

1512 

1513 If an ``event`` is passed in, this method will return immediately, and 

1514 the event will be triggered once authentication succeeds or fails. On 

1515 success, `is_authenticated` will return ``True``. On failure, you may 

1516 use `get_exception` to get more detailed error information. 

1517 

1518 Since 1.1, if no event is passed, this method will block until the 

1519 authentication succeeds or fails. On failure, an exception is raised. 

1520 Otherwise, the method simply returns. 

1521 

1522 Since 1.5, if no event is passed and ``fallback`` is ``True`` (the 

1523 default), if the server doesn't support plain password authentication 

1524 but does support so-called "keyboard-interactive" mode, an attempt 

1525 will be made to authenticate using this interactive mode. If it fails, 

1526 the normal exception will be thrown as if the attempt had never been 

1527 made. This is useful for some recent Gentoo and Debian distributions, 

1528 which turn off plain password authentication in a misguided belief 

1529 that interactive authentication is "more secure". (It's not.) 

1530 

1531 If the server requires multi-step authentication (which is very rare), 

1532 this method will return a list of auth types permissible for the next 

1533 step. Otherwise, in the normal case, an empty list is returned. 

1534 

1535 :param str username: the username to authenticate as 

1536 :param basestring password: the password to authenticate with 

1537 :param .threading.Event event: 

1538 an event to trigger when the authentication attempt is complete 

1539 (whether it was successful or not) 

1540 :param bool fallback: 

1541 ``True`` if an attempt at an automated "interactive" password auth 

1542 should be made if the server doesn't support normal password auth 

1543 :return: 

1544 list of auth types permissible for the next stage of 

1545 authentication (normally empty) 

1546 

1547 :raises: 

1548 `.BadAuthenticationType` -- if password authentication isn't 

1549 allowed by the server for this user (and no event was passed in) 

1550 :raises: 

1551 `.AuthenticationException` -- if the authentication failed (and no 

1552 event was passed in) 

1553 :raises: `.SSHException` -- if there was a network error 

1554 """ 

1555 if (not self.active) or (not self.initial_kex_done): 

1556 # we should never try to send the password unless we're on a secure 

1557 # link 

1558 raise SSHException("No existing session") 

1559 if event is None: 

1560 my_event = threading.Event() 

1561 else: 

1562 my_event = event 

1563 self.auth_handler = AuthHandler(self) 

1564 self.auth_handler.auth_password(username, password, my_event) 

1565 if event is not None: 

1566 # caller wants to wait for event themselves 

1567 return [] 

1568 try: 

1569 return self.auth_handler.wait_for_response(my_event) 

1570 except BadAuthenticationType as e: 

1571 # if password auth isn't allowed, but keyboard-interactive *is*, 

1572 # try to fudge it 

1573 if not fallback or ("keyboard-interactive" not in e.allowed_types): 

1574 raise 

1575 try: 

1576 

1577 def handler(title, instructions, fields): 

1578 if len(fields) > 1: 

1579 raise SSHException("Fallback authentication failed.") 

1580 if len(fields) == 0: 

1581 # for some reason, at least on os x, a 2nd request will 

1582 # be made with zero fields requested. maybe it's just 

1583 # to try to fake out automated scripting of the exact 

1584 # type we're doing here. *shrug* :) 

1585 return [] 

1586 return [password] 

1587 

1588 return self.auth_interactive(username, handler) 

1589 except SSHException: 

1590 # attempt failed; just raise the original exception 

1591 raise e 

1592 

1593 def auth_publickey(self, username, key, event=None): 

1594 """ 

1595 Authenticate to the server using a private key. The key is used to 

1596 sign data from the server, so it must include the private part. 

1597 

1598 If an ``event`` is passed in, this method will return immediately, and 

1599 the event will be triggered once authentication succeeds or fails. On 

1600 success, `is_authenticated` will return ``True``. On failure, you may 

1601 use `get_exception` to get more detailed error information. 

1602 

1603 Since 1.1, if no event is passed, this method will block until the 

1604 authentication succeeds or fails. On failure, an exception is raised. 

1605 Otherwise, the method simply returns. 

1606 

1607 If the server requires multi-step authentication (which is very rare), 

1608 this method will return a list of auth types permissible for the next 

1609 step. Otherwise, in the normal case, an empty list is returned. 

1610 

1611 :param str username: the username to authenticate as 

1612 :param .PKey key: the private key to authenticate with 

1613 :param .threading.Event event: 

1614 an event to trigger when the authentication attempt is complete 

1615 (whether it was successful or not) 

1616 :return: 

1617 list of auth types permissible for the next stage of 

1618 authentication (normally empty) 

1619 

1620 :raises: 

1621 `.BadAuthenticationType` -- if public-key authentication isn't 

1622 allowed by the server for this user (and no event was passed in) 

1623 :raises: 

1624 `.AuthenticationException` -- if the authentication failed (and no 

1625 event was passed in) 

1626 :raises: `.SSHException` -- if there was a network error 

1627 """ 

1628 if (not self.active) or (not self.initial_kex_done): 

1629 # we should never try to authenticate unless we're on a secure link 

1630 raise SSHException("No existing session") 

1631 if event is None: 

1632 my_event = threading.Event() 

1633 else: 

1634 my_event = event 

1635 self.auth_handler = AuthHandler(self) 

1636 self.auth_handler.auth_publickey(username, key, my_event) 

1637 if event is not None: 

1638 # caller wants to wait for event themselves 

1639 return [] 

1640 return self.auth_handler.wait_for_response(my_event) 

1641 

1642 def auth_interactive(self, username, handler, submethods=""): 

1643 """ 

1644 Authenticate to the server interactively. A handler is used to answer 

1645 arbitrary questions from the server. On many servers, this is just a 

1646 dumb wrapper around PAM. 

1647 

1648 This method will block until the authentication succeeds or fails, 

1649 peroidically calling the handler asynchronously to get answers to 

1650 authentication questions. The handler may be called more than once 

1651 if the server continues to ask questions. 

1652 

1653 The handler is expected to be a callable that will handle calls of the 

1654 form: ``handler(title, instructions, prompt_list)``. The ``title`` is 

1655 meant to be a dialog-window title, and the ``instructions`` are user 

1656 instructions (both are strings). ``prompt_list`` will be a list of 

1657 prompts, each prompt being a tuple of ``(str, bool)``. The string is 

1658 the prompt and the boolean indicates whether the user text should be 

1659 echoed. 

1660 

1661 A sample call would thus be: 

1662 ``handler('title', 'instructions', [('Password:', False)])``. 

1663 

1664 The handler should return a list or tuple of answers to the server's 

1665 questions. 

1666 

1667 If the server requires multi-step authentication (which is very rare), 

1668 this method will return a list of auth types permissible for the next 

1669 step. Otherwise, in the normal case, an empty list is returned. 

1670 

1671 :param str username: the username to authenticate as 

1672 :param callable handler: a handler for responding to server questions 

1673 :param str submethods: a string list of desired submethods (optional) 

1674 :return: 

1675 list of auth types permissible for the next stage of 

1676 authentication (normally empty). 

1677 

1678 :raises: `.BadAuthenticationType` -- if public-key authentication isn't 

1679 allowed by the server for this user 

1680 :raises: `.AuthenticationException` -- if the authentication failed 

1681 :raises: `.SSHException` -- if there was a network error 

1682 

1683 .. versionadded:: 1.5 

1684 """ 

1685 if (not self.active) or (not self.initial_kex_done): 

1686 # we should never try to authenticate unless we're on a secure link 

1687 raise SSHException("No existing session") 

1688 my_event = threading.Event() 

1689 self.auth_handler = AuthHandler(self) 

1690 self.auth_handler.auth_interactive( 

1691 username, handler, my_event, submethods 

1692 ) 

1693 return self.auth_handler.wait_for_response(my_event) 

1694 

1695 def auth_interactive_dumb(self, username, handler=None, submethods=""): 

1696 """ 

1697 Authenticate to the server interactively but dumber. 

1698 Just print the prompt and / or instructions to stdout and send back 

1699 the response. This is good for situations where partial auth is 

1700 achieved by key and then the user has to enter a 2fac token. 

1701 """ 

1702 

1703 if not handler: 

1704 

1705 def handler(title, instructions, prompt_list): 

1706 answers = [] 

1707 if title: 

1708 print(title.strip()) 

1709 if instructions: 

1710 print(instructions.strip()) 

1711 for prompt, show_input in prompt_list: 

1712 print(prompt.strip(), end=" ") 

1713 answers.append(input()) 

1714 return answers 

1715 

1716 return self.auth_interactive(username, handler, submethods) 

1717 

1718 def auth_gssapi_with_mic(self, username, gss_host, gss_deleg_creds): 

1719 """ 

1720 Authenticate to the Server using GSS-API / SSPI. 

1721 

1722 :param str username: The username to authenticate as 

1723 :param str gss_host: The target host 

1724 :param bool gss_deleg_creds: Delegate credentials or not 

1725 :return: list of auth types permissible for the next stage of 

1726 authentication (normally empty) 

1727 :raises: `.BadAuthenticationType` -- if gssapi-with-mic isn't 

1728 allowed by the server (and no event was passed in) 

1729 :raises: 

1730 `.AuthenticationException` -- if the authentication failed (and no 

1731 event was passed in) 

1732 :raises: `.SSHException` -- if there was a network error 

1733 """ 

1734 if (not self.active) or (not self.initial_kex_done): 

1735 # we should never try to authenticate unless we're on a secure link 

1736 raise SSHException("No existing session") 

1737 my_event = threading.Event() 

1738 self.auth_handler = AuthHandler(self) 

1739 self.auth_handler.auth_gssapi_with_mic( 

1740 username, gss_host, gss_deleg_creds, my_event 

1741 ) 

1742 return self.auth_handler.wait_for_response(my_event) 

1743 

1744 def auth_gssapi_keyex(self, username): 

1745 """ 

1746 Authenticate to the server with GSS-API/SSPI if GSS-API kex is in use. 

1747 

1748 :param str username: The username to authenticate as. 

1749 :returns: 

1750 a list of auth types permissible for the next stage of 

1751 authentication (normally empty) 

1752 :raises: `.BadAuthenticationType` -- 

1753 if GSS-API Key Exchange was not performed (and no event was passed 

1754 in) 

1755 :raises: `.AuthenticationException` -- 

1756 if the authentication failed (and no event was passed in) 

1757 :raises: `.SSHException` -- if there was a network error 

1758 """ 

1759 if (not self.active) or (not self.initial_kex_done): 

1760 # we should never try to authenticate unless we're on a secure link 

1761 raise SSHException("No existing session") 

1762 my_event = threading.Event() 

1763 self.auth_handler = AuthHandler(self) 

1764 self.auth_handler.auth_gssapi_keyex(username, my_event) 

1765 return self.auth_handler.wait_for_response(my_event) 

1766 

1767 def set_log_channel(self, name): 

1768 """ 

1769 Set the channel for this transport's logging. The default is 

1770 ``"paramiko.transport"`` but it can be set to anything you want. (See 

1771 the `.logging` module for more info.) SSH Channels will log to a 

1772 sub-channel of the one specified. 

1773 

1774 :param str name: new channel name for logging 

1775 

1776 .. versionadded:: 1.1 

1777 """ 

1778 self.log_name = name 

1779 self.logger = util.get_logger(name) 

1780 self.packetizer.set_log(self.logger) 

1781 

1782 def get_log_channel(self): 

1783 """ 

1784 Return the channel name used for this transport's logging. 

1785 

1786 :return: channel name as a `str` 

1787 

1788 .. versionadded:: 1.2 

1789 """ 

1790 return self.log_name 

1791 

1792 def set_hexdump(self, hexdump): 

1793 """ 

1794 Turn on/off logging a hex dump of protocol traffic at DEBUG level in 

1795 the logs. Normally you would want this off (which is the default), 

1796 but if you are debugging something, it may be useful. 

1797 

1798 :param bool hexdump: 

1799 ``True`` to log protocol traffix (in hex) to the log; ``False`` 

1800 otherwise. 

1801 """ 

1802 self.packetizer.set_hexdump(hexdump) 

1803 

1804 def get_hexdump(self): 

1805 """ 

1806 Return ``True`` if the transport is currently logging hex dumps of 

1807 protocol traffic. 

1808 

1809 :return: ``True`` if hex dumps are being logged, else ``False``. 

1810 

1811 .. versionadded:: 1.4 

1812 """ 

1813 return self.packetizer.get_hexdump() 

1814 

1815 def use_compression(self, compress=True): 

1816 """ 

1817 Turn on/off compression. This will only have an affect before starting 

1818 the transport (ie before calling `connect`, etc). By default, 

1819 compression is off since it negatively affects interactive sessions. 

1820 

1821 :param bool compress: 

1822 ``True`` to ask the remote client/server to compress traffic; 

1823 ``False`` to refuse compression 

1824 

1825 .. versionadded:: 1.5.2 

1826 """ 

1827 if compress: 

1828 self._preferred_compression = ("zlib@openssh.com", "zlib", "none") 

1829 else: 

1830 self._preferred_compression = ("none",) 

1831 

1832 def getpeername(self): 

1833 """ 

1834 Return the address of the remote side of this Transport, if possible. 

1835 

1836 This is effectively a wrapper around ``getpeername`` on the underlying 

1837 socket. If the socket-like object has no ``getpeername`` method, then 

1838 ``("unknown", 0)`` is returned. 

1839 

1840 :return: 

1841 the address of the remote host, if known, as a ``(str, int)`` 

1842 tuple. 

1843 """ 

1844 gp = getattr(self.sock, "getpeername", None) 

1845 if gp is None: 

1846 return "unknown", 0 

1847 return gp() 

1848 

1849 def stop_thread(self): 

1850 self.active = False 

1851 self.packetizer.close() 

1852 # Keep trying to join() our main thread, quickly, until: 

1853 # * We join()ed successfully (self.is_alive() == False) 

1854 # * Or it looks like we've hit issue #520 (socket.recv hitting some 

1855 # race condition preventing it from timing out correctly), wherein 

1856 # our socket and packetizer are both closed (but where we'd 

1857 # otherwise be sitting forever on that recv()). 

1858 while ( 

1859 self.is_alive() 

1860 and self is not threading.current_thread() 

1861 and not self.sock._closed 

1862 and not self.packetizer.closed 

1863 ): 

1864 self.join(0.1) 

1865 

1866 # internals... 

1867 

1868 def _log(self, level, msg, *args): 

1869 if issubclass(type(msg), list): 

1870 for m in msg: 

1871 self.logger.log(level, m) 

1872 else: 

1873 self.logger.log(level, msg, *args) 

1874 

1875 def _get_modulus_pack(self): 

1876 """used by KexGex to find primes for group exchange""" 

1877 return self._modulus_pack 

1878 

1879 def _next_channel(self): 

1880 """you are holding the lock""" 

1881 chanid = self._channel_counter 

1882 while self._channels.get(chanid) is not None: 

1883 self._channel_counter = (self._channel_counter + 1) & 0xFFFFFF 

1884 chanid = self._channel_counter 

1885 self._channel_counter = (self._channel_counter + 1) & 0xFFFFFF 

1886 return chanid 

1887 

1888 def _unlink_channel(self, chanid): 

1889 """used by a Channel to remove itself from the active channel list""" 

1890 self._channels.delete(chanid) 

1891 

1892 def _send_message(self, data): 

1893 self.packetizer.send_message(data) 

1894 

1895 def _send_user_message(self, data): 

1896 """ 

1897 send a message, but block if we're in key negotiation. this is used 

1898 for user-initiated requests. 

1899 """ 

1900 start = time.time() 

1901 while True: 

1902 self.clear_to_send.wait(0.1) 

1903 if not self.active: 

1904 self._log( 

1905 DEBUG, "Dropping user packet because connection is dead." 

1906 ) # noqa 

1907 return 

1908 self.clear_to_send_lock.acquire() 

1909 if self.clear_to_send.is_set(): 

1910 break 

1911 self.clear_to_send_lock.release() 

1912 if time.time() > start + self.clear_to_send_timeout: 

1913 raise SSHException( 

1914 "Key-exchange timed out waiting for key negotiation" 

1915 ) # noqa 

1916 try: 

1917 self._send_message(data) 

1918 finally: 

1919 self.clear_to_send_lock.release() 

1920 

1921 def _set_K_H(self, k, h): 

1922 """ 

1923 Used by a kex obj to set the K (root key) and H (exchange hash). 

1924 """ 

1925 self.K = k 

1926 self.H = h 

1927 if self.session_id is None: 

1928 self.session_id = h 

1929 

1930 def _expect_packet(self, *ptypes): 

1931 """ 

1932 Used by a kex obj to register the next packet type it expects to see. 

1933 """ 

1934 self._expected_packet = tuple(ptypes) 

1935 

1936 def _verify_key(self, host_key, sig): 

1937 key = self._key_info[self.host_key_type](Message(host_key)) 

1938 if key is None: 

1939 raise SSHException("Unknown host key type") 

1940 if not key.verify_ssh_sig(self.H, Message(sig)): 

1941 raise SSHException( 

1942 "Signature verification ({}) failed.".format( 

1943 self.host_key_type 

1944 ) 

1945 ) # noqa 

1946 self.host_key = key 

1947 

1948 def _compute_key(self, id, nbytes): 

1949 """id is 'A' - 'F' for the various keys used by ssh""" 

1950 m = Message() 

1951 m.add_mpint(self.K) 

1952 m.add_bytes(self.H) 

1953 m.add_byte(b(id)) 

1954 m.add_bytes(self.session_id) 

1955 # Fallback to SHA1 for kex engines that fail to specify a hex 

1956 # algorithm, or for e.g. transport tests that don't run kexinit. 

1957 hash_algo = getattr(self.kex_engine, "hash_algo", None) 

1958 hash_select_msg = "kex engine {} specified hash_algo {!r}".format( 

1959 self.kex_engine.__class__.__name__, hash_algo 

1960 ) 

1961 if hash_algo is None: 

1962 hash_algo = sha1 

1963 hash_select_msg += ", falling back to sha1" 

1964 if not hasattr(self, "_logged_hash_selection"): 

1965 self._log(DEBUG, hash_select_msg) 

1966 setattr(self, "_logged_hash_selection", True) 

1967 out = sofar = hash_algo(m.asbytes()).digest() 

1968 while len(out) < nbytes: 

1969 m = Message() 

1970 m.add_mpint(self.K) 

1971 m.add_bytes(self.H) 

1972 m.add_bytes(sofar) 

1973 digest = hash_algo(m.asbytes()).digest() 

1974 out += digest 

1975 sofar += digest 

1976 return out[:nbytes] 

1977 

1978 def _get_cipher(self, name, key, iv, operation): 

1979 if name not in self._cipher_info: 

1980 raise SSHException("Unknown client cipher " + name) 

1981 else: 

1982 cipher = Cipher( 

1983 self._cipher_info[name]["class"](key), 

1984 self._cipher_info[name]["mode"](iv), 

1985 backend=default_backend(), 

1986 ) 

1987 if operation is self._ENCRYPT: 

1988 return cipher.encryptor() 

1989 else: 

1990 return cipher.decryptor() 

1991 

1992 def _set_forward_agent_handler(self, handler): 

1993 if handler is None: 

1994 

1995 def default_handler(channel): 

1996 self._queue_incoming_channel(channel) 

1997 

1998 self._forward_agent_handler = default_handler 

1999 else: 

2000 self._forward_agent_handler = handler 

2001 

2002 def _set_x11_handler(self, handler): 

2003 # only called if a channel has turned on x11 forwarding 

2004 if handler is None: 

2005 # by default, use the same mechanism as accept() 

2006 def default_handler(channel, src_addr_port): 

2007 self._queue_incoming_channel(channel) 

2008 

2009 self._x11_handler = default_handler 

2010 else: 

2011 self._x11_handler = handler 

2012 

2013 def _queue_incoming_channel(self, channel): 

2014 self.lock.acquire() 

2015 try: 

2016 self.server_accepts.append(channel) 

2017 self.server_accept_cv.notify() 

2018 finally: 

2019 self.lock.release() 

2020 

2021 def _sanitize_window_size(self, window_size): 

2022 if window_size is None: 

2023 window_size = self.default_window_size 

2024 return clamp_value(MIN_WINDOW_SIZE, window_size, MAX_WINDOW_SIZE) 

2025 

2026 def _sanitize_packet_size(self, max_packet_size): 

2027 if max_packet_size is None: 

2028 max_packet_size = self.default_max_packet_size 

2029 return clamp_value(MIN_PACKET_SIZE, max_packet_size, MAX_WINDOW_SIZE) 

2030 

2031 def _ensure_authed(self, ptype, message): 

2032 """ 

2033 Checks message type against current auth state. 

2034 

2035 If server mode, and auth has not succeeded, and the message is of a 

2036 post-auth type (channel open or global request) an appropriate error 

2037 response Message is crafted and returned to caller for sending. 

2038 

2039 Otherwise (client mode, authed, or pre-auth message) returns None. 

2040 """ 

2041 if ( 

2042 not self.server_mode 

2043 or ptype <= HIGHEST_USERAUTH_MESSAGE_ID 

2044 or self.is_authenticated() 

2045 ): 

2046 return None 

2047 # WELP. We must be dealing with someone trying to do non-auth things 

2048 # without being authed. Tell them off, based on message class. 

2049 reply = Message() 

2050 # Global requests have no details, just failure. 

2051 if ptype == MSG_GLOBAL_REQUEST: 

2052 reply.add_byte(cMSG_REQUEST_FAILURE) 

2053 # Channel opens let us reject w/ a specific type + message. 

2054 elif ptype == MSG_CHANNEL_OPEN: 

2055 kind = message.get_text() # noqa 

2056 chanid = message.get_int() 

2057 reply.add_byte(cMSG_CHANNEL_OPEN_FAILURE) 

2058 reply.add_int(chanid) 

2059 reply.add_int(OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED) 

2060 reply.add_string("") 

2061 reply.add_string("en") 

2062 # NOTE: Post-open channel messages do not need checking; the above will 

2063 # reject attempts to open channels, meaning that even if a malicious 

2064 # user tries to send a MSG_CHANNEL_REQUEST, it will simply fall under 

2065 # the logic that handles unknown channel IDs (as the channel list will 

2066 # be empty.) 

2067 return reply 

2068 

2069 def run(self): 

2070 # (use the exposed "run" method, because if we specify a thread target 

2071 # of a private method, threading.Thread will keep a reference to it 

2072 # indefinitely, creating a GC cycle and not letting Transport ever be 

2073 # GC'd. it's a bug in Thread.) 

2074 

2075 # Hold reference to 'sys' so we can test sys.modules to detect 

2076 # interpreter shutdown. 

2077 self.sys = sys 

2078 

2079 # active=True occurs before the thread is launched, to avoid a race 

2080 _active_threads.append(self) 

2081 tid = hex(id(self) & xffffffff) 

2082 if self.server_mode: 

2083 self._log(DEBUG, "starting thread (server mode): {}".format(tid)) 

2084 else: 

2085 self._log(DEBUG, "starting thread (client mode): {}".format(tid)) 

2086 try: 

2087 try: 

2088 self.packetizer.write_all(b(self.local_version + "\r\n")) 

2089 self._log( 

2090 DEBUG, 

2091 "Local version/idstring: {}".format(self.local_version), 

2092 ) # noqa 

2093 self._check_banner() 

2094 # The above is actually very much part of the handshake, but 

2095 # sometimes the banner can be read but the machine is not 

2096 # responding, for example when the remote ssh daemon is loaded 

2097 # in to memory but we can not read from the disk/spawn a new 

2098 # shell. 

2099 # Make sure we can specify a timeout for the initial handshake. 

2100 # Re-use the banner timeout for now. 

2101 self.packetizer.start_handshake(self.handshake_timeout) 

2102 self._send_kex_init() 

2103 self._expect_packet(MSG_KEXINIT) 

2104 

2105 while self.active: 

2106 if self.packetizer.need_rekey() and not self.in_kex: 

2107 self._send_kex_init() 

2108 try: 

2109 ptype, m = self.packetizer.read_message() 

2110 except NeedRekeyException: 

2111 continue 

2112 if ptype == MSG_IGNORE: 

2113 continue 

2114 elif ptype == MSG_DISCONNECT: 

2115 self._parse_disconnect(m) 

2116 break 

2117 elif ptype == MSG_DEBUG: 

2118 self._parse_debug(m) 

2119 continue 

2120 if len(self._expected_packet) > 0: 

2121 if ptype not in self._expected_packet: 

2122 raise SSHException( 

2123 "Expecting packet from {!r}, got {:d}".format( 

2124 self._expected_packet, ptype 

2125 ) 

2126 ) # noqa 

2127 self._expected_packet = tuple() 

2128 if (ptype >= 30) and (ptype <= 41): 

2129 self.kex_engine.parse_next(ptype, m) 

2130 continue 

2131 

2132 if ptype in self._handler_table: 

2133 error_msg = self._ensure_authed(ptype, m) 

2134 if error_msg: 

2135 self._send_message(error_msg) 

2136 else: 

2137 self._handler_table[ptype](self, m) 

2138 elif ptype in self._channel_handler_table: 

2139 chanid = m.get_int() 

2140 chan = self._channels.get(chanid) 

2141 if chan is not None: 

2142 self._channel_handler_table[ptype](chan, m) 

2143 elif chanid in self.channels_seen: 

2144 self._log( 

2145 DEBUG, 

2146 "Ignoring message for dead channel {:d}".format( # noqa 

2147 chanid 

2148 ), 

2149 ) 

2150 else: 

2151 self._log( 

2152 ERROR, 

2153 "Channel request for unknown channel {:d}".format( # noqa 

2154 chanid 

2155 ), 

2156 ) 

2157 break 

2158 elif ( 

2159 self.auth_handler is not None 

2160 and ptype in self.auth_handler._handler_table 

2161 ): 

2162 handler = self.auth_handler._handler_table[ptype] 

2163 handler(self.auth_handler, m) 

2164 if len(self._expected_packet) > 0: 

2165 continue 

2166 else: 

2167 # Respond with "I don't implement this particular 

2168 # message type" message (unless the message type was 

2169 # itself literally MSG_UNIMPLEMENTED, in which case, we 

2170 # just shut up to avoid causing a useless loop). 

2171 name = MSG_NAMES[ptype] 

2172 warning = "Oops, unhandled type {} ({!r})".format( 

2173 ptype, name 

2174 ) 

2175 self._log(WARNING, warning) 

2176 if ptype != MSG_UNIMPLEMENTED: 

2177 msg = Message() 

2178 msg.add_byte(cMSG_UNIMPLEMENTED) 

2179 msg.add_int(m.seqno) 

2180 self._send_message(msg) 

2181 self.packetizer.complete_handshake() 

2182 except SSHException as e: 

2183 self._log( 

2184 ERROR, 

2185 "Exception ({}): {}".format( 

2186 "server" if self.server_mode else "client", e 

2187 ), 

2188 ) 

2189 self._log(ERROR, util.tb_strings()) 

2190 self.saved_exception = e 

2191 except EOFError as e: 

2192 self._log(DEBUG, "EOF in transport thread") 

2193 self.saved_exception = e 

2194 except socket.error as e: 

2195 if type(e.args) is tuple: 

2196 if e.args: 

2197 emsg = "{} ({:d})".format(e.args[1], e.args[0]) 

2198 else: # empty tuple, e.g. socket.timeout 

2199 emsg = str(e) or repr(e) 

2200 else: 

2201 emsg = e.args 

2202 self._log(ERROR, "Socket exception: " + emsg) 

2203 self.saved_exception = e 

2204 except Exception as e: 

2205 self._log(ERROR, "Unknown exception: " + str(e)) 

2206 self._log(ERROR, util.tb_strings()) 

2207 self.saved_exception = e 

2208 _active_threads.remove(self) 

2209 for chan in list(self._channels.values()): 

2210 chan._unlink() 

2211 if self.active: 

2212 self.active = False 

2213 self.packetizer.close() 

2214 if self.completion_event is not None: 

2215 self.completion_event.set() 

2216 if self.auth_handler is not None: 

2217 self.auth_handler.abort() 

2218 for event in self.channel_events.values(): 

2219 event.set() 

2220 try: 

2221 self.lock.acquire() 

2222 self.server_accept_cv.notify() 

2223 finally: 

2224 self.lock.release() 

2225 self.sock.close() 

2226 except: 

2227 # Don't raise spurious 'NoneType has no attribute X' errors when we 

2228 # wake up during interpreter shutdown. Or rather -- raise 

2229 # everything *if* sys.modules (used as a convenient sentinel) 

2230 # appears to still exist. 

2231 if self.sys.modules is not None: 

2232 raise 

2233 

2234 def _log_agreement(self, which, local, remote): 

2235 # Log useful, non-duplicative line re: an agreed-upon algorithm. 

2236 # Old code implied algorithms could be asymmetrical (different for 

2237 # inbound vs outbound) so we preserve that possibility. 

2238 msg = "{}: ".format(which) 

2239 if local == remote: 

2240 msg += local 

2241 else: 

2242 msg += "local={}, remote={}".format(local, remote) 

2243 self._log(DEBUG, msg) 

2244 

2245 # protocol stages 

2246 

2247 def _negotiate_keys(self, m): 

2248 # throws SSHException on anything unusual 

2249 self.clear_to_send_lock.acquire() 

2250 try: 

2251 self.clear_to_send.clear() 

2252 finally: 

2253 self.clear_to_send_lock.release() 

2254 if self.local_kex_init is None: 

2255 # remote side wants to renegotiate 

2256 self._send_kex_init() 

2257 self._parse_kex_init(m) 

2258 self.kex_engine.start_kex() 

2259 

2260 def _check_banner(self): 

2261 # this is slow, but we only have to do it once 

2262 for i in range(100): 

2263 # give them 15 seconds for the first line, then just 2 seconds 

2264 # each additional line. (some sites have very high latency.) 

2265 if i == 0: 

2266 timeout = self.banner_timeout 

2267 else: 

2268 timeout = 2 

2269 try: 

2270 buf = self.packetizer.readline(timeout) 

2271 except ProxyCommandFailure: 

2272 raise 

2273 except Exception as e: 

2274 raise SSHException( 

2275 "Error reading SSH protocol banner" + str(e) 

2276 ) 

2277 if buf[:4] == "SSH-": 

2278 break 

2279 self._log(DEBUG, "Banner: " + buf) 

2280 if buf[:4] != "SSH-": 

2281 raise SSHException('Indecipherable protocol version "' + buf + '"') 

2282 # save this server version string for later 

2283 self.remote_version = buf 

2284 self._log(DEBUG, "Remote version/idstring: {}".format(buf)) 

2285 # pull off any attached comment 

2286 # NOTE: comment used to be stored in a variable and then...never used. 

2287 # since 2003. ca 877cd974b8182d26fa76d566072917ea67b64e67 

2288 i = buf.find(" ") 

2289 if i >= 0: 

2290 buf = buf[:i] 

2291 # parse out version string and make sure it matches 

2292 segs = buf.split("-", 2) 

2293 if len(segs) < 3: 

2294 raise SSHException("Invalid SSH banner") 

2295 version = segs[1] 

2296 client = segs[2] 

2297 if version != "1.99" and version != "2.0": 

2298 msg = "Incompatible version ({} instead of 2.0)" 

2299 raise IncompatiblePeer(msg.format(version)) 

2300 msg = "Connected (version {}, client {})".format(version, client) 

2301 self._log(INFO, msg) 

2302 

2303 def _send_kex_init(self): 

2304 """ 

2305 announce to the other side that we'd like to negotiate keys, and what 

2306 kind of key negotiation we support. 

2307 """ 

2308 self.clear_to_send_lock.acquire() 

2309 try: 

2310 self.clear_to_send.clear() 

2311 finally: 

2312 self.clear_to_send_lock.release() 

2313 self.gss_kex_used = False 

2314 self.in_kex = True 

2315 kex_algos = list(self.preferred_kex) 

2316 if self.server_mode: 

2317 mp_required_prefix = "diffie-hellman-group-exchange-sha" 

2318 kex_mp = [k for k in kex_algos if k.startswith(mp_required_prefix)] 

2319 if (self._modulus_pack is None) and (len(kex_mp) > 0): 

2320 # can't do group-exchange if we don't have a pack of potential 

2321 # primes 

2322 pkex = [ 

2323 k 

2324 for k in self.get_security_options().kex 

2325 if not k.startswith(mp_required_prefix) 

2326 ] 

2327 self.get_security_options().kex = pkex 

2328 available_server_keys = list( 

2329 filter( 

2330 list(self.server_key_dict.keys()).__contains__, 

2331 # TODO: ensure tests will catch if somebody streamlines 

2332 # this by mistake - case is the admittedly silly one where 

2333 # the only calls to add_server_key() contain keys which 

2334 # were filtered out of the below via disabled_algorithms. 

2335 # If this is streamlined, we would then be allowing the 

2336 # disabled algorithm(s) for hostkey use 

2337 # TODO: honestly this prob just wants to get thrown out 

2338 # when we make kex configuration more straightforward 

2339 self.preferred_keys, 

2340 ) 

2341 ) 

2342 else: 

2343 available_server_keys = self.preferred_keys 

2344 # Signal support for MSG_EXT_INFO. 

2345 # NOTE: doing this here handily means we don't even consider this 

2346 # value when agreeing on real kex algo to use (which is a common 

2347 # pitfall when adding this apparently). 

2348 kex_algos.append("ext-info-c") 

2349 

2350 m = Message() 

2351 m.add_byte(cMSG_KEXINIT) 

2352 m.add_bytes(os.urandom(16)) 

2353 m.add_list(kex_algos) 

2354 m.add_list(available_server_keys) 

2355 m.add_list(self.preferred_ciphers) 

2356 m.add_list(self.preferred_ciphers) 

2357 m.add_list(self.preferred_macs) 

2358 m.add_list(self.preferred_macs) 

2359 m.add_list(self.preferred_compression) 

2360 m.add_list(self.preferred_compression) 

2361 m.add_string(bytes()) 

2362 m.add_string(bytes()) 

2363 m.add_boolean(False) 

2364 m.add_int(0) 

2365 # save a copy for later (needed to compute a hash) 

2366 self.local_kex_init = self._latest_kex_init = m.asbytes() 

2367 self._send_message(m) 

2368 

2369 def _really_parse_kex_init(self, m, ignore_first_byte=False): 

2370 parsed = {} 

2371 if ignore_first_byte: 

2372 m.get_byte() 

2373 m.get_bytes(16) # cookie, discarded 

2374 parsed["kex_algo_list"] = m.get_list() 

2375 parsed["server_key_algo_list"] = m.get_list() 

2376 parsed["client_encrypt_algo_list"] = m.get_list() 

2377 parsed["server_encrypt_algo_list"] = m.get_list() 

2378 parsed["client_mac_algo_list"] = m.get_list() 

2379 parsed["server_mac_algo_list"] = m.get_list() 

2380 parsed["client_compress_algo_list"] = m.get_list() 

2381 parsed["server_compress_algo_list"] = m.get_list() 

2382 parsed["client_lang_list"] = m.get_list() 

2383 parsed["server_lang_list"] = m.get_list() 

2384 parsed["kex_follows"] = m.get_boolean() 

2385 m.get_int() # unused 

2386 return parsed 

2387 

2388 def _get_latest_kex_init(self): 

2389 return self._really_parse_kex_init( 

2390 Message(self._latest_kex_init), ignore_first_byte=True 

2391 ) 

2392 

2393 def _parse_kex_init(self, m): 

2394 parsed = self._really_parse_kex_init(m) 

2395 kex_algo_list = parsed["kex_algo_list"] 

2396 server_key_algo_list = parsed["server_key_algo_list"] 

2397 client_encrypt_algo_list = parsed["client_encrypt_algo_list"] 

2398 server_encrypt_algo_list = parsed["server_encrypt_algo_list"] 

2399 client_mac_algo_list = parsed["client_mac_algo_list"] 

2400 server_mac_algo_list = parsed["server_mac_algo_list"] 

2401 client_compress_algo_list = parsed["client_compress_algo_list"] 

2402 server_compress_algo_list = parsed["server_compress_algo_list"] 

2403 client_lang_list = parsed["client_lang_list"] 

2404 server_lang_list = parsed["server_lang_list"] 

2405 kex_follows = parsed["kex_follows"] 

2406 

2407 self._log(DEBUG, "=== Key exchange possibilities ===") 

2408 for prefix, value in ( 

2409 ("kex algos", kex_algo_list), 

2410 ("server key", server_key_algo_list), 

2411 # TODO: shouldn't these two lines say "cipher" to match usual 

2412 # terminology (including elsewhere in paramiko!)? 

2413 ("client encrypt", client_encrypt_algo_list), 

2414 ("server encrypt", server_encrypt_algo_list), 

2415 ("client mac", client_mac_algo_list), 

2416 ("server mac", server_mac_algo_list), 

2417 ("client compress", client_compress_algo_list), 

2418 ("server compress", server_compress_algo_list), 

2419 ("client lang", client_lang_list), 

2420 ("server lang", server_lang_list), 

2421 ): 

2422 if value == [""]: 

2423 value = ["<none>"] 

2424 value = ", ".join(value) 

2425 self._log(DEBUG, "{}: {}".format(prefix, value)) 

2426 self._log(DEBUG, "kex follows: {}".format(kex_follows)) 

2427 self._log(DEBUG, "=== Key exchange agreements ===") 

2428 

2429 # Strip out ext-info "kex algo" 

2430 self._remote_ext_info = None 

2431 if kex_algo_list[-1].startswith("ext-info-"): 

2432 self._remote_ext_info = kex_algo_list.pop() 

2433 

2434 # as a server, we pick the first item in the client's list that we 

2435 # support. 

2436 # as a client, we pick the first item in our list that the server 

2437 # supports. 

2438 if self.server_mode: 

2439 agreed_kex = list( 

2440 filter(self.preferred_kex.__contains__, kex_algo_list) 

2441 ) 

2442 else: 

2443 agreed_kex = list( 

2444 filter(kex_algo_list.__contains__, self.preferred_kex) 

2445 ) 

2446 if len(agreed_kex) == 0: 

2447 # TODO: do an auth-overhaul style aggregate exception here? 

2448 # TODO: would let us streamline log output & show all failures up 

2449 # front 

2450 raise IncompatiblePeer( 

2451 "Incompatible ssh peer (no acceptable kex algorithm)" 

2452 ) # noqa 

2453 self.kex_engine = self._kex_info[agreed_kex[0]](self) 

2454 self._log(DEBUG, "Kex: {}".format(agreed_kex[0])) 

2455 

2456 if self.server_mode: 

2457 available_server_keys = list( 

2458 filter( 

2459 list(self.server_key_dict.keys()).__contains__, 

2460 self.preferred_keys, 

2461 ) 

2462 ) 

2463 agreed_keys = list( 

2464 filter( 

2465 available_server_keys.__contains__, server_key_algo_list 

2466 ) 

2467 ) 

2468 else: 

2469 agreed_keys = list( 

2470 filter(server_key_algo_list.__contains__, self.preferred_keys) 

2471 ) 

2472 if len(agreed_keys) == 0: 

2473 raise IncompatiblePeer( 

2474 "Incompatible ssh peer (no acceptable host key)" 

2475 ) # noqa 

2476 self.host_key_type = agreed_keys[0] 

2477 if self.server_mode and (self.get_server_key() is None): 

2478 raise IncompatiblePeer( 

2479 "Incompatible ssh peer (can't match requested host key type)" 

2480 ) # noqa 

2481 self._log_agreement("HostKey", agreed_keys[0], agreed_keys[0]) 

2482 

2483 if self.server_mode: 

2484 agreed_local_ciphers = list( 

2485 filter( 

2486 self.preferred_ciphers.__contains__, 

2487 server_encrypt_algo_list, 

2488 ) 

2489 ) 

2490 agreed_remote_ciphers = list( 

2491 filter( 

2492 self.preferred_ciphers.__contains__, 

2493 client_encrypt_algo_list, 

2494 ) 

2495 ) 

2496 else: 

2497 agreed_local_ciphers = list( 

2498 filter( 

2499 client_encrypt_algo_list.__contains__, 

2500 self.preferred_ciphers, 

2501 ) 

2502 ) 

2503 agreed_remote_ciphers = list( 

2504 filter( 

2505 server_encrypt_algo_list.__contains__, 

2506 self.preferred_ciphers, 

2507 ) 

2508 ) 

2509 if len(agreed_local_ciphers) == 0 or len(agreed_remote_ciphers) == 0: 

2510 raise IncompatiblePeer( 

2511 "Incompatible ssh server (no acceptable ciphers)" 

2512 ) # noqa 

2513 self.local_cipher = agreed_local_ciphers[0] 

2514 self.remote_cipher = agreed_remote_ciphers[0] 

2515 self._log_agreement( 

2516 "Cipher", local=self.local_cipher, remote=self.remote_cipher 

2517 ) 

2518 

2519 if self.server_mode: 

2520 agreed_remote_macs = list( 

2521 filter(self.preferred_macs.__contains__, client_mac_algo_list) 

2522 ) 

2523 agreed_local_macs = list( 

2524 filter(self.preferred_macs.__contains__, server_mac_algo_list) 

2525 ) 

2526 else: 

2527 agreed_local_macs = list( 

2528 filter(client_mac_algo_list.__contains__, self.preferred_macs) 

2529 ) 

2530 agreed_remote_macs = list( 

2531 filter(server_mac_algo_list.__contains__, self.preferred_macs) 

2532 ) 

2533 if (len(agreed_local_macs) == 0) or (len(agreed_remote_macs) == 0): 

2534 raise IncompatiblePeer( 

2535 "Incompatible ssh server (no acceptable macs)" 

2536 ) 

2537 self.local_mac = agreed_local_macs[0] 

2538 self.remote_mac = agreed_remote_macs[0] 

2539 self._log_agreement( 

2540 "MAC", local=self.local_mac, remote=self.remote_mac 

2541 ) 

2542 

2543 if self.server_mode: 

2544 agreed_remote_compression = list( 

2545 filter( 

2546 self.preferred_compression.__contains__, 

2547 client_compress_algo_list, 

2548 ) 

2549 ) 

2550 agreed_local_compression = list( 

2551 filter( 

2552 self.preferred_compression.__contains__, 

2553 server_compress_algo_list, 

2554 ) 

2555 ) 

2556 else: 

2557 agreed_local_compression = list( 

2558 filter( 

2559 client_compress_algo_list.__contains__, 

2560 self.preferred_compression, 

2561 ) 

2562 ) 

2563 agreed_remote_compression = list( 

2564 filter( 

2565 server_compress_algo_list.__contains__, 

2566 self.preferred_compression, 

2567 ) 

2568 ) 

2569 if ( 

2570 len(agreed_local_compression) == 0 

2571 or len(agreed_remote_compression) == 0 

2572 ): 

2573 msg = "Incompatible ssh server (no acceptable compression)" 

2574 msg += " {!r} {!r} {!r}" 

2575 raise IncompatiblePeer( 

2576 msg.format( 

2577 agreed_local_compression, 

2578 agreed_remote_compression, 

2579 self.preferred_compression, 

2580 ) 

2581 ) 

2582 self.local_compression = agreed_local_compression[0] 

2583 self.remote_compression = agreed_remote_compression[0] 

2584 self._log_agreement( 

2585 "Compression", 

2586 local=self.local_compression, 

2587 remote=self.remote_compression, 

2588 ) 

2589 self._log(DEBUG, "=== End of kex handshake ===") 

2590 

2591 # save for computing hash later... 

2592 # now wait! openssh has a bug (and others might too) where there are 

2593 # actually some extra bytes (one NUL byte in openssh's case) added to 

2594 # the end of the packet but not parsed. turns out we need to throw 

2595 # away those bytes because they aren't part of the hash. 

2596 self.remote_kex_init = cMSG_KEXINIT + m.get_so_far() 

2597 

2598 def _activate_inbound(self): 

2599 """switch on newly negotiated encryption parameters for 

2600 inbound traffic""" 

2601 block_size = self._cipher_info[self.remote_cipher]["block-size"] 

2602 if self.server_mode: 

2603 IV_in = self._compute_key("A", block_size) 

2604 key_in = self._compute_key( 

2605 "C", self._cipher_info[self.remote_cipher]["key-size"] 

2606 ) 

2607 else: 

2608 IV_in = self._compute_key("B", block_size) 

2609 key_in = self._compute_key( 

2610 "D", self._cipher_info[self.remote_cipher]["key-size"] 

2611 ) 

2612 engine = self._get_cipher( 

2613 self.remote_cipher, key_in, IV_in, self._DECRYPT 

2614 ) 

2615 etm = "etm@openssh.com" in self.remote_mac 

2616 mac_size = self._mac_info[self.remote_mac]["size"] 

2617 mac_engine = self._mac_info[self.remote_mac]["class"] 

2618 # initial mac keys are done in the hash's natural size (not the 

2619 # potentially truncated transmission size) 

2620 if self.server_mode: 

2621 mac_key = self._compute_key("E", mac_engine().digest_size) 

2622 else: 

2623 mac_key = self._compute_key("F", mac_engine().digest_size) 

2624 self.packetizer.set_inbound_cipher( 

2625 engine, block_size, mac_engine, mac_size, mac_key, etm=etm 

2626 ) 

2627 compress_in = self._compression_info[self.remote_compression][1] 

2628 if compress_in is not None and ( 

2629 self.remote_compression != "zlib@openssh.com" or self.authenticated 

2630 ): 

2631 self._log(DEBUG, "Switching on inbound compression ...") 

2632 self.packetizer.set_inbound_compressor(compress_in()) 

2633 

2634 def _activate_outbound(self): 

2635 """switch on newly negotiated encryption parameters for 

2636 outbound traffic""" 

2637 m = Message() 

2638 m.add_byte(cMSG_NEWKEYS) 

2639 self._send_message(m) 

2640 block_size = self._cipher_info[self.local_cipher]["block-size"] 

2641 if self.server_mode: 

2642 IV_out = self._compute_key("B", block_size) 

2643 key_out = self._compute_key( 

2644 "D", self._cipher_info[self.local_cipher]["key-size"] 

2645 ) 

2646 else: 

2647 IV_out = self._compute_key("A", block_size) 

2648 key_out = self._compute_key( 

2649 "C", self._cipher_info[self.local_cipher]["key-size"] 

2650 ) 

2651 engine = self._get_cipher( 

2652 self.local_cipher, key_out, IV_out, self._ENCRYPT 

2653 ) 

2654 etm = "etm@openssh.com" in self.local_mac 

2655 mac_size = self._mac_info[self.local_mac]["size"] 

2656 mac_engine = self._mac_info[self.local_mac]["class"] 

2657 # initial mac keys are done in the hash's natural size (not the 

2658 # potentially truncated transmission size) 

2659 if self.server_mode: 

2660 mac_key = self._compute_key("F", mac_engine().digest_size) 

2661 else: 

2662 mac_key = self._compute_key("E", mac_engine().digest_size) 

2663 sdctr = self.local_cipher.endswith("-ctr") 

2664 self.packetizer.set_outbound_cipher( 

2665 engine, block_size, mac_engine, mac_size, mac_key, sdctr, etm=etm 

2666 ) 

2667 compress_out = self._compression_info[self.local_compression][0] 

2668 if compress_out is not None and ( 

2669 self.local_compression != "zlib@openssh.com" or self.authenticated 

2670 ): 

2671 self._log(DEBUG, "Switching on outbound compression ...") 

2672 self.packetizer.set_outbound_compressor(compress_out()) 

2673 if not self.packetizer.need_rekey(): 

2674 self.in_kex = False 

2675 # If client indicated extension support, send that packet immediately 

2676 if ( 

2677 self.server_mode 

2678 and self.server_sig_algs 

2679 and self._remote_ext_info == "ext-info-c" 

2680 ): 

2681 extensions = {"server-sig-algs": ",".join(self.preferred_pubkeys)} 

2682 m = Message() 

2683 m.add_byte(cMSG_EXT_INFO) 

2684 m.add_int(len(extensions)) 

2685 for name, value in sorted(extensions.items()): 

2686 m.add_string(name) 

2687 m.add_string(value) 

2688 self._send_message(m) 

2689 # we always expect to receive NEWKEYS now 

2690 self._expect_packet(MSG_NEWKEYS) 

2691 

2692 def _auth_trigger(self): 

2693 self.authenticated = True 

2694 # delayed initiation of compression 

2695 if self.local_compression == "zlib@openssh.com": 

2696 compress_out = self._compression_info[self.local_compression][0] 

2697 self._log(DEBUG, "Switching on outbound compression ...") 

2698 self.packetizer.set_outbound_compressor(compress_out()) 

2699 if self.remote_compression == "zlib@openssh.com": 

2700 compress_in = self._compression_info[self.remote_compression][1] 

2701 self._log(DEBUG, "Switching on inbound compression ...") 

2702 self.packetizer.set_inbound_compressor(compress_in()) 

2703 

2704 def _parse_ext_info(self, msg): 

2705 # Packet is a count followed by that many key-string to possibly-bytes 

2706 # pairs. 

2707 extensions = {} 

2708 for _ in range(msg.get_int()): 

2709 name = msg.get_text() 

2710 value = msg.get_string() 

2711 extensions[name] = value 

2712 self._log(DEBUG, "Got EXT_INFO: {}".format(extensions)) 

2713 # NOTE: this should work ok in cases where a server sends /two/ such 

2714 # messages; the RFC explicitly states a 2nd one should overwrite the 

2715 # 1st. 

2716 self.server_extensions = extensions 

2717 

2718 def _parse_newkeys(self, m): 

2719 self._log(DEBUG, "Switch to new keys ...") 

2720 self._activate_inbound() 

2721 # can also free a bunch of stuff here 

2722 self.local_kex_init = self.remote_kex_init = None 

2723 self.K = None 

2724 self.kex_engine = None 

2725 if self.server_mode and (self.auth_handler is None): 

2726 # create auth handler for server mode 

2727 self.auth_handler = AuthHandler(self) 

2728 if not self.initial_kex_done: 

2729 # this was the first key exchange 

2730 self.initial_kex_done = True 

2731 # send an event? 

2732 if self.completion_event is not None: 

2733 self.completion_event.set() 

2734 # it's now okay to send data again (if this was a re-key) 

2735 if not self.packetizer.need_rekey(): 

2736 self.in_kex = False 

2737 self.clear_to_send_lock.acquire() 

2738 try: 

2739 self.clear_to_send.set() 

2740 finally: 

2741 self.clear_to_send_lock.release() 

2742 return 

2743 

2744 def _parse_disconnect(self, m): 

2745 code = m.get_int() 

2746 desc = m.get_text() 

2747 self._log(INFO, "Disconnect (code {:d}): {}".format(code, desc)) 

2748 

2749 def _parse_global_request(self, m): 

2750 kind = m.get_text() 

2751 self._log(DEBUG, 'Received global request "{}"'.format(kind)) 

2752 want_reply = m.get_boolean() 

2753 if not self.server_mode: 

2754 self._log( 

2755 DEBUG, 

2756 'Rejecting "{}" global request from server.'.format(kind), 

2757 ) 

2758 ok = False 

2759 elif kind == "tcpip-forward": 

2760 address = m.get_text() 

2761 port = m.get_int() 

2762 ok = self.server_object.check_port_forward_request(address, port) 

2763 if ok: 

2764 ok = (ok,) 

2765 elif kind == "cancel-tcpip-forward": 

2766 address = m.get_text() 

2767 port = m.get_int() 

2768 self.server_object.cancel_port_forward_request(address, port) 

2769 ok = True 

2770 else: 

2771 ok = self.server_object.check_global_request(kind, m) 

2772 extra = () 

2773 if type(ok) is tuple: 

2774 extra = ok 

2775 ok = True 

2776 if want_reply: 

2777 msg = Message() 

2778 if ok: 

2779 msg.add_byte(cMSG_REQUEST_SUCCESS) 

2780 msg.add(*extra) 

2781 else: 

2782 msg.add_byte(cMSG_REQUEST_FAILURE) 

2783 self._send_message(msg) 

2784 

2785 def _parse_request_success(self, m): 

2786 self._log(DEBUG, "Global request successful.") 

2787 self.global_response = m 

2788 if self.completion_event is not None: 

2789 self.completion_event.set() 

2790 

2791 def _parse_request_failure(self, m): 

2792 self._log(DEBUG, "Global request denied.") 

2793 self.global_response = None 

2794 if self.completion_event is not None: 

2795 self.completion_event.set() 

2796 

2797 def _parse_channel_open_success(self, m): 

2798 chanid = m.get_int() 

2799 server_chanid = m.get_int() 

2800 server_window_size = m.get_int() 

2801 server_max_packet_size = m.get_int() 

2802 chan = self._channels.get(chanid) 

2803 if chan is None: 

2804 self._log(WARNING, "Success for unrequested channel! [??]") 

2805 return 

2806 self.lock.acquire() 

2807 try: 

2808 chan._set_remote_channel( 

2809 server_chanid, server_window_size, server_max_packet_size 

2810 ) 

2811 self._log(DEBUG, "Secsh channel {:d} opened.".format(chanid)) 

2812 if chanid in self.channel_events: 

2813 self.channel_events[chanid].set() 

2814 del self.channel_events[chanid] 

2815 finally: 

2816 self.lock.release() 

2817 return 

2818 

2819 def _parse_channel_open_failure(self, m): 

2820 chanid = m.get_int() 

2821 reason = m.get_int() 

2822 reason_str = m.get_text() 

2823 m.get_text() # ignored language 

2824 reason_text = CONNECTION_FAILED_CODE.get(reason, "(unknown code)") 

2825 self._log( 

2826 ERROR, 

2827 "Secsh channel {:d} open FAILED: {}: {}".format( 

2828 chanid, reason_str, reason_text 

2829 ), 

2830 ) 

2831 self.lock.acquire() 

2832 try: 

2833 self.saved_exception = ChannelException(reason, reason_text) 

2834 if chanid in self.channel_events: 

2835 self._channels.delete(chanid) 

2836 if chanid in self.channel_events: 

2837 self.channel_events[chanid].set() 

2838 del self.channel_events[chanid] 

2839 finally: 

2840 self.lock.release() 

2841 return 

2842 

2843 def _parse_channel_open(self, m): 

2844 kind = m.get_text() 

2845 chanid = m.get_int() 

2846 initial_window_size = m.get_int() 

2847 max_packet_size = m.get_int() 

2848 reject = False 

2849 if ( 

2850 kind == "auth-agent@openssh.com" 

2851 and self._forward_agent_handler is not None 

2852 ): 

2853 self._log(DEBUG, "Incoming forward agent connection") 

2854 self.lock.acquire() 

2855 try: 

2856 my_chanid = self._next_channel() 

2857 finally: 

2858 self.lock.release() 

2859 elif (kind == "x11") and (self._x11_handler is not None): 

2860 origin_addr = m.get_text() 

2861 origin_port = m.get_int() 

2862 self._log( 

2863 DEBUG, 

2864 "Incoming x11 connection from {}:{:d}".format( 

2865 origin_addr, origin_port 

2866 ), 

2867 ) 

2868 self.lock.acquire() 

2869 try: 

2870 my_chanid = self._next_channel() 

2871 finally: 

2872 self.lock.release() 

2873 elif (kind == "forwarded-tcpip") and (self._tcp_handler is not None): 

2874 server_addr = m.get_text() 

2875 server_port = m.get_int() 

2876 origin_addr = m.get_text() 

2877 origin_port = m.get_int() 

2878 self._log( 

2879 DEBUG, 

2880 "Incoming tcp forwarded connection from {}:{:d}".format( 

2881 origin_addr, origin_port 

2882 ), 

2883 ) 

2884 self.lock.acquire() 

2885 try: 

2886 my_chanid = self._next_channel() 

2887 finally: 

2888 self.lock.release() 

2889 elif not self.server_mode: 

2890 self._log( 

2891 DEBUG, 

2892 'Rejecting "{}" channel request from server.'.format(kind), 

2893 ) 

2894 reject = True 

2895 reason = OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED 

2896 else: 

2897 self.lock.acquire() 

2898 try: 

2899 my_chanid = self._next_channel() 

2900 finally: 

2901 self.lock.release() 

2902 if kind == "direct-tcpip": 

2903 # handle direct-tcpip requests coming from the client 

2904 dest_addr = m.get_text() 

2905 dest_port = m.get_int() 

2906 origin_addr = m.get_text() 

2907 origin_port = m.get_int() 

2908 reason = self.server_object.check_channel_direct_tcpip_request( 

2909 my_chanid, 

2910 (origin_addr, origin_port), 

2911 (dest_addr, dest_port), 

2912 ) 

2913 else: 

2914 reason = self.server_object.check_channel_request( 

2915 kind, my_chanid 

2916 ) 

2917 if reason != OPEN_SUCCEEDED: 

2918 self._log( 

2919 DEBUG, 

2920 'Rejecting "{}" channel request from client.'.format(kind), 

2921 ) 

2922 reject = True 

2923 if reject: 

2924 msg = Message() 

2925 msg.add_byte(cMSG_CHANNEL_OPEN_FAILURE) 

2926 msg.add_int(chanid) 

2927 msg.add_int(reason) 

2928 msg.add_string("") 

2929 msg.add_string("en") 

2930 self._send_message(msg) 

2931 return 

2932 

2933 chan = Channel(my_chanid) 

2934 self.lock.acquire() 

2935 try: 

2936 self._channels.put(my_chanid, chan) 

2937 self.channels_seen[my_chanid] = True 

2938 chan._set_transport(self) 

2939 chan._set_window( 

2940 self.default_window_size, self.default_max_packet_size 

2941 ) 

2942 chan._set_remote_channel( 

2943 chanid, initial_window_size, max_packet_size 

2944 ) 

2945 finally: 

2946 self.lock.release() 

2947 m = Message() 

2948 m.add_byte(cMSG_CHANNEL_OPEN_SUCCESS) 

2949 m.add_int(chanid) 

2950 m.add_int(my_chanid) 

2951 m.add_int(self.default_window_size) 

2952 m.add_int(self.default_max_packet_size) 

2953 self._send_message(m) 

2954 self._log( 

2955 DEBUG, "Secsh channel {:d} ({}) opened.".format(my_chanid, kind) 

2956 ) 

2957 if kind == "auth-agent@openssh.com": 

2958 self._forward_agent_handler(chan) 

2959 elif kind == "x11": 

2960 self._x11_handler(chan, (origin_addr, origin_port)) 

2961 elif kind == "forwarded-tcpip": 

2962 chan.origin_addr = (origin_addr, origin_port) 

2963 self._tcp_handler( 

2964 chan, (origin_addr, origin_port), (server_addr, server_port) 

2965 ) 

2966 else: 

2967 self._queue_incoming_channel(chan) 

2968 

2969 def _parse_debug(self, m): 

2970 m.get_boolean() # always_display 

2971 msg = m.get_string() 

2972 m.get_string() # language 

2973 self._log(DEBUG, "Debug msg: {}".format(util.safe_string(msg))) 

2974 

2975 def _get_subsystem_handler(self, name): 

2976 try: 

2977 self.lock.acquire() 

2978 if name not in self.subsystem_table: 

2979 return None, [], {} 

2980 return self.subsystem_table[name] 

2981 finally: 

2982 self.lock.release() 

2983 

2984 _handler_table = { 

2985 MSG_EXT_INFO: _parse_ext_info, 

2986 MSG_NEWKEYS: _parse_newkeys, 

2987 MSG_GLOBAL_REQUEST: _parse_global_request, 

2988 MSG_REQUEST_SUCCESS: _parse_request_success, 

2989 MSG_REQUEST_FAILURE: _parse_request_failure, 

2990 MSG_CHANNEL_OPEN_SUCCESS: _parse_channel_open_success, 

2991 MSG_CHANNEL_OPEN_FAILURE: _parse_channel_open_failure, 

2992 MSG_CHANNEL_OPEN: _parse_channel_open, 

2993 MSG_KEXINIT: _negotiate_keys, 

2994 } 

2995 

2996 _channel_handler_table = { 

2997 MSG_CHANNEL_SUCCESS: Channel._request_success, 

2998 MSG_CHANNEL_FAILURE: Channel._request_failed, 

2999 MSG_CHANNEL_DATA: Channel._feed, 

3000 MSG_CHANNEL_EXTENDED_DATA: Channel._feed_extended, 

3001 MSG_CHANNEL_WINDOW_ADJUST: Channel._window_adjust, 

3002 MSG_CHANNEL_REQUEST: Channel._handle_request, 

3003 MSG_CHANNEL_EOF: Channel._handle_eof, 

3004 MSG_CHANNEL_CLOSE: Channel._handle_close, 

3005 } 

3006 

3007 

3008# TODO 4.0: drop this, we barely use it ourselves, it badly replicates the 

3009# Transport-internal algorithm management, AND does so in a way which doesn't 

3010# honor newer things like disabled_algorithms! 

3011class SecurityOptions: 

3012 """ 

3013 Simple object containing the security preferences of an ssh transport. 

3014 These are tuples of acceptable ciphers, digests, key types, and key 

3015 exchange algorithms, listed in order of preference. 

3016 

3017 Changing the contents and/or order of these fields affects the underlying 

3018 `.Transport` (but only if you change them before starting the session). 

3019 If you try to add an algorithm that paramiko doesn't recognize, 

3020 ``ValueError`` will be raised. If you try to assign something besides a 

3021 tuple to one of the fields, ``TypeError`` will be raised. 

3022 """ 

3023 

3024 __slots__ = "_transport" 

3025 

3026 def __init__(self, transport): 

3027 self._transport = transport 

3028 

3029 def __repr__(self): 

3030 """ 

3031 Returns a string representation of this object, for debugging. 

3032 """ 

3033 return "<paramiko.SecurityOptions for {!r}>".format(self._transport) 

3034 

3035 def _set(self, name, orig, x): 

3036 if type(x) is list: 

3037 x = tuple(x) 

3038 if type(x) is not tuple: 

3039 raise TypeError("expected tuple or list") 

3040 possible = list(getattr(self._transport, orig).keys()) 

3041 forbidden = [n for n in x if n not in possible] 

3042 if len(forbidden) > 0: 

3043 raise ValueError("unknown cipher") 

3044 setattr(self._transport, name, x) 

3045 

3046 @property 

3047 def ciphers(self): 

3048 """Symmetric encryption ciphers""" 

3049 return self._transport._preferred_ciphers 

3050 

3051 @ciphers.setter 

3052 def ciphers(self, x): 

3053 self._set("_preferred_ciphers", "_cipher_info", x) 

3054 

3055 @property 

3056 def digests(self): 

3057 """Digest (one-way hash) algorithms""" 

3058 return self._transport._preferred_macs 

3059 

3060 @digests.setter 

3061 def digests(self, x): 

3062 self._set("_preferred_macs", "_mac_info", x) 

3063 

3064 @property 

3065 def key_types(self): 

3066 """Public-key algorithms""" 

3067 return self._transport._preferred_keys 

3068 

3069 @key_types.setter 

3070 def key_types(self, x): 

3071 self._set("_preferred_keys", "_key_info", x) 

3072 

3073 @property 

3074 def kex(self): 

3075 """Key exchange algorithms""" 

3076 return self._transport._preferred_kex 

3077 

3078 @kex.setter 

3079 def kex(self, x): 

3080 self._set("_preferred_kex", "_kex_info", x) 

3081 

3082 @property 

3083 def compression(self): 

3084 """Compression algorithms""" 

3085 return self._transport._preferred_compression 

3086 

3087 @compression.setter 

3088 def compression(self, x): 

3089 self._set("_preferred_compression", "_compression_info", x) 

3090 

3091 

3092class ChannelMap: 

3093 def __init__(self): 

3094 # (id -> Channel) 

3095 self._map = weakref.WeakValueDictionary() 

3096 self._lock = threading.Lock() 

3097 

3098 def put(self, chanid, chan): 

3099 self._lock.acquire() 

3100 try: 

3101 self._map[chanid] = chan 

3102 finally: 

3103 self._lock.release() 

3104 

3105 def get(self, chanid): 

3106 self._lock.acquire() 

3107 try: 

3108 return self._map.get(chanid, None) 

3109 finally: 

3110 self._lock.release() 

3111 

3112 def delete(self, chanid): 

3113 self._lock.acquire() 

3114 try: 

3115 try: 

3116 del self._map[chanid] 

3117 except KeyError: 

3118 pass 

3119 finally: 

3120 self._lock.release() 

3121 

3122 def values(self): 

3123 self._lock.acquire() 

3124 try: 

3125 return list(self._map.values()) 

3126 finally: 

3127 self._lock.release() 

3128 

3129 def __len__(self): 

3130 self._lock.acquire() 

3131 try: 

3132 return len(self._map) 

3133 finally: 

3134 self._lock.release()