Esempio n. 1
0
 def test_24_prompt_short_2(self):
     """ U24 | short_prompt = 2 should show full dir path """
     expected = '%s: %s$ ' % (getuser(), os.getcwd())
     args = self.args + ['--prompt_short=2']
     userconf = CheckConfig(args).returnconf()
     currentpath = "%s/foo" % userconf['home_path']
     prompt = updateprompt(currentpath, userconf)
     # sort lists to compare
     return self.assertEqual(prompt, expected)
Esempio n. 2
0
 def test_22_prompt_short_0(self):
     """ U22 | short_prompt = 0 should show dir compared to home dir """
     expected = '%s:~/foo$ ' % getuser()
     args = self.args + ['--prompt_short=0']
     userconf = CheckConfig(args).returnconf()
     currentpath = "%s/foo" % userconf['home_path']
     prompt = updateprompt(currentpath, userconf)
     # sort lists to compare
     return self.assertEqual(prompt, expected)
Esempio n. 3
0
 def test_23_prompt_short_1(self):
     """ U23 | short_prompt = 1 should show only current dir """
     expected = '%s: foo$ ' % getuser()
     args = self.args + ['--prompt_short=1']
     userconf = CheckConfig(args).returnconf()
     currentpath = "%s/foo" % userconf['home_path']
     prompt = updateprompt(currentpath, userconf)
     # sort lists to compare
     return self.assertEqual(prompt, expected)
Esempio n. 4
0
 def test_24_prompt_short_2(self):
     """ U24 | short_prompt = 2 should show full dir path """
     expected = '%s: %s$ ' % (getuser(), os.getcwd())
     args = self.args + ['--prompt_short=2']
     userconf = CheckConfig(args).returnconf()
     currentpath = "%s/foo" % userconf['home_path']
     prompt = updateprompt(currentpath, userconf)
     # sort lists to compare
     return self.assertEqual(prompt, expected)
Esempio n. 5
0
 def test_23_prompt_short_1(self):
     """ U23 | short_prompt = 1 should show only current dir """
     expected = '%s: foo$ ' % getuser()
     args = self.args + ['--prompt_short=1']
     userconf = CheckConfig(args).returnconf()
     currentpath = "%s/foo" % userconf['home_path']
     prompt = updateprompt(currentpath, userconf)
     # sort lists to compare
     return self.assertEqual(prompt, expected)
Esempio n. 6
0
 def test_22_prompt_short_0(self):
     """ U22 | short_prompt = 0 should show dir compared to home dir """
     expected = '%s:~/foo$ ' % getuser()
     args = self.args + ['--prompt_short=0']
     userconf = CheckConfig(args).returnconf()
     currentpath = "%s/foo" % userconf['home_path']
     prompt = updateprompt(currentpath, userconf)
     # sort lists to compare
     return self.assertEqual(prompt, expected)
def cd(directory, conf):
    """ implementation of the "cd" command
    """
    # expand user's ~
    directory = os.path.expanduser(directory)

    # remove quotes if present
    directory = directory.strip("'").strip('"')

    if len(directory) >= 1:
        # add wildcard completion support to cd
        if directory.find('*'):
            # get all files and directories matching wildcard
            wildall = glob.glob(directory)
            wilddir = []
            # filter to only directories
            for item in wildall:
                if os.path.isdir(item):
                    wilddir.append(item)
            # sort results
            wilddir.sort()
            # if any results are returned, pick first one
            if len(wilddir) >= 1:
                directory = wilddir[0]
        # go previous directory
        if directory == '-':
            directory = conf['oldpwd']

        # store current directory in oldpwd variable
        conf['oldpwd'] = os.getcwd()

        # change directory
        try:
            os.chdir(os.path.realpath(directory))
            conf['promptprint'] = utils.updateprompt(os.getcwd(), conf)
        except OSError as excp:
            sys.stdout.write("lshell: %s: %s\n" % (directory,
                                                   excp.strerror))
            return excp.errno, conf
    else:
        os.chdir(conf['home_path'])
        conf['promptprint'] = utils.updateprompt(os.getcwd(), conf)

    return 0, conf
