From 33e9b03f81e871594b1f8ab1740c09cd5593c27c Mon Sep 17 00:00:00 2001 From: Scott Little Date: Fri, 26 Aug 2016 16:04:44 -0400 Subject: [PATCH 1/2] WRS: Patch500: bash-history-syslog.patch --- bashhist.c | 78 +- config-top.h | 2 +- shell.c | 111 +++ 3 files changed, 173 insertions(+), 18 deletions(-) diff --git a/bashhist.c b/bashhist.c index 7240a5b..5116f8d 100644 --- a/bashhist.c +++ b/bashhist.c @@ -38,10 +38,6 @@ #include "bashintl.h" -#if defined (SYSLOG_HISTORY) -# include -#endif - #include "shell.h" #include "flags.h" #include "input.h" @@ -54,6 +50,10 @@ #include #include +#if defined (SYSLOG_HISTORY) +#include +#endif + #if defined (READLINE) # include "bashline.h" extern int rl_done, rl_dispatching; /* should really include readline.h */ @@ -68,6 +68,12 @@ static int check_history_control __P((char *)); static void hc_erasedups __P((char *)); static void really_add_history __P((char *)); + +#if defined (SYSLOG_HISTORY) +static void send_cmdline_mq __P((const char *)); +int cmdline_hist_sock[2]; +#endif + static struct ignorevar histignore = { "HISTIGNORE", @@ -700,22 +706,11 @@ check_add_history (line, force) } #if defined (SYSLOG_HISTORY) -#define SYSLOG_MAXLEN 600 - void bash_syslog_history (line) const char *line; { - char trunc[SYSLOG_MAXLEN]; - - if (strlen(line) < SYSLOG_MAXLEN) - syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line); - else - { - strncpy (trunc, line, SYSLOG_MAXLEN); - trunc[SYSLOG_MAXLEN - 1] = '\0'; - syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d %s", getpid(), current_user.uid, trunc); - } + send_cmdline_mq (line); } #endif @@ -769,6 +764,10 @@ bash_add_history (line) sprintf (new_line, "%s%s%s", current->line, chars_to_add, line); offset = where_history (); old = replace_history_entry (offset, new_line, current->data); + +#if defined (SYSLOG_HISTORY) + bash_syslog_history (new_line); +#endif free (new_line); if (old) @@ -779,11 +778,13 @@ bash_add_history (line) } if (add_it) + { really_add_history (line); #if defined (SYSLOG_HISTORY) - bash_syslog_history (line); + bash_syslog_history (line); #endif + } using_history (); } @@ -906,4 +907,47 @@ history_should_ignore (line) return match; } + +#if defined (SYSLOG_HISTORY) + +#define MQ_SEND_MAX_ATTEMPT 2 + +static void +send_cmdline_mq (line) + const char *line; +{ + int ret = 0; + int attempt = 0; + int fail = 0; + size_t len_snd; + int sndbuf_size; + + do { + if (attempt >= MQ_SEND_MAX_ATTEMPT) + { + fail = 1; + break; + } + + len_snd = strlen(line)+1; + ret = send (cmdline_hist_sock[0], line, len_snd, MSG_DONTWAIT); + if (ret == EMSGSIZE) + { + socklen_t optlen = sizeof(sndbuf_size); + ret = getsockopt(cmdline_hist_sock[0], SOL_SOCKET, SO_SNDBUF, + &sndbuf_size, &optlen); + if (ret == 0) { + len_snd = sndbuf_size - 1; + continue; + } + } + + attempt ++; + } while (ret < 0 && (errno == EAGAIN || errno == EINTR)); + + return; +} + +#endif /*SYSLOG_HISTORY*/ + #endif /* HISTORY */ diff --git a/config-top.h b/config-top.h index 01e934e..c22c883 100644 --- a/config-top.h +++ b/config-top.h @@ -103,7 +103,7 @@ /* Define if you want each line saved to the history list in bashhist.c: bash_add_history() to be sent to syslog(). */ -/* #define SYSLOG_HISTORY */ +#define SYSLOG_HISTORY #if defined (SYSLOG_HISTORY) # define SYSLOG_FACILITY LOG_USER # define SYSLOG_LEVEL LOG_INFO diff --git a/shell.c b/shell.c index 6f9afcd..7eca4e3 100644 --- a/shell.c +++ b/shell.c @@ -72,6 +72,12 @@ # include #endif +#if defined (SYSLOG_HISTORY) +# include +# include +# include "error.h" +#endif + #if defined (READLINE) # include "bashline.h" #endif @@ -106,6 +112,9 @@ extern int array_needs_making; extern int gnu_error_format; extern char *primary_prompt, *secondary_prompt; extern char *this_command_name; +#if defined (SYSLOG_HISTORY) +extern int cmdline_hist_sock[2]; +#endif /* Non-zero means that this shell has already been run; i.e. you should call shell_reinitialize () if you need to start afresh. */ @@ -223,6 +232,7 @@ int dump_po_strings; /* Dump strings in $"..." in po format */ int wordexp_only = 0; /* Do word expansion only */ int protected_mode = 0; /* No command substitution with --wordexp */ + #if defined (STRICT_POSIX) int posixly_correct = 1; /* Non-zero means posix.2 superset. */ #else @@ -327,6 +337,10 @@ static void shell_reinitialize __P((void)); static void show_shell_usage __P((FILE *, int)); +#if defined (SYSLOG_HISTORY) +static pid_t make_consumer_process __P(()); +#endif + #ifdef __CYGWIN__ static void _cygwin32_check_tmp () @@ -369,6 +383,11 @@ main (argc, argv, env) env = environ; #endif /* __OPENNT */ + +#if defined (SYSLOG_HISTORY) + pid_t con_pid; +#endif + USE_VAR(argc); USE_VAR(argv); USE_VAR(env); @@ -747,6 +766,11 @@ main (argc, argv, env) /* Initialize terminal state for interactive shells after the .bash_profile and .bashrc are interpreted. */ get_tty_state (); + +#if defined (SYSLOG_HISTORY) + /*fork a child for bash history logging consumption*/ + con_pid = make_consumer_process (); +#endif } #if !defined (ONESHOT) @@ -757,6 +781,13 @@ main (argc, argv, env) /* Read commands until exit condition. */ reader_loop (); + +#if defined (SYSLOG_HISTORY) + if (interactive_shell && con_pid > 0) { + kill(con_pid, SIGKILL); + } +#endif + exit_shell (last_command_exit_value); } @@ -1619,6 +1650,86 @@ set_shell_name (argv0) shell_name = PROGRAM; } + +#if defined (SYSLOG_HISTORY) +#define SYSLOG_MAXLEN 1200 + +/* Fork child process for bash history logging, handling errors. + Returns the pid of the newly made child in parent process context + and will not return in child process context. */ +static pid_t +make_consumer_process () +{ + pid_t pid; + + if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0, cmdline_hist_sock) == -1) + { + return -1; + } + + + pid = fork (); + if (pid < 0) + { + return -1; + } + + if (pid == 0) + { + int ret; + char *buffer; + int rcvbuf_size; + socklen_t optlen = sizeof(rcvbuf_size); + +#if defined (BUFFERED_INPUT) + unset_bash_input (0); +#endif /* BUFFERED_INPUT */ + + default_tty_job_signals (); + + close(cmdline_hist_sock[0]); + + ret = getsockopt(cmdline_hist_sock[1], SOL_SOCKET, SO_RCVBUF, &rcvbuf_size, &optlen); + if (ret < 0) + { + rcvbuf_size = SYSLOG_MAXLEN; + } + + buffer = (char *) malloc(rcvbuf_size); + if (buffer == NULL) + { + return -1; + } + + do { + ret = recv(cmdline_hist_sock[1], buffer, rcvbuf_size, 0); + + if (ret == -1 && errno == EINTR) + { + continue; + } + else if (ret < 0) + { + break; + } + + buffer[ret] = '\0'; + + /*syslog this bash command line*/ + syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", + getpid(), current_user.uid, buffer); + } while (1); + + } + else + { + /* In the parent. */ + close(cmdline_hist_sock[1]); + } + return (pid); +} +#endif /*SYSLOG_HISTORY*/ + static void init_interactive () { -- 1.9.1