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"
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);
}
}

View file

@ -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

View file

@ -31,6 +31,7 @@
* Dave Pare, 1989
* Steve McClure, 1998
* Ron Koenderink, 2005
* Markus Armbruster, 2005-2007
*/
#include <config.h>
@ -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;
}