def build(self, session, local_portnumber): nodelogin = session.hash['nodelogin'] # local_portnumber = rcm_utils.get_unused_portnumber() tunnel = session.hash['tunnel'] try: tunnelling_method = json.loads(parser.get('Settings', 'ssh_client')) except Exception: tunnelling_method = "internal" logic_logger.info("Using " + str(tunnelling_method) + " ssh tunnelling") # Decrypt password vncpassword = session.hash.get('vncpassword', '') rcm_cipher = cipher.RCMCipher() vncpassword_decrypted = rcm_cipher.decrypt(vncpassword) # Darwin if sys.platform.startswith('darwin'): self.add_arg_value( "-W", "vnc://:" + vncpassword_decrypted + "@127.0.0.1:" + str(local_portnumber)) # Win64 elif sys.platform == 'win32': self.add_default_arg("/nounixlogin") self.add_default_arg("/noreconnect") self.add_default_arg("/nonewconn") self.add_arg_value("/loglevel", "0") self.add_arg_value("/password", vncpassword_decrypted) # Linux else: self.add_arg_value("-quality", "80") self.add_arg_value("-password", vncpassword_decrypted) self.add_default_arg("-noreconnect") self.add_default_arg("-nonewconn") if not sys.platform.startswith('darwin'): if tunnel == 'y': self.add_default_arg("127.0.0.1:" + str(local_portnumber)) else: self.add_default_arg(nodelogin + ":" + str(session.hash['display'])) service_command_without_password = self.command if vncpassword_decrypted: service_command_without_password = service_command_without_password.replace( vncpassword_decrypted, "***") logic_logger.debug("service cmd: " + str(service_command_without_password))
def terminate(self): logic_logger.debug('Killing thread ' + str(self.threadnum)) # kill the process if self.service_process: logic_logger.debug("Killing service process " + str(self.service_process.pid)) self.service_process.terminate() # stop the tunnelling if self.ssh_server: self.ssh_server.stop() if self.gui_cmd: self.gui_cmd(active=False)
def prex(self, cmd, commandnode=''): """ This is the function that wrap all the remote comman execution, accept the input command and return the remote server output that comes after the rcm.serverOutputString separation string """ if self.commandnode == '': commandnode = self.proxynode else: commandnode = self.commandnode self.commandnode = '' fullcommand = self.ssh_remote_exec_command + "@" + commandnode + ' ' + cmd ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) logic_logger.debug("on " + commandnode + " run-->" + self.config['remote_rcm_server'] + ' ' + cmd + "<") try: ssh.connect(commandnode, username=self.remoteuser, password=self.passwd, timeout=10) except Exception as e: logic_logger.warning("ERROR {0}: ".format(e) + "in ssh.connect to node->" + commandnode + "< user->" + self.remoteuser + "<") return ('') self.auth_method = ssh.get_transport().auth_handler.auth_method stdin, stdout, stderr = ssh.exec_command( self.config['remote_rcm_server'] + ' ' + cmd) myout = ''.join(stdout) myerr = stderr.readlines() if myerr: logic_logger.error(myerr) raise Exception("Server error: {0}".format(myerr)) # find where the real server output starts index = myout.find(rcm.serverOutputString) if index != -1: index += len(rcm.serverOutputString) myout = myout[index:] return myout
def __init__(self): self.set_env() if sys.platform.startswith('darwin'): exe = "open" else: exe = rcm_utils.which('vncviewer') if not exe: logic_logger.error( "vncviewer not found! Check the PATH environment variable." ) if sys.platform == 'win32': # if the executable path contains spaces, it has to be put inside apexes exe = "\"" + exe + "\"" # self.exe = exe logic_logger.debug("vncviewer path: " + exe) super(TurboVNCExecutable, self).__init__(exe)
def execute_vnc_command_with_internal_ssh_tunnel(self): with SSHTunnelForwarder( (self.host, 22), ssh_username=self.username, ssh_password=self.password, remote_bind_address=(self.node, self.portnumber), local_bind_address=('127.0.0.1', self.local_portnumber) ) as self.ssh_server: self.vnc_process = subprocess.Popen(self.vnc_command, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True, universal_newlines=True) self.vnc_process.stdin.close() while self.vnc_process.poll() is None: stdout = self.vnc_process.stdout.readline() if stdout: logic_logger.debug("output from process: " + stdout.strip())
def __enter__(self): if sys.platform == 'win32': self.tunnel_process = pexpect.popen_spawn.PopenSpawn( self.tunnel_command) i = self.tunnel_process.expect( ['connection', pexpect.TIMEOUT, pexpect.EOF], timeout=2) if i == 0: self.tunnel_process.sendline('yes') else: self.tunnel_process = pexpect.spawn(self.tunnel_command, timeout=None) i = self.tunnel_process.expect([ 'continue connecting', 'password', pexpect.TIMEOUT, pexpect.EOF ], timeout=2) if i == 0: self.tunnel_process.sendline('yes') logic_logger.debug("accepted host verification") i = self.tunnel_process.expect([ 'continue connecting', 'password', pexpect.TIMEOUT, pexpect.EOF ], timeout=2) if i == 1: self.tunnel_process.sendline(self.password) logic_logger.debug("sent password") def wait(): self.tunnel_process.expect(pexpect.EOF) self.thread_tunnel = threading.Thread(target=wait) self.thread_tunnel.start() return self
def wrapper(*args, **kw): """ This is the wrapper for functions into ssh command line, it add debug info before calling actual command It uses mycall defined in manager to get return from ssh command output """ command = '--command=' + name for p in list(kw.keys()): if p in argnames: command += ' --' + p + '=' + kw[p] logic_logger.debug("calling " + name + " argnames-> " + str(argnames)) logic_logger.debug(str(kw) + " -- " + str(args)) logic_logger.debug("self-->" + str(args[0])) logic_logger.debug("running remote:" + command) ret = args[0].mycall(command) return ret
def __init__(self, tunnel_cmd='', vnc_cmd='', host='', username='', passwd='', vncpassword='', otp='', gui_cmd=None, configFile='', auth_method='', local_portnumber=0, node='', portnumber=0, tunnelling_method='internal' ): self.ssh_server = None self.tunnelling_method = tunnelling_method self.auth_method = auth_method self.tunnel_command = tunnel_cmd self.vnc_command = vnc_cmd self.host = host self.username = username self.gui_cmd = gui_cmd self.password = passwd self.vncpassword = vncpassword self.otp = otp self.vnc_process = None self.tunnel_process = None self.configFile = configFile self.local_portnumber = local_portnumber self.node = node self.portnumber = portnumber threading.Thread.__init__(self) self.threadnum = SessionThread.threadscount SessionThread.threadscount += 1 logic_logger.debug('Thread ' + str(self.threadnum) + ' is initialized')
def execute_service_command_with_external_ssh_tunnel(self): with NativeSSHTunnelForwarder( login_node=self.login_node, ssh_username=self.username, ssh_password=self.password, remote_bind_address=(self.node, self.portnumber), local_bind_address=('127.0.0.1', self.local_portnumber)) as self.ssh_server: self.service_process = subprocess.Popen(shlex.split( self.service_command), bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=False, universal_newlines=True) self.service_process.stdin.close() while self.service_process.poll() is None: stdout = self.service_process.stdout.readline() if stdout: logic_logger.debug("service process stdout: " + stdout.strip())
def __init__(self): # Read file containing the platform on which the client were build build_platform_filename = pyinstaller_utils.resource_path( "build_platform.txt") self.buildPlatformString = "" self.rcmVersion = "" if os.path.exists(build_platform_filename): logic_logger.debug("Reading build platform file " + build_platform_filename) with open(build_platform_filename, "r") as f: self.buildPlatformString = f.readline() self.rcmVersion = f.readline() logic_logger.debug(self.buildPlatformString) logic_logger.debug(self.rcmVersion)
def __init__(self): # Read file containing the platform on which the client were build build_platform_filename = pyinstaller_utils.resource_path("build_platform.txt") self.buildPlatformString = "" self.rcmVersion = "" self.checksumString = "" self.client_info = {} if os.path.exists(build_platform_filename): logic_logger.debug("Reading build platform file " + build_platform_filename) with open(build_platform_filename, "r") as f: self.buildPlatformString = f.readline().strip() self.rcmVersion = f.readline() logic_logger.debug("buildPlatformString: " + self.buildPlatformString) logic_logger.debug("rcmVersion: " + self.rcmVersion) if pyinstaller_utils.is_bundled(): self.checksumString = str(compute_checksum(sys.executable))
def copytree(src, dst, symlinks=False, ignore=None): if not os.path.exists(dst): logic_logger.debug("Creating folder " + dst) os.makedirs(dst) for item in os.listdir(src): s = os.path.join(src, item) d = os.path.join(dst, item) if os.path.isdir(s): copytree(s, d, symlinks, ignore) else: if not os.path.exists(d): logic_logger.debug("Copy: " + s + " >> " + d) shutil.copy2(s, d) else: source_hash = compute_checksum(s) dest_hash = compute_checksum(d) if source_hash == dest_hash: logic_logger.debug("Found previous: " + d) else: logic_logger.warning("Update previous: " + s + " >> " + d) shutil.copy2(s, d)
def terminate(self): self.gui_cmd = None logic_logger.debug('Killing thread ' + str(self.threadnum)) if self.ssh_server: self.ssh_server.stop() if self.vnc_process: arguments = 'Args not available in Popen' if hasattr(self.vnc_process, 'args'): arguments = str(self.vnc_process.args) logic_logger.debug("Killing vnc process " + str(self.vnc_process.pid) + " with args " + arguments) self.vnc_process.terminate() if self.tunnel_process: logic_logger.debug("Killing tunnel process" + str(self.tunnel_process.pid)) self.tunnel_process.terminate()
def __init__(self, pack_info=None): self.proxynode = '' self.remoteuser = '' self.passwd = '' self.auth_method = '' self.session_thread = [] self.commandnode = '' # here we instatiate the remote procedure call stub, it will automatically # have all the methods of rcm_protoclo_server.rcm_protocol class # --- TO BE DONE --- handle automatically output type self.protocol = rcm_protocol_client.get_protocol() def mycall(command): return self.prex(command) self.protocol.mycall = mycall if not pack_info: self.pack_info = rcm_utils.pack_info() else: self.pack_info = pack_info self.config = dict() self.config['ssh'] = dict() self.config['ssh']['win32'] = ("PLINK.EXE", " -ssh", "echo yes | ") self.config['ssh']['linux2'] = ("ssh", "", "") # for python3 self.config['ssh']['linux'] = ("ssh", "", "") self.config['ssh']['darwin'] = ("ssh", "", "") self.config['remote_rcm_server'] = json.loads( parser.get('Settings', 'preload_command', fallback='""') ) + "module load rcm; python $RCM_HOME/bin/server/rcm_new_server.py" self.activeConnectionsList = [] # set the environment if getattr(sys, 'frozen', False): logic_logger.debug("Running in a bundle") # if running in a bundle, we hardcode the path # of the built-in vnc viewer and plink (windows only) os.environ['JAVA_HOME'] = resource_path('turbovnc') os.environ['JDK_HOME'] = os.environ['JAVA_HOME'] os.environ['JRE_HOME'] = os.path.join(os.environ['JAVA_HOME'], 'jre') os.environ['CLASSPATH'] = os.path.join(os.environ['JAVA_HOME'], 'lib') + \ os.pathsep + os.path.join(os.environ['JRE_HOME'], 'lib') os.environ['PATH'] = os.path.join( os.environ['JAVA_HOME'], 'bin') + os.pathsep + os.environ['PATH'] logic_logger.debug("JAVA_HOME: " + str(os.environ['JAVA_HOME'])) logic_logger.debug("JRE_HOME: " + str(os.environ['JRE_HOME'])) logic_logger.debug("JDK_HOME: " + str(os.environ['JDK_HOME'])) logic_logger.debug("CLASSPATH: " + str(os.environ['CLASSPATH'])) logic_logger.debug("PATH: " + str(os.environ['PATH'])) # ssh executable if sys.platform == 'win32': sshexe = rcm_utils.which('PLINK') else: sshexe = rcm_utils.which('ssh') if not sshexe: if sys.platform == 'win32': logic_logger.error( "plink.exe not found! Check the PATH environment variable." ) else: logic_logger.error("ssh not found!") sys.exit() if sys.platform == 'win32': # if the executable path contains spaces, it has to be put inside apexes sshexe = "\"" + sshexe + "\"" self.ssh_command = self.config['ssh'][sys.platform][2] + \ sshexe + \ self.config['ssh'][sys.platform][1] logic_logger.debug("ssh command: " + self.ssh_command) self.vnc_cmdline_builder = vnc_client.VNCClientCommandLineBuilder() self.vnc_cmdline_builder.build()
def vncsession(self, session=None, otp='', gui_cmd=None, configFile=None): tunnel_command = '' vnc_command = '' vncpassword_decrypted = '' try: tunnelling_method = json.loads(parser.get('Settings', 'ssh_client')) except Exception: tunnelling_method = "internal" logic_logger.info("Using " + str(tunnelling_method) + " ssh tunnelling") if session: portnumber = 5900 + int(session.hash['display']) local_portnumber = rcm_utils.get_unused_portnumber() node = session.hash['node'] nodelogin = session.hash['nodelogin'] tunnel = session.hash['tunnel'] vncpassword = session.hash.get('vncpassword', '') # Decrypt password rcm_cipher = cipher.RCMCipher() vncpassword_decrypted = rcm_cipher.decrypt(vncpassword) logic_logger.debug("portnumber --> " + str(portnumber) + " node --> " + str(node) + " nodelogin --> " + str(nodelogin) + " tunnel --> " + str(tunnel)) if sys.platform.startswith('darwin'): vnc_command = self.vnc_cmdline_builder.get_executable_path() + " -quality 80 -subsampling 2X" \ + " -password " + vncpassword_decrypted vnc_command += " -loglevel " + str(rcm_utils.vnc_loglevel) elif sys.platform == 'win32': vnc_command = "echo " + vncpassword_decrypted + " | " + self.vnc_cmdline_builder.get_executable_path() \ + " -autopass -nounixlogin" vnc_command += " -logfile " + os.path.join( rcm_utils.log_folder(), 'vncviewer_' + nodelogin + '_' + session.hash.get('sessionid', '') + '.log') vnc_command += " -loglevel " + str(rcm_utils.vnc_loglevel) else: vnc_command = self.vnc_cmdline_builder.get_executable_path() + " -quality 80 " \ + " -password " + vncpassword_decrypted if sys.platform == 'win32' or sys.platform.startswith('darwin'): if tunnel == 'y': tunnel_command = self.ssh_command + " -L 127.0.0.1:" + str(local_portnumber) + ":" + node + ":" \ + str(portnumber) + " " + self.login_options + "@" + nodelogin if sys.platform.startswith('darwin'): tunnel_command += " echo 'rcm_tunnel'; sleep 20" else: tunnel_command += " echo 'rcm_tunnel'; sleep 10" vnc_command += " 127.0.0.1:" + str(local_portnumber) else: vnc_command += " " + nodelogin + ":" + str(portnumber) else: if tunnel == 'y': if tunnelling_method == 'internal': vnc_command += " 127.0.0.1:" + str(local_portnumber) elif tunnelling_method == 'external': tunnel_command = self.ssh_command + " -L 127.0.0.1:" + str(local_portnumber) + ":" + node + ":" \ + str(portnumber) + " " + self.login_options + "@" + nodelogin elif tunnelling_method == 'via': vnc_command += " -via '" + self.login_options + "@" + nodelogin + "' " \ + node + ":" + str(session.hash['display']) else: logic_logger.error(tunnelling_method + ' is not a valid option') return else: vnc_command += ' ' + nodelogin + ":" + session.hash[ 'display'] else: vnc_command = self.vnc_cmdline_builder.get_executable_path( ) + " -config " logic_logger.debug("tunnel->" + tunnel_command.replace(self.passwd, "****") + "< vnc->" + vnc_command + "< conffile->" + str(configFile) + "<") st = thread.SessionThread(tunnel_command, vnc_command, self.proxynode, self.remoteuser, self.passwd, vncpassword_decrypted, otp, gui_cmd, configFile, self.auth_method, local_portnumber, node, portnumber, tunnelling_method) logic_logger.debug("session thread--->" + str(st) + "<--- num thread:" + str(len(self.session_thread))) self.session_thread.append(st) st.start()
def get_config(self): o = self.protocol.config( build_platform=self.pack_info.buildPlatformString) self.server_config = rcm.rcm_config(o) logic_logger.debug("config---->" + str(self.server_config)) return self.server_config
def stop(self): if self.tunnel_process: logic_logger.debug("Stopping ssh tunnelling") self.tunnel_process.close(force=True) self.tunnel_process = None
command += ' --' + p + '=' + kw[p] logic_logger.debug("calling " + name + " argnames-> " + str(argnames)) logic_logger.debug(str(kw) + " -- " + str(args)) logic_logger.debug("self-->" + str(args[0])) logic_logger.debug("running remote:" + command) ret = args[0].mycall(command) return ret return wrapper for name, fn in inspect.getmembers(rcm_protocol_server.rcm_protocol): if sys.version_info >= (3, 0): # look for user-defined member functions if isinstance(fn, types.FunctionType) and name[:2] != '__': logic_logger.debug("wrapping-->" + name) setattr(rcm_protocol_server.rcm_protocol, name, rcm_decorate(fn)) else: if isinstance(fn, types.MethodType) and name[:2] != '__': logic_logger.debug("wrapping-->" + name) setattr(rcm_protocol_server.rcm_protocol, name, rcm_decorate(fn)) def get_protocol(): return rcm_protocol_server.rcm_protocol() if __name__ == '__main__': def prex(command='', commandnode=''): return "prex:node " + commandnode + " run -->" + command + "<--"
def set_env(self): # set the environment if getattr(sys, 'frozen', False): logic_logger.debug("Running in a bundle") # if running in a bundle, we hardcode the path # of the built-in vnc viewer and plink (windows only) os.environ['JAVA_HOME'] = resource_path('turbovnc') if sys.platform == 'win32': # on windows 10, administration policies prevent execution of external programs # located in %TEMP% ... it seems that it cannot be loaded home_path = os.path.expanduser('~') desktop_path = os.path.join(home_path, 'Desktop') exe_dir_path = os.path.dirname(sys.executable) if os.path.exists(desktop_path): rcm_unprotected_path = os.path.join( exe_dir_path, '.rcm', 'executables') os.makedirs(rcm_unprotected_path, exist_ok=True) dest_dir = os.path.join(rcm_unprotected_path, 'turbovnc') rcm_utils.copytree(resource_path('turbovnc'), dest_dir) os.environ['JAVA_HOME'] = dest_dir os.environ['JDK_HOME'] = os.environ['JAVA_HOME'] os.environ['JRE_HOME'] = os.path.join(os.environ['JAVA_HOME'], 'jre') os.environ['CLASSPATH'] = os.path.join(os.environ['JAVA_HOME'], 'lib') + \ os.pathsep + os.path.join(os.environ['JRE_HOME'], 'lib') os.environ['PATH'] = os.path.join( os.environ['JAVA_HOME'], 'bin') + os.pathsep + os.environ['PATH'] logic_logger.debug("JAVA_HOME: " + str(os.environ['JAVA_HOME'])) logic_logger.debug("JRE_HOME: " + str(os.environ['JRE_HOME'])) logic_logger.debug("JDK_HOME: " + str(os.environ['JDK_HOME'])) logic_logger.debug("CLASSPATH: " + str(os.environ['CLASSPATH'])) logic_logger.debug("PATH: " + str(os.environ['PATH']))
@wraps(fn) def wrapper(*args, **kw): """ This is the wrapper for functions into ssh command line, it add debug info before calling actual command It uses the prex function defined in manager to get return from ssh command output """ command = '--command=' + name for p in list(kw.keys()): if p in argnames: command += ' --' + p + '=' + "'" + kw[p] + "'" ret = args[0].decorate(command) return ret return wrapper for name, fn in inspect.getmembers(ServerAPIs): if sys.version_info >= (3, 0): # look for user-defined member functions if isinstance(fn, types.FunctionType) and name[:2] != '__': logic_logger.debug("wrapping: " + name) setattr(ServerAPIs, name, rcm_decorate(fn)) else: if isinstance(fn, types.MethodType) and name[:2] != '__': logic_logger.debug("wrapping: "+name) setattr(ServerAPIs, name, rcm_decorate(fn)) def get_protocol(): return ServerAPIs()
def execute_vnc_command_with_external_ssh_tunnel(self): if sys.platform == 'win32': if self.tunnel_command != '': tunnel_command_without_password = self.tunnel_command if self.auth_method == 'password': tunnel_command_without_password = self.tunnel_command.replace(self.password, "****") logic_logger.debug('Thread ' + str(self.threadnum) + " executing " + tunnel_command_without_password) self.tunnel_process = subprocess.Popen(self.tunnel_command, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True, universal_newlines=True) self.tunnel_process.stdin.close() while True: o = self.tunnel_process.stdout.readline() if o == '' and self.tunnel_process.poll() is not None: continue logic_logger.debug("output from process---->" + o.strip() + "<---") if o.strip() == 'rcm_tunnel': break a = self.vnc_command.split("|") logic_logger.debug("starting vncviewer") logic_logger.debug("splitting" + str(a)) if len(a) > 1: tmppass = a[0].strip().split()[1].strip() commandlist = a[1].strip() else: tmppass = None commandlist = self.vnc_command.split() logic_logger.debug("vncviewer tmp pass-->" + tmppass + "<--") logic_logger.debug("vncviewer command-->" + str(commandlist) + "<--") self.vnc_process = subprocess.Popen(commandlist, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=False, universal_newlines=True) if tmppass: self.vnc_process.stdin.write(tmppass) o = self.vnc_process.communicate() logic_logger.debug("vnc res-->" + str(o) + "<--") if self.vnc_process: self.vnc_process.stdin.close() if self.vnc_process: self.vnc_process.wait() elif sys.platform.startswith('darwin'): if self.tunnel_command != '': ssh_newkey = 'Are you sure you want to continue connecting' logic_logger.debug('Tunnel commands: ' + str(self.tunnel_command)) child = pexpect.spawn(self.tunnel_command, timeout=50) i = child.expect([ssh_newkey, 'password:'******'rcm_tunnel', pexpect.TIMEOUT, pexpect.EOF]) logic_logger.info('Tunnel return: ' + str(i)) if i == 0: # no certificate child.sendline('yes') i = child.expect(['password', 'standard VNC authentication', 'rcm_tunnel', pexpect.TIMEOUT, pexpect.EOF]) if i == 1: # no certificate child.sendline(self.password) if i == 0 or i == 3: logic_logger.debug("Timeout connecting to the display.") if self.gui_cmd: self.gui_cmd(active=False) raise Exception("Timeout connecting to the display.") commandlist = self.vnc_command.split() self.vnc_process = subprocess.Popen(commandlist, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=False, universal_newlines=True) if self.vnc_process: self.vnc_process.stdin.close() if self.vnc_process: self.vnc_process.wait() else: # linux child = pexpect.spawn(self.vnc_command, timeout=50) self.vnc_process = child i = child.expect(['continue connecting', 'password', 'standard VNC authentication', pexpect.EOF], timeout=None) if i == 0: child.sendline('yes') i = child.expect(['continue connecting', 'password', 'standard VNC authentication', pexpect.EOF], timeout=None) if i == 1: child.sendline(self.password) i = child.expect(['continue connecting', 'password', 'standard VNC authentication', pexpect.EOF], timeout=None) if i == 2: # Standard VNC authentication i = child.expect(['dummy0', 'dummy1', 'Password:'******'Authentication successful', pexpect.EOF], timeout=None) if i > 0: logic_logger.debug("#REMOVE_FOR_JAVA#Authentication problems.") for line in child: logic_logger.debug("#REMOVE_FOR_JAVA#child expect-->" + str(line)) child.expect(pexpect.EOF, timeout=None)