summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in4
-rw-r--r--config-bot.h5
-rw-r--r--config.h.in5
-rw-r--r--configure.in12
-rw-r--r--debian/control3
-rwxr-xr-xdebian/rules1
-rw-r--r--doc/bash.117
-rw-r--r--eval.c55
-rw-r--r--externs.h4
-rw-r--r--flags.c6
-rw-r--r--flags.h4
-rw-r--r--parse.y2
-rw-r--r--shell.c30
13 files changed, 143 insertions, 5 deletions
diff --git a/Makefile.in b/Makefile.in
index 28af658..79e0e9f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -359,6 +359,8 @@ MALLOC_LIBRARY = @MALLOC_LIBRARY@
MALLOC_LDFLAGS = @MALLOC_LDFLAGS@
MALLOC_DEP = @MALLOC_DEP@
+AUDIT_LIB = @AUDIT_LIB@
+
ALLOC_HEADERS = $(ALLOC_LIBSRC)/getpagesize.h $(ALLOC_LIBSRC)/shmalloc.h \
$(ALLOC_LIBSRC)/imalloc.h $(ALLOC_LIBSRC)/mstats.h \
$(ALLOC_LIBSRC)/table.h $(ALLOC_LIBSRC)/watch.h
@@ -379,7 +381,7 @@ BASHINCFILES = $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \
$(BASHINCDIR)/ocache.h
LIBRARIES = $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) $(GLOB_LIB) \
- $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LOCAL_LIBS)
+ $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LOCAL_LIBS) $(AUDIT_LIB)
LIBDEP = $(SHLIB_DEP) $(INTL_DEP) $(READLINE_DEP) $(HISTORY_DEP) $(TERMCAP_DEP) $(GLOB_DEP) \
$(TILDE_DEP) $(MALLOC_DEP)
diff --git a/config-bot.h b/config-bot.h
index 1b8fd5d..a4f95cf 100644
--- a/config-bot.h
+++ b/config-bot.h
@@ -97,6 +97,11 @@
# define RESTRICTED_SHELL_NAME "rbash"
#endif
+/* If the shell is called by this name, it will become audited. */
+#if defined (AUDIT_SHELL)
+# define AUDIT_SHELL_NAME "aubash"
+#endif
+
/***********************************************************/
/* Make sure feature defines have necessary prerequisites. */
/***********************************************************/
diff --git a/config.h.in b/config.h.in
index 7fde761..46d281b 100644
--- a/config.h.in
+++ b/config.h.in
@@ -81,6 +81,11 @@
flag. */
#undef RESTRICTED_SHELL
+/* Define AUDIT_SHELL if you want the generated shell to audit all
+ actions performed by root account. The shell thus generated can become
+ audited by being run with the name "aubash". */
+#undef AUDIT_SHELL
+
/* Define DISABLED_BUILTINS if you want "builtin foo" to always run the
shell builtin "foo", even if it has been disabled with "enable -n foo". */
#undef DISABLED_BUILTINS
diff --git a/configure.in b/configure.in
index 182d773..c40c1bd 100644
--- a/configure.in
+++ b/configure.in
@@ -162,6 +162,7 @@ opt_history=yes
opt_bang_history=yes
opt_dirstack=yes
opt_restricted=yes
+opt_audit=yes
opt_process_subst=yes
opt_prompt_decoding=yes
opt_select=yes
@@ -195,8 +196,8 @@ dnl a minimal configuration turns everything off, but features can be
dnl added individually
if test $opt_minimal_config = yes; then
opt_job_control=no opt_alias=no opt_readline=no
- opt_history=no opt_bang_history=no opt_dirstack=no
- opt_restricted=no opt_process_subst=no opt_prompt_decoding=no
+ opt_history=no opt_bang_history=no opt_dirstack=no opt_restricted=no
+ opt_audit=no opt_process_subst=no opt_prompt_decoding=no
opt_select=no opt_help=no opt_array_variables=no opt_dparen_arith=no
opt_brace_expansion=no opt_disabled_builtins=no opt_command_timing=no
opt_extended_glob=no opt_cond_command=no opt_arith_for_command=no
@@ -227,6 +228,7 @@ AC_ARG_ENABLE(progcomp, AC_HELP_STRING([--enable-progcomp], [enable programmable
AC_ARG_ENABLE(prompt-string-decoding, AC_HELP_STRING([--enable-prompt-string-decoding], [turn on escape character decoding in prompts]), opt_prompt_decoding=$enableval)
AC_ARG_ENABLE(readline, AC_HELP_STRING([--enable-readline], [turn on command line editing]), opt_readline=$enableval)
AC_ARG_ENABLE(restricted, AC_HELP_STRING([--enable-restricted], [enable a restricted shell]), opt_restricted=$enableval)
+AC_ARG_ENABLE(audit, AC_HELP_STRING([--enable-audit], [enable an audited shell]), opt_audit=$enableval)
AC_ARG_ENABLE(select, AC_HELP_STRING([--enable-select], [include select command]), opt_select=$enableval)
AC_ARG_ENABLE(separate-helpfiles, AC_HELP_STRING([--enable-separate-helpfiles], [use external files for help builtin documentation]), opt_separate_help=$enableval)
AC_ARG_ENABLE(single-help-strings, AC_HELP_STRING([--enable-single-help-strings], [store help documentation as a single string to ease translation]), opt_single_longdoc_strings=$enableval)
@@ -254,6 +256,10 @@ fi
if test $opt_restricted = yes; then
AC_DEFINE(RESTRICTED_SHELL)
fi
+if test $opt_audit = yes; then
+AC_DEFINE(AUDIT_SHELL)
+AUDIT_LIB='-laudit'
+fi
if test $opt_process_subst = yes; then
AC_DEFINE(PROCESS_SUBSTITUTION)
fi
@@ -355,6 +361,8 @@ AC_SUBST(HELPDIRDEFINE)
AC_SUBST(HELPINSTALL)
AC_SUBST(HELPSTRINGS)
+AC_SUBST(AUDIT_LIB)
+
echo ""
echo "Beginning configuration for bash-$BASHVERS-$RELSTATUS for ${host_cpu}-${host_vendor}-${host_os}"
echo ""
diff --git a/debian/control b/debian/control
index cfc0652..8e5985d 100644
--- a/debian/control
+++ b/debian/control
@@ -3,7 +3,8 @@ Section: base
Priority: optional
Maintainer: Vyatta Package Maintainers <maintainers@vyatta.com>
Standards-Version: 3.6.2
-Build-Depends: autoconf, patch, bison, libncurses5-dev, texinfo, autotools-dev, debhelper (>= 4.1), texi2html, locales
+Build-Depends: autoconf, patch, bison, libncurses5-dev, texinfo, autotools-dev,
+ debhelper (>= 4.1), texi2html, locales, libaudit-dev
Build-Depends-Indep: tetex-bin
Package: vyatta-bash
diff --git a/debian/rules b/debian/rules
index 0935fcc..20225f2 100755
--- a/debian/rules
+++ b/debian/rules
@@ -43,6 +43,7 @@ d = debian/$(p)
conf_args = \
--with-curses \
--disable-net-redirections \
+ --enable-audit \
--enable-largefile \
--prefix=/usr \
--infodir=/usr/share/info \
diff --git a/doc/bash.1 b/doc/bash.1
index 80d51fa..f6f6649 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -154,6 +154,12 @@ single-character options to be recognized.
.PP
.PD 0
.TP
+.B \-\-audit
+The shell logs all commands run by the root user (see
+.SM
+.B "AUDIT SHELL"
+below).
+.TP
.B \-\-debugger
Arrange for the debugger profile to be executed before the shell
starts.
@@ -8797,6 +8803,17 @@ turns off any restrictions in the shell spawned to execute the
script.
.\" end of rbash.1
.if \n(zY=1 .ig zY
+.SH "AUDIT SHELL"
+.zY
+.PP
+If
+.B bash
+is started with the name
+.BR aubash ,
+or the
+.B \-\-audit
+option is supplied at invocation, the shell logs all commands issued by the root user to the audit system.
+.if \n(zY=1 .ig zY
.SH "SEE ALSO"
.PD 0
.TP
diff --git a/eval.c b/eval.c
index 4f4a13f..e493643 100644
--- a/eval.c
+++ b/eval.c
@@ -45,6 +45,11 @@
# include "bashhist.h"
#endif
+#if defined (AUDIT_SHELL)
+# include <libaudit.h>
+# include <errno.h>
+#endif
+
extern int EOF_reached;
extern int indirection_level;
extern int posixly_correct;
@@ -62,6 +67,38 @@ extern char *current_readline_line;
extern int current_readline_line_index;
#endif
+#if defined (AUDIT_SHELL)
+static int audit_fd = -1;
+
+static int
+audit_start ()
+{
+ audit_fd = audit_open ();
+ if (audit_fd < 0)
+ return -1;
+ else
+ return 0;
+}
+
+static int
+audit (cmd, result)
+ char *cmd;
+ int result;
+{
+ int rc;
+
+ if (audit_fd < 0)
+ return 0;
+
+ rc = audit_log_user_command (audit_fd, AUDIT_USER_CMD, cmd,
+ NULL, !result);
+ close (audit_fd);
+ audit_fd = -1;
+ return rc;
+}
+#endif
+
+
/* Read and execute commands until EOF is reached. This assumes that
the input source has already been initialized. */
int
@@ -149,7 +186,25 @@ reader_loop ()
executing = 1;
stdin_redir = 0;
+#if defined (AUDIT_SHELL)
+ if (audited && interactive_shell && getuid () == 0)
+ {
+ if (audit_start () < 0)
+ {
+ if (errno != EINVAL && errno != EPROTONOSUPPORT &&
+ errno != EAFNOSUPPORT)
+ return EXECUTION_FAILURE;
+ }
+ }
+#endif
+
execute_command (current_command);
+#if defined (AUDIT_SHELL)
+ {
+ extern char *shell_input_line;
+ audit (shell_input_line, last_command_exit_value);
+ }
+#endif
exec_done:
QUIT;
diff --git a/externs.h b/externs.h
index 094d924..e2dd09f 100644
--- a/externs.h
+++ b/externs.h
@@ -77,6 +77,10 @@ extern int shell_is_restricted __P((char *));
extern int maybe_make_restricted __P((char *));
#endif
+#if defined (AUDIT_SHELL)
+extern int maybe_make_audited __P((char *));
+#endif
+
extern void unset_bash_input __P((int));
extern void get_current_user_info __P((void));
diff --git a/flags.c b/flags.c
index 0c0868b..e50d6dc 100644
--- a/flags.c
+++ b/flags.c
@@ -142,6 +142,12 @@ int restricted = 0; /* currently restricted */
int restricted_shell = 0; /* shell was started in restricted mode. */
#endif /* RESTRICTED_SHELL */
+#if defined (AUDIT_SHELL)
+/* Non-zero means that this shell is audited. An audited shell records
+ each command that the root user executes. */
+int audited = 0; /* shell was started in audit mode. */
+#endif /* AUDIT_SHELL */
+
/* Non-zero means that this shell is running in `privileged' mode. This
is required if the shell is to run setuid. If the `-p' option is
not supplied at startup, and the real and effective uids or gids
diff --git a/flags.h b/flags.h
index f16e604..1ee63c8 100644
--- a/flags.h
+++ b/flags.h
@@ -66,6 +66,10 @@ extern int restricted;
extern int restricted_shell;
#endif /* RESTRICTED_SHELL */
+#if defined (AUDIT_SHELL)
+extern int audited;
+#endif /* AUDIT_SHELL */
+
extern int *find_flag __P((int));
extern int change_flag __P((int, int));
extern char *which_set_flags __P((void));
diff --git a/parse.y b/parse.y
index 4fe354f..a179c93 100644
--- a/parse.y
+++ b/parse.y
@@ -263,7 +263,7 @@ int need_here_doc;
/* Where shell input comes from. History expansion is performed on each
line when the shell is interactive. */
-static char *shell_input_line = (char *)NULL;
+char *shell_input_line = (char *)NULL;
static int shell_input_line_index;
static int shell_input_line_size; /* Amount allocated for shell_input_line. */
static int shell_input_line_len; /* strlen (shell_input_line) */
diff --git a/shell.c b/shell.c
index b8dcf32..b417d24 100644
--- a/shell.c
+++ b/shell.c
@@ -236,6 +236,9 @@ struct {
#if defined (RESTRICTED_SHELL)
{ "restricted", Int, &restricted, (char **)0x0 },
#endif
+#if defined (AUDIT_SHELL)
+ { "audit", Int, &audited, (char **)0x0 },
+#endif
{ "verbose", Int, &echo_input_at_read, (char **)0x0 },
{ "version", Int, &do_version, (char **)0x0 },
{ "wordexp", Int, &wordexp_only, (char **)0x0 },
@@ -633,6 +636,10 @@ main (argc, argv, env)
maybe_make_restricted (shell_name);
#endif /* RESTRICTED_SHELL */
+#if defined (AUDIT_SHELL)
+ maybe_make_audited (shell_name);
+#endif
+
if (wordexp_only)
{
startup_state = 3;
@@ -1132,6 +1139,29 @@ maybe_make_restricted (name)
}
#endif /* RESTRICTED_SHELL */
+#if defined (AUDIT_SHELL)
+/* Perhaps make this shell an `audited' one, based on NAME. If the
+ basename of NAME is "aubash", then this shell is audited. The
+ name of the audited shell is a configurable option, see config.h.
+ In an audited shell, all actions performed by root will be logged
+ to the audit system.
+ Do this also if `audited' is already set to 1 maybe the shell was
+ started with --audit. */
+int
+maybe_make_audited (name)
+ char *name;
+{
+ char *temp;
+
+ temp = base_pathname (name);
+ if (*temp == '-')
+ temp++;
+ if (audited || (STREQ (temp, AUDIT_SHELL_NAME)))
+ audited = 1;
+ return (audited);
+}
+#endif /* AUDIT_SHELL */
+
/* Fetch the current set of uids and gids and return 1 if we're running
setuid or setgid. */
static int