From 02a9af06a0e3a4e38cc81b33801f9daee360148f Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 18 Nov 2007 09:41:59 +0000 Subject: [PATCH] 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(). --- src/client/secure.c | 45 +++++++++++++++++++++++++++++++++++++++----- src/client/secure.h | 5 +++-- src/client/servcmd.c | 12 +++++++++++- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/client/secure.c b/src/client/secure.c index deecea2a..00a2ac82 100644 --- a/src/client/secure.c +++ b/src/client/secure.c @@ -39,8 +39,15 @@ #include "secure.h" 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) { size_t len = strlen(inp); @@ -53,19 +60,47 @@ save_input(char *inp) ring_discard(&recent_input, ring_search(&recent_input, "\n")); 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) { 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'); + dist = ring_search(&recent_input, tail); if (dist < 0) return 0; - ring_discard(&recent_input, dist + len); - return 1; + assert(dist + len <= remembered && remembered <= saved_bytes); + 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); + } } diff --git a/src/client/secure.h b/src/client/secure.h index c05636fd..2f87f4b3 100644 --- a/src/client/secure.h +++ b/src/client/secure.h @@ -34,7 +34,8 @@ #ifndef SECURE_H #define SECURE_H -extern void save_input(char *); -extern int seen_input(char *); +extern size_t save_input(char *); +extern size_t seen_input(char *); +extern void forget_input(size_t); #endif diff --git a/src/client/servcmd.c b/src/client/servcmd.c index 19121f03..0b837f3e 100644 --- a/src/client/servcmd.c +++ b/src/client/servcmd.c @@ -31,6 +31,7 @@ * Dave Pare, 1989 * Steve McClure, 1998 * Ron Koenderink, 2005 + * Markus Armbruster, 2005-2007 */ #include @@ -50,6 +51,7 @@ FILE *auxfp; static FILE *redir_fp; static FILE *pipe_fp; +static size_t input_to_forget; static void prompt(int, char *, char *); static void doredir(char *p); @@ -124,7 +126,12 @@ prompt(int code, char *prompt, char *teles) (void)pclose(pipe_fp); pipe_fp = NULL; } + if (input_to_forget) { + forget_input(input_to_forget); + input_to_forget = 0; + } } + nl = code == C_PROMPT || code == C_INFORM ? "\n" : ""; printf("%s%s%s", nl, teles, prompt); fflush(stdout); @@ -148,11 +155,14 @@ fname(char *s) static int 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", attempt, arg); return 0; } + input_to_forget = seen; return 1; }