Fix redirections with execute. Redirection consumed the remembered

input, and execute couldn't find it and mistakenly raised the
tampering deity alarm.  Closes #804644:
(saved_bytes): New.
(save_input): Set it.
(forget_input): New.
(seen_input): Don't discard, return a value for forget_input().
(save_input): Return a value for forget_input(), just because it makes
sense.
(input_to_forget, redir_authorized, prompt): Save value of
seen_input() to new input_to_forget in redir_authorized(), pass it to
forget_input() in prompt().
This commit is contained in:
Markus Armbruster 2007-11-18 09:41:59 +00:00
parent 72b01c8ba1
commit 02a9af06a0
3 changed files with 54 additions and 8 deletions

View file

@ -39,8 +39,15 @@
#include "secure.h" #include "secure.h"
struct ring recent_input; struct ring recent_input;
static size_t saved_bytes;
void /*
* Remember line of input INP for a while.
* It must end with a newline.
* Return value is suitable for forget_input(): it makes it forget all
* input up to and including this line.
*/
size_t
save_input(char *inp) save_input(char *inp)
{ {
size_t len = strlen(inp); size_t len = strlen(inp);
@ -53,19 +60,47 @@ save_input(char *inp)
ring_discard(&recent_input, ring_search(&recent_input, "\n")); ring_discard(&recent_input, ring_search(&recent_input, "\n"));
ring_putm(&recent_input, inp, len); ring_putm(&recent_input, inp, len);
} }
saved_bytes += len;
return saved_bytes;
} }
int /*
* Can you still remember a line of input that ends with TAIL?
* It must end with a newline.
* Return non-zero iff TAIL can be remembered.
* Passing that value to forget_input() will forget all input up to
* and including this line.
*/
size_t
seen_input(char *tail) seen_input(char *tail)
{ {
size_t len = strlen(tail); size_t len = strlen(tail);
int dist = ring_search(&recent_input, tail); size_t remembered = ring_len(&recent_input);
int dist;
assert(len && tail[len - 1] == '\n'); assert(len && tail[len - 1] == '\n');
dist = ring_search(&recent_input, tail);
if (dist < 0) if (dist < 0)
return 0; return 0;
ring_discard(&recent_input, dist + len); assert(dist + len <= remembered && remembered <= saved_bytes);
return 1; return saved_bytes - remembered + dist + len;
}
/*
* Forget remembered input up to SEEN.
* SEEN should be obtained from save_input() or seen_input().
*/
void
forget_input(size_t seen)
{
size_t forgotten = saved_bytes - ring_len(&recent_input);
assert(seen);
if (seen > forgotten) {
assert(ring_peek(&recent_input, seen - forgotten - 1) == '\n');
ring_discard(&recent_input, seen - forgotten);
}
} }

View file

@ -34,7 +34,8 @@
#ifndef SECURE_H #ifndef SECURE_H
#define SECURE_H #define SECURE_H
extern void save_input(char *); extern size_t save_input(char *);
extern int seen_input(char *); extern size_t seen_input(char *);
extern void forget_input(size_t);
#endif #endif

View file

@ -31,6 +31,7 @@
* Dave Pare, 1989 * Dave Pare, 1989
* Steve McClure, 1998 * Steve McClure, 1998
* Ron Koenderink, 2005 * Ron Koenderink, 2005
* Markus Armbruster, 2005-2007
*/ */
#include <config.h> #include <config.h>
@ -50,6 +51,7 @@ FILE *auxfp;
static FILE *redir_fp; static FILE *redir_fp;
static FILE *pipe_fp; static FILE *pipe_fp;
static size_t input_to_forget;
static void prompt(int, char *, char *); static void prompt(int, char *, char *);
static void doredir(char *p); static void doredir(char *p);
@ -124,7 +126,12 @@ prompt(int code, char *prompt, char *teles)
(void)pclose(pipe_fp); (void)pclose(pipe_fp);
pipe_fp = NULL; pipe_fp = NULL;
} }
if (input_to_forget) {
forget_input(input_to_forget);
input_to_forget = 0;
}
} }
nl = code == C_PROMPT || code == C_INFORM ? "\n" : ""; nl = code == C_PROMPT || code == C_INFORM ? "\n" : "";
printf("%s%s%s", nl, teles, prompt); printf("%s%s%s", nl, teles, prompt);
fflush(stdout); fflush(stdout);
@ -148,11 +155,14 @@ fname(char *s)
static int static int
redir_authorized(char *arg, char *attempt) redir_authorized(char *arg, char *attempt)
{ {
if (!seen_input(arg)) { size_t seen = seen_input(arg);
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);
return 0; return 0;
} }
input_to_forget = seen;
return 1; return 1;
} }