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.
This commit is contained in:
Markus Armbruster 2007-11-28 07:10:27 +00:00
parent 51846ec38f
commit 2dbc45eff7
3 changed files with 23 additions and 13 deletions

View file

@ -45,6 +45,7 @@ extern char empirehost[];
extern char empireport[]; extern char empireport[];
extern int eight_bit_clean; extern int eight_bit_clean;
extern int input_fd; extern int input_fd;
extern int send_eof;
extern FILE *auxfp; extern FILE *auxfp;
extern char *SO; extern char *SO;
extern char *SE; extern char *SE;

View file

@ -51,6 +51,7 @@
#define INTR_COOKIE "\naborted\n" #define INTR_COOKIE "\naborted\n"
int input_fd; int input_fd;
int send_eof; /* need to send EOF_COOKIE */
static volatile sig_atomic_t send_intr; /* need to send INTR_COOKIE */ static volatile sig_atomic_t send_intr; /* need to send INTR_COOKIE */
/* /*
@ -218,7 +219,6 @@ play(int sock)
struct sigaction sa; struct sigaction sa;
struct ring inbuf; /* input buffer, draining to SOCK */ struct ring inbuf; /* input buffer, draining to SOCK */
int eof_fd0; /* read fd 0 hit EOF? */ int eof_fd0; /* read fd 0 hit EOF? */
int send_eof; /* need to send EOF_COOKIE */
fd_set rdfd, wrfd; fd_set rdfd, wrfd;
int n; int n;
@ -229,7 +229,8 @@ play(int sock)
sigaction(SIGPIPE, &sa, NULL); sigaction(SIGPIPE, &sa, NULL);
ring_init(&inbuf); ring_init(&inbuf);
eof_fd0 = send_eof = 0; eof_fd0 = send_eof = send_intr = 0;
input_fd = 0;
for (;;) { for (;;) {
FD_ZERO(&rdfd); FD_ZERO(&rdfd);
@ -278,7 +279,6 @@ play(int sock)
send_eof++; send_eof++;
if (input_fd) { if (input_fd) {
/* execute done, switch back to fd 0 */ /* execute done, switch back to fd 0 */
if (input_fd > 0)
close(input_fd); close(input_fd);
input_fd = 0; input_fd = 0;
} else { } else {
@ -308,11 +308,6 @@ play(int sock)
} }
if (n == 0) if (n == 0)
return 0; return 0;
if (input_fd < 0) {
/* execute failed */
input_fd = 0;
send_eof++;
}
} }
} }
} }

View file

@ -51,6 +51,7 @@ FILE *auxfp;
static FILE *redir_fp; static FILE *redir_fp;
static FILE *pipe_fp; static FILE *pipe_fp;
static int executing;
static size_t input_to_forget; static size_t input_to_forget;
static void prompt(int, char *, char *); static void prompt(int, char *, char *);
@ -126,6 +127,7 @@ prompt(int code, char *prompt, char *teles)
(void)pclose(pipe_fp); (void)pclose(pipe_fp);
pipe_fp = NULL; pipe_fp = NULL;
} }
executing = 0;
if (input_to_forget) { if (input_to_forget) {
forget_input(input_to_forget); forget_input(input_to_forget);
input_to_forget = 0; input_to_forget = 0;
@ -157,6 +159,11 @@ redir_authorized(char *arg, char *attempt)
{ {
size_t seen = seen_input(arg); 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)) { if (!seen || (input_to_forget && input_to_forget != seen)) {
fprintf(stderr, "WARNING! Server attempted to %s %s\n", fprintf(stderr, "WARNING! Server attempted to %s %s\n",
attempt, arg); attempt, arg);
@ -217,7 +224,7 @@ doredir(char *p)
static void static void
dopipe(char *p) dopipe(char *p)
{ {
if (!redir_authorized(p, "pipe to command")) if (!redir_authorized(p, "pipe to shell command"))
return; return;
if (*p++ != '|') { if (*p++ != '|') {
fprintf(stderr, "WARNING! Weird pipe %s", p); fprintf(stderr, "WARNING! Weird pipe %s", p);
@ -239,22 +246,29 @@ dopipe(char *p)
static void static void
doexecute(char *p) 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; return;
}
p = fname(p); p = fname(p);
if (*p == 0) { if (*p == 0) {
fprintf(stderr, "Need a file to execute\n"); fprintf(stderr, "Need a file to execute\n");
send_eof++;
return; 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", fprintf(stderr, "Can't open execute file %s: %s\n",
p, strerror(errno)); p, strerror(errno));
send_eof++;
return; return;
} }
input_fd = fd;
executing = 1;
} }
void void