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:
parent
51846ec38f
commit
2dbc45eff7
3 changed files with 23 additions and 13 deletions
|
@ -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;
|
||||||
|
|
|
@ -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,8 +279,7 @@ 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 {
|
||||||
/* stop reading input, drain socket ring buffers */
|
/* stop reading input, drain socket ring buffers */
|
||||||
|
@ -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++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue