]> granicus.if.org Git - sudo/commitdiff
Add separate I/O logging functions for tty in/out and stdin/stdout/stderr.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 5 May 2010 11:29:28 +0000 (07:29 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 5 May 2010 11:29:28 +0000 (07:29 -0400)
NOTE: stdin logging does not currently work and is disabled for now.

include/sudo_plugin.h
plugins/sample/sample_plugin.c
plugins/sudoers/sudoers.c
src/script.c

index 21c9c6a07411740f91c61215e772c6855c3159c6..26289f901965379195d77be9601a8de1caf34cef 100644 (file)
@@ -80,8 +80,11 @@ struct io_plugin {
        char * const user_info[], char * const user_env[]);
     void (*close)(int exit_status, int error); /* wait status or error */
     int (*show_version)(int verbose);
-    int (*log_input)(const char *buf, unsigned int len);
-    int (*log_output)(const char *buf, unsigned int len);
+    int (*log_ttyin)(const char *buf, unsigned int len);
+    int (*log_ttyout)(const char *buf, unsigned int len);
+    int (*log_stdin)(const char *buf, unsigned int len);
+    int (*log_stdout)(const char *buf, unsigned int len);
+    int (*log_stderr)(const char *buf, unsigned int len);
 };
 
 /* Internal use only */
index 03a8f0632e274f9caf744148cccb5781bec78b64..04a724714b45a47a082d99cc35ae6cccbfc027be 100644 (file)
@@ -349,12 +349,19 @@ struct policy_plugin sample_policy = {
     NULL /* invalidate */
 };
 
+/*
+ * Note: This plugin does not differentiate between tty and pipe I/O.
+ *       It all gets logged to the same file.
+ */
 struct io_plugin sample_io = {
     SUDO_IO_PLUGIN,
     SUDO_API_VERSION,
     io_open,
     io_close,
     io_version,
-    io_log_input,
-    io_log_output
+    io_log_input,      /* tty input */
+    io_log_output,     /* tty output */
+    io_log_input,      /* command stdin if not tty */
+    io_log_output,     /* command stdout if not tty */
+    io_log_output      /* command stderr if not tty */
 };
index 86d67a5b9209949ddd48fabdf2b5bedc6c64ce68..6c043df1b2989bbffcf301adab9acdc718184478 100644 (file)
@@ -1313,6 +1313,9 @@ struct io_plugin sudoers_io = {
     sudoers_io_open,
     sudoers_io_close,
     sudoers_io_version,
-    NULL,
-    sudoers_io_log_output
+    NULL,                      /* log_ttyin */
+    sudoers_io_log_output,     /* log_ttyout */
+    NULL,                      /* log_stdin */
+    sudoers_io_log_output,     /* log_stdout */
+    sudoers_io_log_output      /* log_stderr */
 };
index e61d20695d0eb38e1caf79a28b9dc9b88ea436e3..1e8082dc68b1b60fcf7d5e5a8ee92082bd369976 100644 (file)
@@ -146,9 +146,9 @@ script_setup(uid_t uid)
        error(1, "Can't get pty");
 }
 
-/* Call I/O plugin input method. */
+/* Call I/O plugin tty input log method. */
 static int
-log_input(char *buf, unsigned int n)
+log_ttyin(char *buf, unsigned int n)
 {
     struct plugin_container *plugin;
     sigset_t omask;
@@ -157,8 +157,8 @@ log_input(char *buf, unsigned int n)
     sigprocmask(SIG_BLOCK, &ttyblock, &omask);
 
     tq_foreach_fwd(&io_plugins, plugin) {
-       if (plugin->u.io->log_input) {
-           if (!plugin->u.io->log_input(buf, n)) {
+       if (plugin->u.io->log_ttyin) {
+           if (!plugin->u.io->log_ttyin(buf, n)) {
                rval = FALSE;
                break;
            }
@@ -169,9 +169,9 @@ log_input(char *buf, unsigned int n)
     return rval;
 }
 
-/* Call I/O plugin output method. */
+/* Call I/O plugin stdin log method. */
 static int
-log_output(char *buf, unsigned int n)
+log_stdin(char *buf, unsigned int n)
 {
     struct plugin_container *plugin;
     sigset_t omask;
@@ -180,8 +180,77 @@ log_output(char *buf, unsigned int n)
     sigprocmask(SIG_BLOCK, &ttyblock, &omask);
 
     tq_foreach_fwd(&io_plugins, plugin) {
-       if (plugin->u.io->log_output) {
-           if (!plugin->u.io->log_output(buf, n)) {
+       if (plugin->u.io->log_stdin) {
+           if (!plugin->u.io->log_stdin(buf, n)) {
+               rval = FALSE;
+               break;
+           }
+       }
+    }
+
+    sigprocmask(SIG_SETMASK, &omask, NULL);
+    return rval;
+}
+
+/* Call I/O plugin tty output log method. */
+static int
+log_ttyout(char *buf, unsigned int n)
+{
+    struct plugin_container *plugin;
+    sigset_t omask;
+    int rval = TRUE;
+
+    sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+
+    tq_foreach_fwd(&io_plugins, plugin) {
+       if (plugin->u.io->log_ttyout) {
+           if (!plugin->u.io->log_ttyout(buf, n)) {
+               rval = FALSE;
+               break;
+           }
+       }
+    }
+
+    sigprocmask(SIG_SETMASK, &omask, NULL);
+    return rval;
+}
+
+/* Call I/O plugin stdout log method. */
+static int
+log_stdout(char *buf, unsigned int n)
+{
+    struct plugin_container *plugin;
+    sigset_t omask;
+    int rval = TRUE;
+
+    sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+
+    tq_foreach_fwd(&io_plugins, plugin) {
+       if (plugin->u.io->log_stdout) {
+           if (!plugin->u.io->log_stdout(buf, n)) {
+               rval = FALSE;
+               break;
+           }
+       }
+    }
+
+    sigprocmask(SIG_SETMASK, &omask, NULL);
+    return rval;
+}
+
+/* Call I/O plugin stderr log method. */
+static int
+log_stderr(char *buf, unsigned int n)
+{
+    struct plugin_container *plugin;
+    sigset_t omask;
+    int rval = TRUE;
+
+    sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+
+    tq_foreach_fwd(&io_plugins, plugin) {
+       if (plugin->u.io->log_stderr) {
+           if (!plugin->u.io->log_stderr(buf, n)) {
                rval = FALSE;
                break;
            }
@@ -432,36 +501,46 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
        /*
         * Setup stdin/stdout/stderr for child, to be duped after forking.
         */
-       /* XXX - use a pipe for stdin if not a tty? */
-       script_fds[SFD_STDIN] = isatty(STDIN_FILENO) ?
+#ifdef notyet
+       script_fds[SFD_STDIN] = script_fds[SFD_SLAVE];
+#else
+       script_fds[SFD_STDIN] = isatty(STDIN_FILENO) ?
            script_fds[SFD_SLAVE] : STDIN_FILENO;
+#endif
        script_fds[SFD_STDOUT] = script_fds[SFD_SLAVE];
        script_fds[SFD_STDERR] = script_fds[SFD_SLAVE];
 
        /* Copy /dev/tty -> pty master */
        iobufs = io_buf_new(script_fds[SFD_USERTTY], script_fds[SFD_MASTER],
-           log_input, iobufs);
+           log_ttyin, iobufs);
 
        /* Copy pty master -> /dev/tty */
        iobufs = io_buf_new(script_fds[SFD_MASTER], script_fds[SFD_USERTTY],
-           log_output, iobufs);
+           log_ttyout, iobufs);
 
        /*
-        * If either stdout or stderr is not a tty we use a pipe
+        * If either stdin, stdout or stderr is not a tty we use a pipe
         * to interpose ourselves instead of duping the pty fd.
-        * NOTE: we don't currently log tty/stdout/stderr separately.
         */
+#ifdef notyet
+       if (!isatty(STDIN_FILENO)) {
+           if (pipe(pv) != 0)
+               error(1, "unable to create pipe");
+           iobufs = io_buf_new(STDIN_FILENO, pv[1], log_stdin, iobufs);
+           script_fds[SFD_STDIN] = pv[0];
+       }
+#endif
        if (!isatty(STDOUT_FILENO)) {
            ttyout = FALSE;
            if (pipe(pv) != 0)
                error(1, "unable to create pipe");
-           iobufs = io_buf_new(pv[0], STDOUT_FILENO, log_output, iobufs);
+           iobufs = io_buf_new(pv[0], STDOUT_FILENO, log_stdout, iobufs);
            script_fds[SFD_STDOUT] = pv[1];
        }
        if (!isatty(STDERR_FILENO)) {
            if (pipe(pv) != 0)
                error(1, "unable to create pipe");
-           iobufs = io_buf_new(pv[0], STDERR_FILENO, log_output, iobufs);
+           iobufs = io_buf_new(pv[0], STDERR_FILENO, log_stderr, iobufs);
            script_fds[SFD_STDERR] = pv[1];
        }
 
@@ -617,6 +696,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
            }
        }
 
+    retry:
        nready = select(maxfd + 1, fdsr, fdsw, NULL, NULL);
        if (nready == -1) {
            if (errno == EINTR)
@@ -676,9 +756,9 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
                    sizeof(iob->buf) - iob->len);
                if (n == -1) {
                    if (errno == EINTR)
-                       continue;
+                       goto retry;
                    if (errno != EAGAIN)
-                       break;
+                       goto io_error;
                } else {
                    if (n == 0)
                        break; /* got EOF */
@@ -692,9 +772,9 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
                    iob->len - iob->off);
                if (n == -1) {
                    if (errno == EINTR)
-                       continue;
+                       goto retry;
                    if (errno != EAGAIN)
-                       break;
+                       goto io_error;
                } else {
                    iob->off += n;
                }
@@ -702,6 +782,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
        }
     }
 
+io_error:
     if (log_io) {
        /* Flush any remaining output (the plugin already got it) */
        n = fcntl(script_fds[SFD_USERTTY], F_GETFL, 0);
@@ -892,6 +973,16 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
     }
     close(errpipe[1]);
 
+#ifdef notyet
+    /* If any of stdin/stdout/stderr are pipes, close them in parent. */
+    if (script_fds[SFD_STDIN] != script_fds[SFD_SLAVE])
+       close(script_fds[SFD_STDIN]);
+    if (script_fds[SFD_STDOUT] != script_fds[SFD_SLAVE])
+       close(script_fds[SFD_STDOUT]);
+    if (script_fds[SFD_STDERR] != script_fds[SFD_SLAVE])
+       close(script_fds[SFD_STDERR]);
+#endif
+
     /*
      * Put child in its own process group.  If we are starting the command
      * in the foreground, assign its pgrp to the tty.
@@ -1011,6 +1102,7 @@ flush_output(struct io_buffer *iobufs)
 
     /* Drain output buffers. */
     for (iob = iobufs; iob; iob = iob->next) {
+       /* XXX - check wfd against slave instead? */
        if (iob->rfd == script_fds[SFD_USERTTY])
            continue;
        while (iob->len > iob->off) {