def test_19_allowed_environment(self): """ U19 | other environment are accepted """ INPUT = 'export MY_PROJECT_VERSION=43' args = INPUT retcode = builtins.export(args)[0] return self.assertEqual(retcode, 0)
def test_18_forbidden_environment(self): """ U18 | unsafe environment are forbidden """ INPUT = 'export LD_PRELOAD=/lib64/ld-2.21.so' args = INPUT retcode = builtins.export(args)[0] return self.assertEqual(retcode, 1)
def test_19_allowed_environment(self): """ U19 | other environment are accepted """ INPUT = 'export MY_PROJECT_VERSION=43' args = INPUT retcode = builtins.export(args)[0] return self.assertEqual(retcode, 0)
def test_18_forbidden_environment(self): """ U18 | unsafe environment are forbidden """ INPUT = 'export LD_PRELOAD=/lib64/ld-2.21.so' args = INPUT retcode = builtins.export(args)[0] return self.assertEqual(retcode, 1)
def check_env(self): """ Load environment variable set in configuration file """ if 'env_vars' in self.conf: env_vars = self.conf['env_vars'] for key in env_vars.keys(): os.environ[key] = str(env_vars[key]) # Check paths to files that contain env vars if 'env_vars_path' in self.conf: for file_path in self.conf['env_vars_path']: if not os.path.exists(file_path): self.stderr.write('WARN: env_vars_path %s not found. \n' % file_path) continue with open(file_path) as env_vars: for env_var in env_vars.readlines(): if env_var.split(" ", 1)[0] == 'export': builtins.export(env_var.strip())
def __getattr__(self, attr): """ This method actually takes care of all the called method that are not resolved (i.e not existing methods). It actually will simulate the existence of any method entered in the 'allowed' variable list. e.g. You just have to add 'uname' in list of allowed commands in the 'allowed' variable, and lshell will react as if you had added a do_uname in the ShellCmd class! """ # expand environment variables in command line self.g_cmd = os.path.expandvars(self.g_cmd) self.g_line = os.path.expandvars(self.g_line) self.g_arg = os.path.expandvars(self.g_arg) # in case the configuration file has been modified, reload it if self.conf['config_mtime'] != os.path.getmtime( self.conf['configfile']): from lshell.checkconfig import CheckConfig self.conf = CheckConfig(['--config', self.conf['configfile']], refresh=1).returnconf() self.conf['promptprint'] = utils.updateprompt( os.getcwd(), self.conf) self.log = self.conf['logpath'] if self.g_cmd in ['quit', 'exit', 'EOF']: self.log.error('Exited') if self.g_cmd == 'EOF': self.stdout.write('\n') if self.conf['disable_exit'] != 1: sys.exit(0) # check that commands/chars present in line are allowed/secure ret_check_secure, self.conf = sec.check_secure( self.g_line, self.conf, strict=self.conf['strict']) if ret_check_secure == 1: # see http://tldp.org/LDP/abs/html/exitcodes.html self.retcode = 126 return object.__getattribute__(self, attr) # check that path present in line are allowed/secure ret_check_path, self.conf = sec.check_path(self.g_line, self.conf, strict=self.conf['strict']) if ret_check_path == 1: # see http://tldp.org/LDP/abs/html/exitcodes.html self.retcode = 126 # in case request was sent by WinSCP, return error code has to be # sent via an specific echo command if self.conf['winscp'] and re.search('WinSCP: this is end-of-file', self.g_line): utils.exec_cmd('echo "WinSCP: this is end-of-file: %s"' % self.retcode) return object.__getattribute__(self, attr) if self.g_cmd in self.conf['allowed']: if self.conf['timer'] > 0: self.mytimer(0) self.g_arg = re.sub('^~$|^~/', '%s/' % self.conf['home_path'], self.g_arg) self.g_arg = re.sub(' ~/', ' %s/' % self.conf['home_path'], self.g_arg) # replace previous command exit code # in case multiple commands (using separators), only replace first # command. Regex replaces all occurrences of $?, before ;,&,| if re.search('[;&|]', self.g_line): p = re.compile("(\s|^)(\$\?)([\s|$]?[;&|].*)") else: p = re.compile("(\s|^)(\$\?)(\s|$)") self.g_line = p.sub(r' %s \3' % self.retcode, self.g_line) if type(self.conf['aliases']) == dict: self.g_line = utils.get_aliases(self.g_line, self.conf['aliases']) self.log.info('CMD: "%s"' % self.g_line) if self.g_cmd == 'cd': # split cd <dir> and rest of command cmd_split = re.split(';|&&|&|\|\||\|', self.g_line, 1) # in case the are commands following cd, first change the # directory, then execute the command if len(cmd_split) == 2: directory, command = cmd_split # only keep cd's argument directory = directory.split('cd', 1)[1].strip() # change directory then, if success, execute the rest of # the cmd line self.retcode, self.conf = builtins.cd(directory, self.conf) if self.retcode == 0: self.retcode = utils.exec_cmd(command) else: # set directory to command line argument and change dir directory = self.g_arg self.retcode, self.conf = builtins.cd(directory, self.conf) # built-in lpath function: list all allowed path elif self.g_cmd == 'lpath': self.retcode = builtins.lpath(self.conf) # built-in lsudo function: list all allowed sudo commands elif self.g_cmd == 'lsudo': self.retcode = builtins.lsudo(self.conf) # built-in history function: print command history elif self.g_cmd == 'history': self.retcode = builtins.history(self.conf, self.log) # built-in export function elif self.g_cmd == 'export': self.retcode, var = builtins.export(self.g_line) if self.retcode == 1: self.log.critical( "** forbidden environment variable '%s'" % var) # case 'cd' is in an alias e.g. {'toto':'cd /var/tmp'} elif self.g_line[0:2] == 'cd': self.g_cmd = self.g_line.split()[0] directory = ' '.join(self.g_line.split()[1:]) self.retcode, self.conf = builtins.cd(directory, self.conf) else: self.retcode = utils.exec_cmd(self.g_line) elif self.g_cmd not in ['', '?', 'help', None]: self.log.warn('INFO: unknown syntax -> "%s"' % self.g_line) self.stderr.write('*** unknown syntax: %s\n' % self.g_cmd) self.g_cmd, self.g_arg, self.g_line = ['', '', ''] if self.conf['timer'] > 0: self.mytimer(self.conf['timer']) return object.__getattribute__(self, attr)
def __getattr__(self, attr): """ This method actually takes care of all the called method that are not resolved (i.e not existing methods). It actually will simulate the existence of any method entered in the 'allowed' variable list. e.g. You just have to add 'uname' in list of allowed commands in the 'allowed' variable, and lshell will react as if you had added a do_uname in the ShellCmd class! """ # expand environment variables in command line self.g_cmd = os.path.expandvars(self.g_cmd) self.g_line = os.path.expandvars(self.g_line) self.g_arg = os.path.expandvars(self.g_arg) # in case the configuration file has been modified, reload it if self.conf['config_mtime'] != os.path.getmtime( self.conf['configfile']): from lshell.checkconfig import CheckConfig self.conf = CheckConfig(['--config', self.conf['configfile']], refresh=1).returnconf() self.conf['promptprint'] = utils.updateprompt(os.getcwd(), self.conf) self.log = self.conf['logpath'] if self.g_cmd in ['quit', 'exit', 'EOF']: self.log.error('Exited') if self.g_cmd == 'EOF': self.stdout.write('\n') if self.conf['disable_exit'] != 1: sys.exit(0) # check that commands/chars present in line are allowed/secure ret_check_secure, self.conf = sec.check_secure( self.g_line, self.conf, strict=self.conf['strict']) if ret_check_secure == 1: # see http://tldp.org/LDP/abs/html/exitcodes.html self.retcode = 126 return object.__getattribute__(self, attr) # check that path present in line are allowed/secure ret_check_path, self.conf = sec.check_path(self.g_line, self.conf, strict=self.conf['strict']) if ret_check_path == 1: # see http://tldp.org/LDP/abs/html/exitcodes.html self.retcode = 126 # in case request was sent by WinSCP, return error code has to be # sent via an specific echo command if self.conf['winscp'] and re.search('WinSCP: this is end-of-file', self.g_line): utils.exec_cmd('echo "WinSCP: this is end-of-file: %s"' % self.retcode) return object.__getattribute__(self, attr) if self.g_cmd in self.conf['allowed']: if self.conf['timer'] > 0: self.mytimer(0) self.g_arg = re.sub('^~$|^~/', '%s/' % self.conf['home_path'], self.g_arg) self.g_arg = re.sub(' ~/', ' %s/' % self.conf['home_path'], self.g_arg) # replace previous command exit code # in case multiple commands (using separators), only replace first # command. Regex replaces all occurrences of $?, before ;,&,| if re.search('[;&\|]', self.g_line): p = re.compile("(\s|^)(\$\?)([\s|$]?[;&|].*)") else: p = re.compile("(\s|^)(\$\?)(\s|$)") self.g_line = p.sub(r' %s \3' % self.retcode, self.g_line) if type(self.conf['aliases']) == dict: self.g_line = utils.get_aliases(self.g_line, self.conf['aliases']) self.log.info('CMD: "%s"' % self.g_line) if self.g_cmd == 'cd': # split cd <dir> and rest of command cmd_split = re.split(';|&&|&|\|\||\|', self.g_line, 1) # in case the are commands following cd, first change the # directory, then execute the command if len(cmd_split) == 2: directory, command = cmd_split # only keep cd's argument directory = directory.split('cd', 1)[1].strip() # change directory then, if success, execute the rest of # the cmd line self.retcode, self.conf = builtins.cd(directory, self.conf) if self.retcode == 0: self.retcode = utils.exec_cmd(command) else: # set directory to command line argument and change dir directory = self.g_arg self.retcode, self.conf = builtins.cd(directory, self.conf) # built-in lpath function: list all allowed path elif self.g_cmd == 'lpath': self.retcode = builtins.lpath(self.conf) # built-in lsudo function: list all allowed sudo commands elif self.g_cmd == 'lsudo': self.retcode = builtins.lsudo(self.conf) # built-in history function: print command history elif self.g_cmd == 'history': self.retcode = builtins.history(self.conf, self.log) # built-in export function elif self.g_cmd == 'export': self.retcode, var = builtins.export(self.g_line) if self.retcode == 1: self.log.critical("** forbidden environment variable '%s'" % var) # case 'cd' is in an alias e.g. {'toto':'cd /var/tmp'} elif self.g_line[0:2] == 'cd': self.g_cmd = self.g_line.split()[0] directory = ' '.join(self.g_line.split()[1:]) self.retcode, self.conf = builtins.cd(directory, self.conf) else: self.retcode = utils.exec_cmd(self.g_line) elif self.g_cmd not in ['', '?', 'help', None]: self.log.warn('INFO: unknown syntax -> "%s"' % self.g_line) self.stderr.write('*** unknown syntax: %s\n' % self.g_cmd) self.g_cmd, self.g_arg, self.g_line = ['', '', ''] if self.conf['timer'] > 0: self.mytimer(self.conf['timer']) return object.__getattribute__(self, attr)