Esempio n. 8
0
    def __init__(self,
                 userconf,
                 args,
                 stdin=None,
                 stdout=None,
                 stderr=None,
                 g_cmd=None,
                 g_line=None):
        if stdin is None:
            self.stdin = sys.stdin
        else:
            self.stdin = stdin
        if stdout is None:
            self.stdout = sys.stdout
        else:
            self.stdout = stdout
        if stderr is None:
            self.stderr = sys.stderr
        else:
            self.stderr = stderr

        self.args = args
        self.conf = userconf
        self.log = self.conf['logpath']

        # Set timer
        if self.conf['timer'] > 0:
            self.mytimer(self.conf['timer'])
        self.identchars = self.identchars + '+./-'
        self.log.error('Logged in')
        cmd.Cmd.__init__(self)

        # set prompt
        self.conf['promptprint'] = utils.updateprompt(os.getcwd(), self.conf)

        self.intro = self.conf['intro']

        # initialize oldpwd variable to home directory
        self.conf['oldpwd'] = self.conf['home_path']

        # initialize cli variables
        self.g_cmd = g_cmd
        self.g_line = g_line
        self.g_arg = None

        # initialize return code
        self.retcode = 0
Esempio n. 9
0
    def __init__(self, userconf, args, stdin=None, stdout=None, stderr=None,
                 g_cmd=None, g_line=None):
        if stdin is None:
            self.stdin = sys.stdin
        else:
            self.stdin = stdin
        if stdout is None:
            self.stdout = sys.stdout
        else:
            self.stdout = stdout
        if stderr is None:
            self.stderr = sys.stderr
        else:
            self.stderr = stderr

        self.args = args
        self.conf = userconf
        self.log = self.conf['logpath']

        # Set timer
        if self.conf['timer'] > 0:
            self.mytimer(self.conf['timer'])
        self.identchars = self.identchars + '+./-'
        self.log.error('Logged in')
        cmd.Cmd.__init__(self)

        # set prompt
        self.conf['promptprint'] = utils.updateprompt(os.getcwd(), self.conf)

        self.intro = self.conf['intro']

        # initialize oldpwd variable to home directory
        self.conf['oldpwd'] = self.conf['home_path']

        # initialize cli variables
        self.g_cmd = g_cmd
        self.g_line = g_line

        # initialize return code
        self.retcode = 0
Esempio n. 10
0
def check_path(line, conf, completion=None, ssh=None, strict=None):
    """ Check if a path is entered in the line. If so, it checks if user
    are allowed to see this path. If user is not allowed, it calls
    warn_count. In case of completion, it only returns 0 or 1.
    """
    allowed_path_re = str(conf['path'][0])
    denied_path_re = str(conf['path'][1][:-1])

    # split line depending on the operators
    sep = re.compile(r'\ |;|\||&')
    line = line.strip()
    line = sep.split(line)

    for item in line:
        # remove potential quotes or back-ticks
        item = re.sub(r'^["\'`]|["\'`]$', '', item)

        # remove potential $(), ${}, ``
        item = re.sub(r'^\$[\(\{]|[\)\}]$', '', item)

        # if item has been converted to something other than a string
        # or an int, reconvert it to a string
        if type(item) not in ['str', 'int']:
            item = str(item)
        # replace "~" with home path
        item = os.path.expanduser(item)

        # expand shell wildcards using "echo"
        # i know, this a bit nasty...
        if re.findall('\$|\*|\?', item):
            # remove quotes if available
            item = re.sub("\"|\'", "", item)
            import subprocess
            p = subprocess.Popen("`which echo` %s" % item,
                                 shell=True,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
            cout = p.stdout

            try:
                item = cout.readlines()[0].decode('utf8').split(' ')[0]
                item = item.strip()
                item = os.path.expandvars(item)
            except IndexError:
                conf['logpath'].critical('*** Internal error: command not '
                                         'executed')
                return 1, conf

        tomatch = os.path.realpath(item)
        if os.path.isdir(tomatch) and tomatch[-1] != '/':
            tomatch += '/'
        match_allowed = re.findall(allowed_path_re, tomatch)
        if denied_path_re:
            match_denied = re.findall(denied_path_re, tomatch)
        else:
            match_denied = None

        # if path not allowed
        # case path executed: warn, and return 1
        # case completion: return 1
        if not match_allowed or match_denied:
            if not completion:
                ret, conf = warn_count('path',
                                       tomatch,
                                       conf,
                                       strict=strict,
                                       ssh=ssh)
            return 1, conf

    if not completion:
        if not re.findall(allowed_path_re, os.getcwd() + '/'):
            ret, conf = warn_count('path',
                                   tomatch,
                                   conf,
                                   strict=strict,
                                   ssh=ssh)
            os.chdir(conf['home_path'])
            conf['promptprint'] = utils.updateprompt(os.getcwd(), conf)
            return 1, conf
    return 0, conf
Esempio n. 11
0
    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)
