]> git.pond.sub.org Git - empserver/commitdiff
Fix redirections with execute. Redirection consumed the remembered
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 18 Nov 2007 09:41:59 +0000 (09:41 +0000)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 18 Nov 2007 09:41:59 +0000 (09:41 +0000)
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
src/client/secure.h
src/client/servcmd.c

index deecea2a588a1900208a01fdc2ae4efcdf41cdfb..00a2ac82ff078609c45e4466ad6f234a31a53573 100644 (file)
 #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);
+    }
 }
index c05636fd7c2c9df08f30c751d2dbc665779c07a2..2f87f4b3334cbe98e92f37e4165a62388cca8e1c 100644 (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
index 19121f0371e46816f6951d0d9b027f17f1de4b51..0b837f3ebd464927fc43099addce610f8e63f82c 100644 (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;
 }