summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2007-11-29 16:56:29 -0800
committerAn-Cheng Huang <ancheng@vyatta.com>2007-11-29 16:56:29 -0800
commit05ac050c585a52df2f475bface59562656b08b4e (patch)
treec10f3fcd19bd7d1698938772c155f7361f651a10
parent027bd747d8dd050937dc6344c207530e79808b89 (diff)
downloadvyatta-bash-05ac050c585a52df2f475bface59562656b08b4e.tar.gz
vyatta-bash-05ac050c585a52df2f475bface59562656b08b4e.zip
restricted modes:
* do not restart completion after a "connector" or a '`'. * only allow simple commands and "pipe" in "full" mode. * add mechanism to limit allowed pipe commands. * remove unnecessary command checks (non-interactive and same command).
-rw-r--r--bashline.c21
-rw-r--r--eval.c91
2 files changed, 101 insertions, 11 deletions
diff --git a/bashline.c b/bashline.c
index c0f67c9..d11904a 100644
--- a/bashline.c
+++ b/bashline.c
@@ -941,9 +941,12 @@ find_cmd_start (start)
register int s, os;
os = 0;
- while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS)) <= start) &&
- rl_line_buffer[s])
- os = s+1;
+ if (!in_vyatta_restricted_mode(OUTPUT)) {
+ while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS))
+ <= start)
+ && rl_line_buffer[s])
+ os = s+1;
+ }
return os;
}
@@ -953,7 +956,11 @@ find_cmd_end (end)
{
register int e;
- e = skip_to_delim (rl_line_buffer, end, COMMAND_SEPARATORS);
+ if (!in_vyatta_restricted_mode(OUTPUT)) {
+ e = skip_to_delim (rl_line_buffer, end, COMMAND_SEPARATORS);
+ } else {
+ e = strlen(rl_line_buffer);
+ }
return e;
}
@@ -1038,7 +1045,9 @@ attempt_shell_completion (text, start, end)
}
else if (member (rl_line_buffer[ti], command_separator_chars))
{
- in_command_position++;
+ if (!in_vyatta_restricted_mode(OUTPUT)) {
+ in_command_position++;
+ }
if (check_redir (ti) == 1)
in_command_position = 0;
@@ -1060,7 +1069,7 @@ attempt_shell_completion (text, start, end)
it can be the start or end of an old-style command substitution, or
unmatched. If it's unmatched, both calls to unclosed_pair will
succeed. */
- if (*text == '`' &&
+ if (*text == '`' && !in_vyatta_restricted_mode(OUTPUT) &&
(in_command_position || (unclosed_pair (rl_line_buffer, start, "`") &&
unclosed_pair (rl_line_buffer, end, "`"))))
matches = rl_completion_matches (text, command_subst_completion_function);
diff --git a/eval.c b/eval.c
index 72e5a45..4848e7d 100644
--- a/eval.c
+++ b/eval.c
@@ -199,7 +199,7 @@ send_pwd_to_eterm ()
}
static int
-is_in_command_list(const char *cmd, const char *cmds[])
+is_in_command_list(const char *cmd, char *cmds[])
{
int idx = 0;
for (idx = 0; cmds[idx]; idx++) {
@@ -211,6 +211,64 @@ is_in_command_list(const char *cmd, const char *cmds[])
}
static int
+is_vyatta_restricted_pipe_command(WORD_LIST *words)
+{
+ char *allowed_commands[] = { "more", NULL };
+ if (words) {
+ if (!words->next) {
+ /* only 1 word */
+ if (is_in_command_list(words->word->word, allowed_commands)) {
+ /* allowed */
+ return 1;
+ }
+ }
+ }
+ /* not allowed */
+ return 0;
+}
+
+static int
+is_vyatta_restricted_command(COMMAND *cmd)
+{
+ struct simple_com *cS;
+ struct connection *cC;
+
+ if (!cmd) {
+ return 1;
+ }
+
+ switch (cmd->type) {
+ case cm_simple:
+ cS = cmd->value.Simple;
+ if (!(cS->redirects)) {
+ /* simple command, no redirects => allowed */
+ return 1;
+ }
+ break;
+ case cm_connection:
+ cC = cmd->value.Connection;
+ if (cC->connector == '|') {
+ if ((cC->first->type == cm_simple) && (cC->second->type == cm_simple)) {
+ struct simple_com *cS1 = cC->first->value.Simple;
+ struct simple_com *cS2 = cC->second->value.Simple;
+ if (!(cS1->redirects) && !(cS2->redirects)) {
+ /* both are simple and no redirects */
+ if (is_vyatta_restricted_pipe_command(cS2->words)) {
+ /* pipe command is allowed => allowed */
+ return 1;
+ }
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ /* not allowed */
+ return 0;
+}
+
+static int
is_vyatta_cfg_command(const char *cmd)
{
char *valid_commands[] = { "set", "delete", "commit", "save", "load",
@@ -243,8 +301,10 @@ is_vyatta_op_command(const char *cmd)
return (ret) ? 1 : is_in_command_list(cmd, other_commands);
}
+static char *prev_cmdline = NULL;
+
static int
-is_vyatta_command(char *cmdline)
+is_vyatta_command(char *cmdline, COMMAND *cmd)
{
char *cfg = getenv("_OFR_CONFIGURE");
int in_cfg = (cfg) ? (strcmp(cfg, "ok") == 0) : 0;
@@ -252,11 +312,25 @@ is_vyatta_command(char *cmdline)
char *end = NULL;
char save = 0;
int ret = 0;
+
+ if (!prev_cmdline) {
+ prev_cmdline = strdup("");
+ }
+ if (strcmp(cmdline, prev_cmdline) == 0) {
+ /* still at the same line. not checking. */
+ return 1;
+ }
+ if (!is_vyatta_restricted_command(cmd)) {
+ return 0;
+ }
+
while (*start && (whitespace(*start) || *start == '\n')) {
start++;
}
if (*start == 0) {
- /* empty command line */
+ /* empty command line is valid */
+ free(prev_cmdline);
+ prev_cmdline = strdup(cmdline);
return 1;
}
end = start;
@@ -272,6 +346,12 @@ is_vyatta_command(char *cmdline)
ret = is_vyatta_op_command(start);
}
*end = save;
+
+ if (ret) {
+ /* valid command */
+ free(prev_cmdline);
+ prev_cmdline = strdup(cmdline);
+ }
return ret;
}
@@ -305,8 +385,9 @@ parse_command ()
r = yyparse ();
#if defined (READLINE)
- if (in_vyatta_restricted_mode(FULL) && current_readline_line) {
- if (!is_vyatta_command(current_readline_line)) {
+ if (interactive && in_vyatta_restricted_mode(FULL)
+ && current_readline_line) {
+ if (!is_vyatta_command(current_readline_line, global_command)) {
printf("Invalid command\n");
current_readline_line_index = 0;
current_readline_line[0] = '\n';