Esempio n. 12
0
    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)
Esempio n. 13
0
def check_path(line, conf, completion=None, ssh=None, strict=None):
    """ Check if a path is entered in the line. If so, it checks if user
    are allowed to see this path. If user is not allowed, it calls
    warn_count. In case of completion, it only returns 0 or 1.
    """
    allowed_path_re = str(conf['path'][0])
    denied_path_re = str(conf['path'][1][:-1])

    # split line depending on the operators
    sep = re.compile(r'\ |;|\||&')
    line = line.strip()
    line = sep.split(line)

    for item in line:
        # remove potential quotes or back-ticks
        item = re.sub(r'^["\'`]|["\'`]$', '', item)

        # remove potential $(), ${}, ``
        item = re.sub(r'^\$[\(\{]|[\)\}]$', '', item)

        # if item has been converted to something other than a string
        # or an int, reconvert it to a string
        if type(item) not in ['str', 'int']:
            item = str(item)
        # replace "~" with home path
        item = os.path.expanduser(item)

        # expand shell wildcards using "echo"
        # i know, this a bit nasty...
        if re.findall('\$|\*|\?', item):
            # remove quotes if available
            item = re.sub("\"|\'", "", item)
            import subprocess
            p = subprocess.Popen("`which echo` %s" % item,
                                 shell=True,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
            cout = p.stdout

            try:
                item = cout.readlines()[0].decode('utf8').split(' ')[0]
                item = item.strip()
                item = os.path.expandvars(item)
            except IndexError:
                conf['logpath'].critical('*** Internal error: command not '
                                         'executed')
                return 1, conf

        tomatch = os.path.realpath(item)
        if os.path.isdir(tomatch) and tomatch[-1] != '/':
            tomatch += '/'
        match_allowed = re.findall(allowed_path_re, tomatch)
        if denied_path_re:
            match_denied = re.findall(denied_path_re, tomatch)
        else:
            match_denied = None

        # if path not allowed
        # case path executed: warn, and return 1
        # case completion: return 1
        if not match_allowed or match_denied:
            if not completion:
                ret, conf = warn_count('path',
                                       tomatch,
                                       conf,
                                       strict=strict,
                                       ssh=ssh)
            return 1, conf

    if not completion:
        if not re.findall(allowed_path_re, os.getcwd() + '/'):
            ret, conf = warn_count('path',
                                   tomatch,
                                   conf,
                                   strict=strict,
                                   ssh=ssh)
            os.chdir(conf['home_path'])
            conf['promptprint'] = utils.updateprompt(os.getcwd(),
                                                     conf)
            return 1, conf
    return 0, conf