Imported from ../bash-4.0-rc1.tar.gz.
[platform/upstream/bash.git] / CWRU / audit-patch
1 Date: Tue, 06 Feb 2007 16:06:58 -0500
2 From: Steve Grubb <sgrubb@redhat.com>
3 Subject: Re: bash and linux audit
4 To: chet.ramey@case.edu
5 Organization: Red Hat
6
7 OK, I released audit 1.4 Sunday which has the logging function for user
8 commands. It produces audit events like this:
9
10 type=USER_CMD msg=audit(01/30/2007 18:23:45.793:143) : user pid=22862 uid=root
11 auid=root subj=system_u:system_r:unconfined_t:s0-s0:c0.c1023
12 msg='cwd=/root/test dir cmd=ls -l (terminal=tty1 res=success)'
13
14 diff -urp bash-3.2.orig/config-bot.h bash-3.2/config-bot.h
15 --- bash-3.2.orig/config-bot.h  2007-01-03 09:01:05.000000000 -0500
16 +++ bash-3.2/config-bot.h       2007-01-20 11:59:23.000000000 -0500
17 @@ -97,6 +97,11 @@
18  #  define RESTRICTED_SHELL_NAME "rbash"
19  #endif
20  
21 +/* If the shell is called by this name, it will become audited. */
22 +#if defined (AUDIT_SHELL)
23 +#  define AUDIT_SHELL_NAME "aubash"
24 +#endif
25 +
26  /***********************************************************/
27  /* Make sure feature defines have necessary prerequisites. */
28  /***********************************************************/
29 diff -urp bash-3.2.orig/config.h.in bash-3.2/config.h.in
30 --- bash-3.2.orig/config.h.in   2007-01-03 09:01:05.000000000 -0500
31 +++ bash-3.2/config.h.in        2007-01-20 11:59:23.000000000 -0500
32 @@ -81,6 +81,11 @@
33     flag. */
34  #undef RESTRICTED_SHELL
35  
36 +/* Define AUDIT_SHELL if you want the generated shell to audit all
37 +   actions performed by root account.  The shell thus generated can become
38 +   audited by being run with the name "aubash". */
39 +#undef AUDIT_SHELL
40 +
41  /* Define DISABLED_BUILTINS if you want "builtin foo" to always run the
42     shell builtin "foo", even if it has been disabled with "enable -n foo". */
43  #undef DISABLED_BUILTINS
44 diff -urp bash-3.2.orig/configure.in bash-3.2/configure.in
45 --- bash-3.2.orig/configure.in  2007-01-03 09:01:05.000000000 -0500
46 +++ bash-3.2/configure.in       2007-01-20 11:59:23.000000000 -0500
47 @@ -162,6 +162,7 @@ opt_history=yes
48  opt_bang_history=yes
49  opt_dirstack=yes
50  opt_restricted=yes
51 +opt_audit=yes
52  opt_process_subst=yes
53  opt_prompt_decoding=yes
54  opt_select=yes
55 @@ -195,8 +196,8 @@ dnl a minimal configuration turns everyt
56  dnl added individually
57  if test $opt_minimal_config = yes; then
58         opt_job_control=no opt_alias=no opt_readline=no
59 -       opt_history=no opt_bang_history=no opt_dirstack=no
60 -       opt_restricted=no opt_process_subst=no opt_prompt_decoding=no
61 +       opt_history=no opt_bang_history=no opt_dirstack=no opt_restricted=no
62 +       opt_audit=no opt_process_subst=no opt_prompt_decoding=no
63         opt_select=no opt_help=no opt_array_variables=no opt_dparen_arith=no
64         opt_brace_expansion=no opt_disabled_builtins=no opt_command_timing=no
65         opt_extended_glob=no opt_cond_command=no opt_arith_for_command=no
66 @@ -227,6 +228,7 @@ AC_ARG_ENABLE(progcomp, AC_HELP_STRING([
67  AC_ARG_ENABLE(prompt-string-decoding, AC_HELP_STRING([--enable-prompt-string-decoding], [turn on escape character decoding in prompts]), opt_prompt_decoding=$enableval)
68  AC_ARG_ENABLE(readline, AC_HELP_STRING([--enable-readline], [turn on command line editing]), opt_readline=$enableval)
69  AC_ARG_ENABLE(restricted, AC_HELP_STRING([--enable-restricted], [enable a restricted shell]), opt_restricted=$enableval)
70 +AC_ARG_ENABLE(audit, AC_HELP_STRING([--enable-audit], [enable an audited shell]), opt_audit=$enableval)
71  AC_ARG_ENABLE(select, AC_HELP_STRING([--enable-select], [include select command]), opt_select=$enableval)
72  AC_ARG_ENABLE(separate-helpfiles, AC_HELP_STRING([--enable-separate-helpfiles], [use external files for help builtin documentation]), opt_separate_help=$enableval)
73  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)
74 @@ -254,6 +256,10 @@ fi
75  if test $opt_restricted = yes; then
76  AC_DEFINE(RESTRICTED_SHELL)
77  fi
78 +if test $opt_audit = yes; then
79 +AC_DEFINE(AUDIT_SHELL)
80 +AUDIT_LIB='-laudit'
81 +fi
82  if test $opt_process_subst = yes; then
83  AC_DEFINE(PROCESS_SUBSTITUTION)
84  fi
85 @@ -355,6 +361,8 @@ AC_SUBST(HELPDIRDEFINE)
86  AC_SUBST(HELPINSTALL)
87  AC_SUBST(HELPSTRINGS)
88  
89 +AC_SUBST(AUDIT_LIB)
90 +
91  echo ""
92  echo "Beginning configuration for bash-$BASHVERS-$RELSTATUS for ${host_cpu}-${host_vendor}-${host_os}"
93  echo ""
94 diff -urp bash-3.2.orig/doc/bash.1 bash-3.2/doc/bash.1
95 --- bash-3.2.orig/doc/bash.1    2007-01-03 09:01:05.000000000 -0500
96 +++ bash-3.2/doc/bash.1 2007-01-20 11:59:23.000000000 -0500
97 @@ -155,6 +155,12 @@ single-character options to be recognize
98  .PP
99  .PD 0
100  .TP
101 +.B \-\-audit
102 +The shell logs all commands run by the root user (see
103 +.SM
104 +.B "AUDIT SHELL"
105 +below).
106 +.TP
107  .B \-\-debugger
108  Arrange for the debugger profile to be executed before the shell
109  starts.
110 @@ -8770,6 +8776,17 @@ turns off any restrictions in the shell 
111  script.
112  .\" end of rbash.1
113  .if \n(zY=1 .ig zY
114 +.SH "AUDIT SHELL"
115 +.zY
116 +.PP
117 +If
118 +.B bash
119 +is started with the name
120 +.BR aubash ,
121 +or the
122 +.B \-\-audit
123 +option is supplied at invocation, the shell logs all commands issued by the root user to the audit system.
124 +.if \n(zY=1 .ig zY
125  .SH "SEE ALSO"
126  .PD 0
127  .TP
128 diff -urp bash-3.2.orig/eval.c bash-3.2/eval.c
129 --- bash-3.2.orig/eval.c        2007-01-03 09:01:06.000000000 -0500
130 +++ bash-3.2/eval.c     2007-01-20 11:59:23.000000000 -0500
131 @@ -45,6 +45,11 @@
132  #  include "bashhist.h"
133  #endif
134  
135 +#if defined (AUDIT_SHELL)
136 +#  include <libaudit.h>
137 +#  include <errno.h>
138 +#endif
139 +
140  extern int EOF_reached;
141  extern int indirection_level;
142  extern int posixly_correct;
143 @@ -58,6 +63,38 @@ extern int rpm_requires;
144  static void send_pwd_to_eterm __P((void));
145  static sighandler alrm_catcher __P((int));
146  
147 +#if defined (AUDIT_SHELL)
148 +static int audit_fd = -1;
149 +
150 +static int
151 +audit_start ()
152 +{
153 +  audit_fd = audit_open ();
154 +  if (audit_fd < 0)
155 +    return -1;
156 +  else
157 +    return 0;
158 +}
159 +
160 +static int
161 +audit (cmd, result)
162 +        char *cmd;
163 +        int result;
164 +{
165 +  int rc;
166 +
167 +  if (audit_fd < 0)
168 +    return 0;
169 +
170 +  rc = audit_log_user_command (audit_fd, AUDIT_USER_CMD, cmd,
171 +                               NULL, !result);
172 +  close (audit_fd);
173 +  audit_fd = -1;
174 +  return rc;
175 +}
176 +#endif
177 +
178 +
179  /* Read and execute commands until EOF is reached.  This assumes that
180     the input source has already been initialized. */
181  int
182 @@ -145,7 +182,25 @@ reader_loop ()
183  
184               executing = 1;
185               stdin_redir = 0;
186 +#if defined (AUDIT_SHELL)
187 +              if (audited && interactive_shell && getuid () == 0)
188 +                {
189 +                  if (audit_start () < 0)
190 +                    {
191 +                      if (errno != EINVAL && errno != EPROTONOSUPPORT &&
192 +                          errno != EAFNOSUPPORT)
193 +                        return EXECUTION_FAILURE;
194 +                    }
195 +                }
196 +#endif
197 +
198               execute_command (current_command);
199 +#if defined (AUDIT_SHELL)
200 +              {
201 +                extern char *shell_input_line;
202 +                audit (shell_input_line, last_command_exit_value);
203 +              }
204 +#endif
205  
206             exec_done:
207               QUIT;
208 diff -urp bash-3.2.orig/externs.h bash-3.2/externs.h
209 --- bash-3.2.orig/externs.h     2007-01-03 09:01:06.000000000 -0500
210 +++ bash-3.2/externs.h  2007-01-20 12:05:00.000000000 -0500
211 @@ -77,6 +77,10 @@ extern int shell_is_restricted __P((char
212  extern int maybe_make_restricted __P((char *));
213  #endif
214  
215 +#if defined (AUDIT_SHELL)
216 +extern int maybe_make_audited __P((char *));
217 +#endif
218 +
219  extern void unset_bash_input __P((int));
220  extern void get_current_user_info __P((void));
221  
222 diff -urp bash-3.2.orig/flags.c bash-3.2/flags.c
223 --- bash-3.2.orig/flags.c       2007-01-03 09:01:06.000000000 -0500
224 +++ bash-3.2/flags.c    2007-01-20 11:59:23.000000000 -0500
225 @@ -142,6 +142,12 @@ int restricted = 0;                /* currently restri
226  int restricted_shell = 0;      /* shell was started in restricted mode. */
227  #endif /* RESTRICTED_SHELL */
228  
229 +#if defined (AUDIT_SHELL)
230 +/* Non-zero means that this shell is audited. An audited shell records
231 +   each command that the root user executes. */
232 +int audited = 0;               /* shell was started in audit mode. */
233 +#endif /* AUDIT_SHELL */
234 +
235  /* Non-zero means that this shell is running in `privileged' mode.  This
236     is required if the shell is to run setuid.  If the `-p' option is
237     not supplied at startup, and the real and effective uids or gids
238 diff -urp bash-3.2.orig/flags.h bash-3.2/flags.h
239 --- bash-3.2.orig/flags.h       2007-01-03 09:01:06.000000000 -0500
240 +++ bash-3.2/flags.h    2007-01-20 11:59:23.000000000 -0500
241 @@ -66,6 +66,10 @@ extern int restricted;
242  extern int restricted_shell;
243  #endif /* RESTRICTED_SHELL */
244  
245 +#if defined (AUDIT_SHELL)
246 +extern int audited;
247 +#endif /* AUDIT_SHELL */
248 +
249  extern int *find_flag __P((int));
250  extern int change_flag __P((int, int));
251  extern char *which_set_flags __P((void));
252 Only in bash-3.2: .made
253 diff -urp bash-3.2.orig/Makefile.in bash-3.2/Makefile.in
254 --- bash-3.2.orig/Makefile.in   2007-01-03 09:01:06.000000000 -0500
255 +++ bash-3.2/Makefile.in        2007-01-20 11:59:23.000000000 -0500
256 @@ -366,6 +366,8 @@ MALLOC_LIBRARY = @MALLOC_LIBRARY@
257  MALLOC_LDFLAGS = @MALLOC_LDFLAGS@
258  MALLOC_DEP = @MALLOC_DEP@
259  
260 +AUDIT_LIB = @AUDIT_LIB@
261 +
262  ALLOC_HEADERS = $(ALLOC_LIBSRC)/getpagesize.h $(ALLOC_LIBSRC)/shmalloc.h \
263                 $(ALLOC_LIBSRC)/imalloc.h $(ALLOC_LIBSRC)/mstats.h \
264                 $(ALLOC_LIBSRC)/table.h $(ALLOC_LIBSRC)/watch.h
265 @@ -386,7 +388,7 @@ BASHINCFILES =       $(BASHINCDIR)/posixstat.
266                  $(BASHINCDIR)/ocache.h
267  
268  LIBRARIES = $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) $(GLOB_LIB) \
269 -           $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LOCAL_LIBS)
270 +           $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LOCAL_LIBS) $(AUDIT_LIB)
271  
272  LIBDEP = $(SHLIB_DEP) $(INTL_DEP) $(READLINE_DEP) $(HISTORY_DEP) $(TERMCAP_DEP) $(GLOB_DEP) \
273          $(TILDE_DEP) $(MALLOC_DEP)
274 diff -urp bash-3.2.orig/parse.y bash-3.2/parse.y
275 --- bash-3.2.orig/parse.y       2007-01-03 09:01:06.000000000 -0500
276 +++ bash-3.2/parse.y    2007-01-20 11:59:23.000000000 -0500
277 @@ -258,7 +258,7 @@ int need_here_doc;
278  
279  /* Where shell input comes from.  History expansion is performed on each
280     line when the shell is interactive. */
281 -static char *shell_input_line = (char *)NULL;
282 +char *shell_input_line = (char *)NULL;
283  static int shell_input_line_index;
284  static int shell_input_line_size;      /* Amount allocated for shell_input_line. */
285  static int shell_input_line_len;       /* strlen (shell_input_line) */
286 diff -urp bash-3.2.orig/shell.c bash-3.2/shell.c
287 --- bash-3.2.orig/shell.c       2007-01-03 09:01:06.000000000 -0500
288 +++ bash-3.2/shell.c    2007-01-20 12:04:23.000000000 -0500
289 @@ -240,6 +240,9 @@ struct {
290  #if defined (RESTRICTED_SHELL)
291    { "restricted", Int, &restricted, (char **)0x0 },
292  #endif
293 +#if defined (AUDIT_SHELL)
294 +  { "audit", Int, &audited, (char **)0x0 },
295 +#endif
296    { "verbose", Int, &echo_input_at_read, (char **)0x0 },
297    { "version", Int, &do_version, (char **)0x0 },
298    { "wordexp", Int, &wordexp_only, (char **)0x0 },
299 @@ -644,6 +647,10 @@ main (argc, argv, env)
300      maybe_make_restricted (shell_name);
301  #endif /* RESTRICTED_SHELL */
302  
303 +#if defined (AUDIT_SHELL)
304 +    maybe_make_audited (shell_name);
305 +#endif
306 +
307    if (wordexp_only)
308      {
309        startup_state = 3;
310 @@ -1143,6 +1150,29 @@ maybe_make_restricted (name)
311  }
312  #endif /* RESTRICTED_SHELL */
313  
314 +#if defined (AUDIT_SHELL)
315 +/* Perhaps make this shell an `audited' one, based on NAME.  If the
316 +   basename of NAME is "aubash", then this shell is audited.  The
317 +   name of the audited shell is a configurable option, see config.h.
318 +   In an audited shell, all actions performed by root will be logged
319 +   to the audit system.
320 +   Do this also if `audited' is already set to 1 maybe the shell was
321 +   started with --audit. */
322 +int
323 +maybe_make_audited (name)
324 +     char *name;
325 +{
326 +  char *temp;
327 +
328 +  temp = base_pathname (name);
329 +  if (*temp == '-')
330 +    temp++;
331 +  if (audited || (STREQ (temp, AUDIT_SHELL_NAME)))
332 +    audited = 1;
333 +  return (audited);
334 +}
335 +#endif /* AUDIT_SHELL */
336 +
337  /* Fetch the current set of uids and gids and return 1 if we're running
338     setuid or setgid. */
339  static int