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:
parent
72b01c8ba1
commit
02a9af06a0
3 changed files with 54 additions and 8 deletions
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue