From 2dbc45eff7ea9365b998049c5922ca6cb9146e8a Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 28 Nov 2007 07:10:27 +0000 Subject: [PATCH] Flaws in the Empire protocol make redirections within execute next to impossible to implement correctly, and nested execute practically useless (#116377). Catch and refuse those: (executing): New. (doexecute, prompt): Set and clear it. (redir_authorized): Reject if set. (doexecute, play): Don't signal doexecute() failure through input_fd, because that screws up up when we're executing already. Increment send_eof in doexecute() instead. (send_eof): External linkage. --- src/client/misc.h | 1 + src/client/play.c | 13 ++++--------- src/client/servcmd.c | 22 ++++++++++++++++++---- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/client/misc.h b/src/client/misc.h index ee9c9e06..8cb8acd3 100644 --- a/src/client/misc.h +++ b/src/client/misc.h @@ -45,6 +45,7 @@ extern char empirehost[]; extern char empireport[]; extern int eight_bit_clean; extern int input_fd; +extern int send_eof; extern FILE *auxfp; extern char *SO; extern char *SE; diff --git a/src/client/play.c b/src/client/play.c index 956ca410..ff465e5f 100644 --- a/src/client/play.c +++ b/src/client/play.c @@ -51,6 +51,7 @@ #define INTR_COOKIE "\naborted\n" int input_fd; +int send_eof; /* need to send EOF_COOKIE */ static volatile sig_atomic_t send_intr; /* need to send INTR_COOKIE */ /* @@ -218,7 +219,6 @@ play(int sock) struct sigaction sa; struct ring inbuf; /* input buffer, draining to SOCK */ int eof_fd0; /* read fd 0 hit EOF? */ - int send_eof; /* need to send EOF_COOKIE */ fd_set rdfd, wrfd; int n; @@ -229,7 +229,8 @@ play(int sock) sigaction(SIGPIPE, &sa, NULL); ring_init(&inbuf); - eof_fd0 = send_eof = 0; + eof_fd0 = send_eof = send_intr = 0; + input_fd = 0; for (;;) { FD_ZERO(&rdfd); @@ -278,8 +279,7 @@ play(int sock) send_eof++; if (input_fd) { /* execute done, switch back to fd 0 */ - if (input_fd > 0) - close(input_fd); + close(input_fd); input_fd = 0; } else { /* stop reading input, drain socket ring buffers */ @@ -308,11 +308,6 @@ play(int sock) } if (n == 0) return 0; - if (input_fd < 0) { - /* execute failed */ - input_fd = 0; - send_eof++; - } } } } diff --git a/src/client/servcmd.c b/src/client/servcmd.c index 0b837f3e..aaab478a 100644 --- a/src/client/servcmd.c +++ b/src/client/servcmd.c @@ -51,6 +51,7 @@ FILE *auxfp; static FILE *redir_fp; static FILE *pipe_fp; +static int executing; static size_t input_to_forget; static void prompt(int, char *, char *); @@ -126,6 +127,7 @@ prompt(int code, char *prompt, char *teles) (void)pclose(pipe_fp); pipe_fp = NULL; } + executing = 0; if (input_to_forget) { forget_input(input_to_forget); input_to_forget = 0; @@ -157,6 +159,11 @@ redir_authorized(char *arg, char *attempt) { size_t seen = seen_input(arg); + if (executing) { + fprintf(stderr, "Can't %s in a script\n", attempt); + return 0; + } + if (!seen || (input_to_forget && input_to_forget != seen)) { fprintf(stderr, "WARNING! Server attempted to %s %s\n", attempt, arg); @@ -217,7 +224,7 @@ doredir(char *p) static void dopipe(char *p) { - if (!redir_authorized(p, "pipe to command")) + if (!redir_authorized(p, "pipe to shell command")) return; if (*p++ != '|') { fprintf(stderr, "WARNING! Weird pipe %s", p); @@ -239,22 +246,29 @@ dopipe(char *p) static void doexecute(char *p) { - input_fd = -1; /* make sure play() terminates exec */ + int fd; - if (!redir_authorized(p, "read file")) + if (!redir_authorized(p, "execute script file")) { + send_eof++; return; + } p = fname(p); if (*p == 0) { fprintf(stderr, "Need a file to execute\n"); + send_eof++; return; } - if ((input_fd = open(p, O_RDONLY)) < 0) { + if ((fd = open(p, O_RDONLY)) < 0) { fprintf(stderr, "Can't open execute file %s: %s\n", p, strerror(errno)); + send_eof++; return; } + + input_fd = fd; + executing = 1; } void