def test_recv_raises_timeout_if_nothing_read(self, select, os_read, Popen): stdout = Popen.return_value.stdout select.return_value = [stdout], None, None fileno = stdout.fileno.return_value os_read.side_effect = socket.timeout proxy = ProxyCommand("hi") with raises(socket.timeout): proxy.recv(5) assert os_read.call_args[0] == (fileno, 5)
def test_recv_returns_buffer_on_timeout_if_any_read( self, select, os_read, Popen): stdout = Popen.return_value.stdout select.return_value = [stdout], None, None fileno = stdout.fileno.return_value os_read.side_effect = [b"was", socket.timeout] proxy = ProxyCommand("hi") data = proxy.recv(5) assert data == b"was" # not b"waste" assert os_read.call_args[0] == (fileno, 2)
def test_recv_reads_from_process_stdout_returning_bytes( self, select, os_read, Popen): stdout = Popen.return_value.stdout select.return_value = [stdout], None, None fileno = stdout.fileno.return_value # Intentionally returning <5 at a time sometimes os_read.side_effect = [b"was", b"te", b"of ti", b"me"] proxy = ProxyCommand("hi") data = proxy.recv(5) assert data == b"waste" assert [x[0] for x in os_read.call_args_list] == [ (fileno, 5), (fileno, 2), ]
def openconnection(self): if (self.grid_params["short_name"] == "hopper" or self.grid_params["short_name"] == "edison"): print "connecting ", self.grid_params["short_name"] self.client = SSHClient() self.client.set_missing_host_key_policy(client.AutoAddPolicy()) self.client.load_system_host_keys() self.client.connect(self.grid_params["full_name"], allow_agent=True) self.sftp = self.client.open_sftp() else: proxy_command = 'ssh %s nc %s %s' % ( 'aluf.technion.ac.il', self.grid_params["full_name"], 22) proxy = ProxyCommand(proxy_command) self.client = SSHClient() self.client.load_system_host_keys() self.client.connect(self.grid_params["short_name"], sock=proxy, allow_agent=True) self.sftp = self.client.open_sftp() stdin, stdout, stderr = self.client.exec_command("pwd") home = stdout.readlines()[0].rstrip() print home self.grid_params['home'] = home print "Connection Open"
def _configure(self): """ Configure the ssh parameters from the config file. """ configfile = expanduser("~/.ssh/config") if not isfile(configfile): raise GerritError("ssh config file '%s' does not exist" % configfile) config = SSHConfig() config.parse(open(configfile)) data = config.lookup(self.hostname) if not data: raise GerritError("No ssh config for host %s" % self.hostname) if 'hostname' not in data or 'port' not in data or 'user' not in data: raise GerritError("Missing configuration data in %s" % configfile) self.hostname = data['hostname'] self.username = data['user'] if 'identityfile' in data: key_filename = abspath(expanduser(data['identityfile'][0])) if not isfile(key_filename): raise GerritError("Identity file '%s' does not exist" % key_filename) self.key_filename = key_filename try: self.port = int(data['port']) except ValueError: raise GerritError("Invalid port: %s" % data['port']) if 'proxycommand' in data: self.proxy = ProxyCommand(data['proxycommand'])
def _get_proxy_command(self, port=22): proxy_command = None # TO-DO: Add logic to scan ssh_* args to read ProxyCommand proxy_command = self.get_option("proxy_command") sock = None if proxy_command: if Version(NCCLIENT_VERSION) < "0.6.10": raise AnsibleError( "Configuring jumphost settings through ProxyCommand is unsupported in ncclient version %s. " "Please upgrade to ncclient 0.6.10 or newer." % NCCLIENT_VERSION) replacers = { "%h": self._play_context.remote_addr, "%p": port, "%r": self._play_context.remote_user, } for find, replace in replacers.items(): proxy_command = proxy_command.replace(find, str(replace)) sock = ProxyCommand(proxy_command) return sock
def test_closed_exposes_whether_subprocess_has_exited(self, Popen): proxy = ProxyCommand("hi") Popen.return_value.returncode = None assert proxy.closed is False assert proxy._closed is False Popen.return_value.returncode = 0 assert proxy.closed is True assert proxy._closed is True
def test_recv_raises_ProxyCommandFailure_on_non_timeout_error( self, select, os_read, Popen): select.return_value = [Popen.return_value.stdout], None, None os_read.side_effect = IOError(0, "whoops") with raises(ProxyCommandFailure) as info: ProxyCommand("hi").recv(5) assert info.value.command == "hi" assert info.value.error == "whoops"
def test_init_takes_command_string(self, subprocess): ProxyCommand(command_line="do a thing") subprocess.Popen.assert_called_once_with( ["do", "a", "thing"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0, )
def test_timeout_affects_whether_timeout_is_raised(self, select, os_read, Popen, time): stdout = Popen.return_value.stdout select.return_value = [stdout], None, None # Base case: None timeout means no timing out os_read.return_value = b"meh" proxy = ProxyCommand("yello") assert proxy.timeout is None # Implicit 'no raise' check assert proxy.recv(3) == b"meh" # Use settimeout to set timeout, and it is honored time.side_effect = [0, 10] # elapsed > 7 proxy = ProxyCommand("ohnoz") proxy.settimeout(7) assert proxy.timeout == 7 with raises(socket.timeout): proxy.recv(3)
def ssh_connection(hostname): host = ssh_config(hostname) ssh_client = SSHClient() ssh_client.load_system_host_keys() try: ssh_client.connect(host['hostname'], username=host['user'], sock=ProxyCommand(host.get('proxycommand'))) return ssh_client except: ssh_client.connect(host['hostname'], username=host['user']) return ssh_client
def scp_upload(src_blob='Preproc.tar.gz', dst_blob="~", options={ 'hostname': 'lecun', 'username': '******' }, progress=simple_callback): # from https://gist.github.com/acdha/6064215 #--- Make the Paramiko SSH thing use my .ssh/config file (b/c I like ProxyCommand!) client = SSHClient() client.load_system_host_keys() client._policy = WarningPolicy() client.set_missing_host_key_policy( WarningPolicy()) # hmm. WarningPolicy? Most people use AutoAddPolicy. ssh_config = SSHConfig() user_config_file = os.path.expanduser("~/.ssh/config") if os.path.exists(user_config_file): with open(user_config_file) as f: ssh_config.parse(f) cfg = {'hostname': options['hostname'], 'username': options["username"]} user_config = ssh_config.lookup(cfg['hostname']) for k in ('hostname', 'username', 'port'): if k in user_config: cfg[k] = user_config[k] if 'proxycommand' in user_config: cfg['sock'] = ProxyCommand(user_config['proxycommand']) client.connect(**cfg) socket_timeout = None # number of seconds for timeout. None = never timeout. TODO: None means program may hang. But timeouts are annoying! # SCPCLient takes a paramiko transport and progress callback as its arguments. scp = SCPClient(client.get_transport(), progress=progress, socket_timeout=socket_timeout) # NOW we can finally upload! (in a separate process) #scp.put(src_blob, dst_blob) # now in scp_thread # we want this to be non-blocking so we stick it in a thread thread = threading.Thread(target=scp_thread, args=(scp, src_blob, dst_blob)) thread.start()
def parse_config(self, hostname): cfg = {'port': 22} forward_agent = False ssh_config = get_ssh_config() if not ssh_config: return hostname, cfg, forward_agent host_config = ssh_config.lookup(hostname) forward_agent = host_config.get('forwardagent') == 'yes' if 'hostname' in host_config: hostname = host_config['hostname'] if 'user' in host_config: cfg['username'] = host_config['user'] if 'identityfile' in host_config: cfg['key_filename'] = host_config['identityfile'] if 'port' in host_config: cfg['port'] = int(host_config['port']) if 'proxycommand' in host_config: cfg['sock'] = ProxyCommand(host_config['proxycommand']) elif 'proxyjump' in host_config: hops = host_config['proxyjump'].split(',') sock = None for i, hop in enumerate(hops): hop_hostname, hop_config = self.derive_shorthand(hop) c = SSHClient() c.set_missing_host_key_policy(AutoAddPolicy()) c.connect(hop_hostname, sock=sock, **hop_config) if i == len(hops) - 1: target = hostname target_config = {'port': cfg['port']} else: target, target_config = self.derive_shorthand(hops[i + 1]) sock = c.gateway(target, target_config['port']) cfg['sock'] = sock return hostname, cfg, forward_agent
def update_database(): if os.uname()[1] in ('workstation', ): print("Actualizando copia local de la base de datos...") host = 'ha-remote' ssh = SSHClient() ssh_config_file = os.path.expanduser("~/.ssh/config") if os.path.exists(ssh_config_file): conf = SSHConfig() with open(ssh_config_file) as f: conf.parse(f) host_config = conf.lookup(host) proxy = ProxyCommand("ssh {}@{} -p {} nc {} 22".format( "pi", "remote-ssh.proxy.host", 2222, 'homeassistant-host')) ssh.load_system_host_keys() ssh.set_missing_host_key_policy(AutoAddPolicy()) #ssh.connect(host, username=user, pkey=pkey, sock=proxy) ssh.connect(host, username=host_config['user'], sock=proxy) with SCPClient(ssh.get_transport()) as scp: src = '/home/homeassistant/devel/hamlfeeder/database.sqlite' dst = '/home/roberto/devel/python/hamlfeeder/database.sqlite' scp.get(src, dst)
def parse_config(self, hostname): cfg = { 'port': 22, } user_config_file = os.path.expanduser('~/.ssh/config') if os.path.exists(user_config_file): with open(user_config_file) as f: ssh_config = SSHConfig() ssh_config.parse(f) host_config = ssh_config.lookup(hostname) if 'hostname' in host_config: hostname = host_config['hostname'] if 'user' in host_config: cfg['username'] = host_config['user'] if 'identityfile' in host_config: cfg['key_filename'] = host_config['identityfile'] if 'port' in host_config: cfg['port'] = int(host_config['port']) if 'proxycommand' in host_config: cfg['sock'] = ProxyCommand(host_config['proxycommand']) elif 'proxyjump' in host_config: hops = host_config['proxyjump'].split(',') sock = None for i, hop in enumerate(hops): hop_hostname, hop_config = self.derive_shorthand(hop) c = SSHClient() c.set_missing_host_key_policy(AutoAddPolicy()) c.connect(hop_hostname, sock=sock, **hop_config) if i == len(hops) - 1: target = hostname target_config = {'port': cfg['port']} else: target, target_config = self.derive_shorthand( hops[i + 1]) sock = c.gateway(target, target_config['port']) cfg['sock'] = sock return hostname, cfg
def connect(self): host_config = self.config.lookup(self.host) log.debug('ssh-config: %s' % host_config) forwardagent = host_config.get('forwardagent') if forwardagent is not None and forwardagent == 'yes': self.forward_agent = True log.debug('forwarding agent is enabled') param = { 'sock': None, 'timeout': 10.0, } proxy_command = host_config.get('proxycommand') if proxy_command is not None: param['sock'] = ProxyCommand(proxy_command) if self.credential is not None: param.update(self.credential.connect_param) self.client.connect(self.host, **param) log.info('connected: %s' % self.host)
def parse_config( self, hostname, initial_cfg=None, ssh_config_file=None, strict_host_key_checking=None, ): cfg = {"port": 22} cfg.update(initial_cfg or {}) forward_agent = False missing_host_key_policy = get_missing_host_key_policy(strict_host_key_checking) host_keys_file = path.expanduser("~/.ssh/known_hosts") # OpenSSH default ssh_config = get_ssh_config(ssh_config_file) if not ssh_config: return hostname, cfg, forward_agent, missing_host_key_policy, host_keys_file host_config = ssh_config.lookup(hostname) forward_agent = host_config.get("forwardagent") == "yes" # If not overridden, apply any StrictHostKeyChecking if strict_host_key_checking is None and "stricthostkeychecking" in host_config: missing_host_key_policy = get_missing_host_key_policy( host_config["stricthostkeychecking"], ) if "userknownhostsfile" in host_config: host_keys_file = path.expanduser(host_config["userknownhostsfile"]) if "hostname" in host_config: hostname = host_config["hostname"] if "user" in host_config: cfg["username"] = host_config["user"] if "identityfile" in host_config: cfg["key_filename"] = host_config["identityfile"] if "port" in host_config: cfg["port"] = int(host_config["port"]) if "proxycommand" in host_config: cfg["sock"] = ProxyCommand(host_config["proxycommand"]) elif "proxyjump" in host_config: hops = host_config["proxyjump"].split(",") sock = None for i, hop in enumerate(hops): hop_hostname, hop_config = self.derive_shorthand(ssh_config, hop) logger.debug("SSH ProxyJump through %s:%s", hop_hostname, hop_config["port"]) c = SSHClient() c.connect( hop_hostname, _pyinfra_ssh_config_file=ssh_config_file, sock=sock, **hop_config ) if i == len(hops) - 1: target = hostname target_config = {"port": cfg["port"]} else: target, target_config = self.derive_shorthand(ssh_config, hops[i + 1]) sock = c.gateway(hostname, cfg["port"], target, target_config["port"]) cfg["sock"] = sock return hostname, cfg, forward_agent, missing_host_key_policy, host_keys_file
def test_send_raises_ProxyCommandFailure_on_error(self, Popen): Popen.return_value.stdin.write.side_effect = IOError(0, "whoops") with raises(ProxyCommandFailure) as info: ProxyCommand("hi").send("data") assert info.value.command == "hi" assert info.value.error == "whoops"
def connect(self, username=None, password=None, accept_missing_host_key=True, tcp_timeout=30, auth_strategy=SSHAuthStrategy.PASSWORD, port=22, key=None, allow_agent=True, key_filename=None): """ Attempts to connect to a remote server via SSH @param username: Username to be used for SSH connection @type username: string @param password: Password to be used for SSH connection @type password: string @param auth_strategy: Authentication strategy to use to connect @type auth_strategy: string @param port: Port to use for the SSH connection @type port: int @param key: Text of an SSH key to be used to connect @type key: string @param key_filename: Name of a file that contains a SSH key @type key_filename: string @param allow_agent: Set to False to disable connecting to the SSH agent @type allow_agent: bool @param accept_missing_host_key: Sets if a SSH connection can be made to remote server if the server does not have a host key in the local system @type accept_missing_host_key: bool @return: None """ ssh = ExtendedParamikoSSHClient() if accept_missing_host_key: ssh.set_missing_host_key_policy(AutoAddPolicy()) connect_args = {'hostname': self.host, 'username': username, 'timeout': tcp_timeout, 'port': port, 'allow_agent': allow_agent} self._log.debug('Attempting to SSH connect to {host} ' 'with user {user} and strategy {strategy}.'.format( host=self.host, user=username, strategy=auth_strategy)) if auth_strategy == SSHAuthStrategy.PASSWORD: connect_args['password'] = password if auth_strategy == SSHAuthStrategy.LOCAL_KEY: connect_args['look_for_keys'] = True if auth_strategy == SSHAuthStrategy.KEY_STRING: key_file = io.StringIO(key) key = RSAKey.from_private_key(key_file) connect_args['pkey'] = key if auth_strategy == SSHAuthStrategy.KEY_FILE_LIST: connect_args['key_filename'] = key_filename # Add sock proxy if ssh tunnel through proxy/bastion is required if self.is_proxy_needed(): self._log.info("Using a proxy: {proxy}".format(proxy=self.proxy)) proxy_str = 'ssh -q -a -x {proxy} nc {host} {port}' proxy_cmd = proxy_str.format(proxy=self.proxy, host=self.host, port=port) connect_args['sock'] = ProxyCommand(proxy_cmd) try: ssh.connect(**connect_args) except (AuthenticationException, SSHException, socket.error, EOFError) as exception: # Log the failure self._log.error(exception.message) else: # Complete setup of the client ResourceManager.register(self, ssh.get_transport()) self.ssh_connection = ssh
def ssh_paramiko_connect_to(display_desc): #plain socket attributes: dtype = display_desc["type"] host = display_desc["host"] port = display_desc.get("ssh-port", 22) #ssh and command attributes: username = display_desc.get("username") or get_username() if "proxy_host" in display_desc: display_desc.setdefault("proxy_username", get_username()) password = display_desc.get("password") remote_xpra = display_desc["remote_xpra"] proxy_command = display_desc["proxy_command"] #ie: "_proxy_start" socket_dir = display_desc.get("socket_dir") display = display_desc.get("display") display_as_args = display_desc["display_as_args"] #ie: "--start=xterm :10" paramiko_config = display_desc.copy() paramiko_config.update(display_desc.get("paramiko-config", {})) socket_info = { "host" : host, "port" : port, } def get_keyfiles(host_config, config_name="key"): keyfiles = (host_config or {}).get("identityfile") or get_default_keyfiles() keyfile = paramiko_config.get(config_name) if keyfile: keyfiles.insert(0, keyfile) return keyfiles with nogssapi_context(): from paramiko import SSHConfig, ProxyCommand ssh_config = SSHConfig() user_config_file = os.path.expanduser("~/.ssh/config") sock = None host_config = None if os.path.exists(user_config_file): with open(user_config_file) as f: ssh_config.parse(f) log("parsed user config '%s': %i hosts found", user_config_file, len(ssh_config.get_hostnames())) host_config = ssh_config.lookup(host) if host_config: log("got host config for '%s': %s", host, host_config) chost = host_config.get("hostname", host) cusername = host_config.get("user", username) cport = host_config.get("port", port) try: port = int(cport) except (TypeError, ValueError): raise InitExit(EXIT_SSH_FAILURE, "invalid ssh port specified: '%s'" % cport) from None proxycommand = host_config.get("proxycommand") if proxycommand: log("found proxycommand='%s' for host '%s'", proxycommand, chost) sock = ProxyCommand(proxycommand) log("ProxyCommand(%s)=%s", proxycommand, sock) from xpra.child_reaper import getChildReaper cmd = getattr(sock, "cmd", []) def proxycommand_ended(proc): log("proxycommand_ended(%s) exit code=%s", proc, proc.poll()) getChildReaper().add_process(sock.process, "paramiko-ssh-client", cmd, True, True, callback=proxycommand_ended) proxy_keys = get_keyfiles(host_config, "proxy_key") log("proxy keys=%s", proxy_keys) from paramiko.client import SSHClient ssh_client = SSHClient() ssh_client.load_system_host_keys() log("ssh proxy command connect to %s", (chost, cport, sock)) ssh_client.connect(chost, cport, sock=sock) transport = ssh_client.get_transport() do_ssh_paramiko_connect_to(transport, chost, cusername, password, host_config or ssh_config.lookup("*"), proxy_keys, paramiko_config) chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra, socket_dir, display_as_args) peername = (chost, cport) conn = SSHProxyCommandConnection(chan, peername, peername, socket_info) conn.target = host_target_string("ssh", cusername, chost, port, display) conn.timeout = SOCKET_TIMEOUT conn.start_stderr_reader() conn.process = (sock.process, "ssh", cmd) from xpra.net import bytestreams from paramiko.ssh_exception import ProxyCommandFailure bytestreams.CLOSED_EXCEPTIONS = tuple(list(bytestreams.CLOSED_EXCEPTIONS)+[ProxyCommandFailure]) return conn keys = get_keyfiles(host_config) from xpra.scripts.main import socket_connect from paramiko.transport import Transport from paramiko import SSHException if "proxy_host" in display_desc: proxy_host = display_desc["proxy_host"] proxy_port = display_desc.get("proxy_port", 22) proxy_username = display_desc.get("proxy_username", username) proxy_password = display_desc.get("proxy_password", password) proxy_keys = get_keyfiles(host_config, "proxy_key") sock = socket_connect(dtype, proxy_host, proxy_port) middle_transport = Transport(sock) middle_transport.use_compression(False) try: middle_transport.start_client() except SSHException as e: log("start_client()", exc_info=True) raise InitExit(EXIT_SSH_FAILURE, "SSH negotiation failed: %s" % e) from None proxy_host_config = ssh_config.lookup(host) do_ssh_paramiko_connect_to(middle_transport, proxy_host, proxy_username, proxy_password, proxy_host_config or ssh_config.lookup("*"), proxy_keys, paramiko_config) log("Opening proxy channel") chan_to_middle = middle_transport.open_channel("direct-tcpip", (host, port), ('localhost', 0)) transport = Transport(chan_to_middle) transport.use_compression(False) try: transport.start_client() except SSHException as e: log("start_client()", exc_info=True) raise InitExit(EXIT_SSH_FAILURE, "SSH negotiation failed: %s" % e) do_ssh_paramiko_connect_to(transport, host, username, password, host_config or ssh_config.lookup("*"), keys, paramiko_config) chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra, socket_dir, display_as_args) peername = (host, port) conn = SSHProxyCommandConnection(chan, peername, peername, socket_info) conn.target = "%s via %s" % ( host_target_string("ssh", username, host, port, display), host_target_string("ssh", proxy_username, proxy_host, proxy_port, None), ) conn.timeout = SOCKET_TIMEOUT conn.start_stderr_reader() return conn #plain TCP connection to the server, #we open it then give the socket to paramiko: sock = socket_connect(dtype, host, port) sockname = sock.getsockname() peername = sock.getpeername() log("paramiko socket_connect: sockname=%s, peername=%s", sockname, peername) transport = Transport(sock) transport.use_compression(False) try: transport.start_client() except SSHException as e: log("start_client()", exc_info=True) raise InitExit(EXIT_SSH_FAILURE, "SSH negotiation failed: %s" % e) from None do_ssh_paramiko_connect_to(transport, host, username, password, host_config or ssh_config.lookup("*"), keys, paramiko_config) chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra, socket_dir, display_as_args) conn = SSHSocketConnection(chan, sock, sockname, peername, (host, port), socket_info) conn.target = host_target_string("ssh", username, host, port, display) conn.timeout = SOCKET_TIMEOUT conn.start_stderr_reader() return conn
def test_raises_subprocess_ImportErrors_at_runtime(self): # Not an ideal test, but I don't know of a non-bad way to fake out # module-time ImportErrors. So we mock the symptoms. Meh! with raises(ImportError) as info: ProxyCommand("hi!!!") assert str(info.value) == "meh"
def test_close_kills_subprocess(self, os_kill, Popen): proxy = ProxyCommand("hi") proxy.close() os_kill.assert_called_once_with(Popen.return_value.pid, signal.SIGTERM)
def ssh(host, forward_agent=False, sudoable=False, max_attempts=1, max_timeout=5, ssh_password=None): """Manages a SSH connection to the desired host. Will leverage your ssh config at ~/.ssh/config if available :param host: the server to connect to :type host: str :param forward_agent: forward the local agents :type forward_agent: bool :param sudoable: allow sudo commands :type sudoable: bool :param max_attempts: the maximum attempts to connect to the desired host :type max_attempts: int :param max_timeout: the maximum timeout in seconds to sleep between attempts :type max_timeout: int :param ssh_password: SSH password to use if needed :type ssh_password: str :returns a SSH connection to the desired host :rtype: Connection :raises MaxConnectionAttemptsError: Exceeded the maximum attempts to establish the SSH connection. """ with closing(SSHClient()) as client: client.set_missing_host_key_policy(AutoAddPolicy()) cfg = { "hostname": host, "timeout": max_timeout, } if ssh_password: cfg['password'] = ssh_password ssh_config = SSHConfig() user_config_file = os.path.expanduser("~/.ssh/config") if os.path.exists(user_config_file): with open(user_config_file) as f: ssh_config.parse(f) host_config = ssh_config.lookup(host) if "user" in host_config: cfg["username"] = host_config["user"] if "proxycommand" in host_config: cfg["sock"] = ProxyCommand(host_config["proxycommand"]) if "identityfile" in host_config: cfg['key_filename'] = host_config['identityfile'] if "port" in host_config: cfg["port"] = int(host_config["port"]) attempts = 0 while attempts < max_attempts: try: attempts += 1 client.connect(**cfg) break except socket.error as e: if attempts < max_attempts: print("SSH to host {0} failed, retrying...".format(host)) time.sleep(max_timeout) else: print("SSH Exception: {0}".format(e)) else: raise MaxConnectionAttemptsError( "Exceeded max attempts to connect to host {0} after {1} retries" .format(host, max_attempts)) yield Connection(client, forward_agent, sudoable)
def ssh_paramiko_connect_to(display_desc): #plain socket attributes: dtype = display_desc["type"] host = display_desc["host"] port = display_desc.get("ssh-port", 22) #ssh and command attributes: username = display_desc.get("username") or get_username() if "proxy_host" in display_desc: display_desc.setdefault("proxy_username", get_username()) password = display_desc.get("password") target = ssh_target_string(display_desc) remote_xpra = display_desc["remote_xpra"] proxy_command = display_desc["proxy_command"] #ie: "_proxy_start" socket_dir = display_desc.get("socket_dir") display_as_args = display_desc["display_as_args"] #ie: "--start=xterm :10" socket_info = { "host": host, "port": port, } with nogssapi_context(): from paramiko import SSHConfig, ProxyCommand ssh_config = SSHConfig() user_config_file = os.path.expanduser("~/.ssh/config") sock = None host_config = None if os.path.exists(user_config_file): with open(user_config_file) as f: ssh_config.parse(f) host_config = ssh_config.lookup(host) if host_config: host = host_config.get("hostname", host) username = host_config.get("username", username) port = host_config.get("port", port) proxycommand = host_config.get("proxycommand") if proxycommand: sock = ProxyCommand(proxycommand) from xpra.child_reaper import getChildReaper cmd = getattr(sock, "cmd", []) getChildReaper().add_process(sock.process, "paramiko-ssh-client", cmd, True, True) log("found proxycommand='%s' for host '%s'", proxycommand, host) from paramiko.client import SSHClient ssh_client = SSHClient() ssh_client.load_system_host_keys() ssh_client.connect(host, port, sock=sock) transport = ssh_client.get_transport() do_ssh_paramiko_connect_to( transport, host, username, password, host_config or ssh_config.lookup("*")) chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra, socket_dir, display_as_args) peername = (host, port) conn = SSHProxyCommandConnection(chan, peername, target, socket_info) conn.timeout = SOCKET_TIMEOUT conn.start_stderr_reader() conn.process = (sock.process, "ssh", cmd) from xpra.net import bytestreams from paramiko.ssh_exception import ProxyCommandFailure bytestreams.CLOSED_EXCEPTIONS = tuple( list(bytestreams.CLOSED_EXCEPTIONS) + [ProxyCommandFailure]) return conn from xpra.scripts.main import socket_connect from paramiko.transport import Transport from paramiko import SSHException if "proxy_host" in display_desc: proxy_host = display_desc["proxy_host"] proxy_port = display_desc.get("proxy_port", 22) proxy_username = display_desc.get("proxy_username", username) proxy_password = display_desc.get("proxy_password", password) sock = socket_connect(dtype, proxy_host, proxy_port) middle_transport = Transport(sock) middle_transport.use_compression(False) try: middle_transport.start_client() except SSHException as e: log("start_client()", exc_info=True) raise InitException("SSH negotiation failed: %s" % e) proxy_host_config = ssh_config.lookup(host) do_ssh_paramiko_connect_to( middle_transport, proxy_host, proxy_username, proxy_password, proxy_host_config or ssh_config.lookup("*")) log("Opening proxy channel") chan_to_middle = middle_transport.open_channel( "direct-tcpip", (host, port), ('localhost', 0)) transport = Transport(chan_to_middle) transport.use_compression(False) try: transport.start_client() except SSHException as e: log("start_client()", exc_info=True) raise InitException("SSH negotiation failed: %s" % e) do_ssh_paramiko_connect_to(transport, host, username, password, host_config or ssh_config.lookup("*")) chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra, socket_dir, display_as_args) peername = (host, port) conn = SSHProxyCommandConnection(chan, peername, target, socket_info) conn.timeout = SOCKET_TIMEOUT conn.start_stderr_reader() return conn #plain TCP connection to the server, #we open it then give the socket to paramiko: sock = socket_connect(dtype, host, port) sockname = sock.getsockname() peername = sock.getpeername() log("paramiko socket_connect: sockname=%s, peername=%s", sockname, peername) transport = Transport(sock) transport.use_compression(False) try: transport.start_client() except SSHException as e: log("start_client()", exc_info=True) raise InitException("SSH negotiation failed: %s" % e) do_ssh_paramiko_connect_to(transport, host, username, password, host_config or ssh_config.lookup("*")) chan = paramiko_run_remote_xpra(transport, proxy_command, remote_xpra, socket_dir, display_as_args) conn = SSHSocketConnection(chan, sock, sockname, peername, target, socket_info) conn.timeout = SOCKET_TIMEOUT conn.start_stderr_reader() return conn
def test_send_writes_to_process_stdin_returning_length(self, Popen): proxy = ProxyCommand("hi") written = proxy.send(b"data") Popen.return_value.stdin.write.assert_called_once_with(b"data") assert written == len(b"data")