]> granicus.if.org Git - sudo/commitdiff
Add bsm audit support from Christian S.J. Peron
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 11 Feb 2009 01:18:02 +0000 (01:18 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 11 Feb 2009 01:18:02 +0000 (01:18 +0000)
Makefile.in
auth/sudo_auth.c
bsm_audit.c [new file with mode: 0644]
bsm_audit.h [new file with mode: 0644]
configure
configure.in
sudo.c

index 98c3e3933683aa9ebac723dccf334c22b010f37c..836e2e9630f2322b36bc175c071abae4b7d55246 100644 (file)
@@ -102,14 +102,15 @@ SHELL = /bin/sh
 
 PROGS = @PROGS@
 
-SRCS = aix.c alias.c alloc.c check.c closefrom.c def_data.c defaults.c env.c \
-       error.c fileops.c find_path.c fnmatch.c getcwd.c getprogname.c \
-       getspwuid.c gettime.c glob.c goodpath.c gram.c gram.y interfaces.c \
-       isblank.c lbuf.c ldap.c list.c logging.c match.c mkstemp.c memrchr.c \
-       parse.c pwutil.c  set_perms.c sigaction.c snprintf.c strcasecmp.c \
-       strerror.c strlcat.c strlcpy.c sudo.c sudo_noexec.c sudo_edit.c \
-       sudo_nss.c term.c testsudoers.c tgetpass.c toke.c toke.l tsgetgrpw.c \
-       utimes.c visudo.c zero_bytes.c redblack.c selinux.c sesh.c $(AUTH_SRCS)
+SRCS = aix.c alias.c alloc.c bsm_audit.c check.c closefrom.c def_data.c \
+       defaults.c env.c error.c fileops.c find_path.c fnmatch.c getcwd.c \
+       getprogname.c getspwuid.c gettime.c glob.c goodpath.c gram.c gram.y \
+       interfaces.c isblank.c lbuf.c ldap.c list.c logging.c match.c mkstemp.c \
+       memrchr.c parse.c pwutil.c  set_perms.c sigaction.c snprintf.c \
+       strcasecmp.c strerror.c strlcat.c strlcpy.c sudo.c sudo_noexec.c \
+       sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c toke.c toke.l \
+       tsgetgrpw.c utimes.c visudo.c zero_bytes.c redblack.c selinux.c sesh.c \
+       $(AUTH_SRCS)
 
 AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \
            auth/kerb4.c auth/kerb5.c auth/pam.c auth/passwd.c auth/rfc1938.c \
@@ -226,6 +227,8 @@ alias.o: $(srcdir)/alias.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdi
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alias.c
 alloc.o: $(srcdir)/alloc.c $(SUDODEP)
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alloc.c
+bsm_audit.o: $(srcdir)/bsm_audit.c $(SUDODEP) bsm_audit.h
+       $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/bsm_audit.c
 check.o: $(srcdir)/check.c $(SUDODEP)
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/check.c
 closefrom.o: $(srcdir)/closefrom.c config.h
index 834924cc1297287aa8e1c93c095852bd0e992502..a7fefb23418d6eb1033edd02f1560ac6751d680b 100644 (file)
@@ -100,6 +100,9 @@ verify_user(pw, prompt)
     char *p;
     sudo_auth *auth;
     sigaction_t sa, osa;
+#ifdef HAVE_BSM_AUDIT
+    extern char **NewArgv;
+#endif
 
     /* Enable suspend during password entry. */
     sigemptyset(&sa.sa_mask);
@@ -108,11 +111,15 @@ verify_user(pw, prompt)
     (void) sigaction(SIGTSTP, &sa, &osa);
 
     /* Make sure we have at least one auth method. */
-    if (auth_switch[0].name == NULL)
+    if (auth_switch[0].name == NULL) {
+#ifdef HAVE_BSM_AUDIT
+       audit_failure(NewArgv, "no authentication methods");
+#endif
        log_error(0, "%s  %s %s",
            "There are no authentication methods compiled into sudo!",
            "If you want to turn off authentication, use the",
            "--disable-authentication configure option.");
+    }
 
     /* Set FLAG_ONEANDONLY if there is only one auth method. */
     if (auth_switch[1].name == NULL)
@@ -127,8 +134,12 @@ verify_user(pw, prompt)
            status = (auth->init)(pw, &prompt, auth);
            if (status == AUTH_FAILURE)
                CLR(auth->flags, FLAG_CONFIGURED);
-           else if (status == AUTH_FATAL)      /* XXX log */
+           else if (status == AUTH_FATAL) {    /* XXX log */
+#ifdef HAVE_BSM_AUDIT
+               audit_failure(NewArgv, "authentication failure");
+#endif
                exit(1);                /* assume error msg already printed */
+           }
 
            if (NEEDS_USER(auth))
                set_perms(PERM_ROOT);
@@ -145,8 +156,12 @@ verify_user(pw, prompt)
                status = (auth->setup)(pw, &prompt, auth);
                if (status == AUTH_FAILURE)
                    CLR(auth->flags, FLAG_CONFIGURED);
-               else if (status == AUTH_FATAL)  /* XXX log */
+               else if (status == AUTH_FATAL) {/* XXX log */
+#ifdef HAVE_BSM_AUDIT
+                   audit_failure(NewArgv, "authentication failure");
+#endif
                    exit(1);            /* assume error msg already printed */
+               }
 
                if (NEEDS_USER(auth))
                    set_perms(PERM_ROOT);
@@ -193,8 +208,12 @@ cleanup:
                set_perms(PERM_USER);
 
            status = (auth->cleanup)(pw, auth);
-           if (status == AUTH_FATAL)   /* XXX log */
+           if (status == AUTH_FATAL) { /* XXX log */
+#ifdef HAVE_BSM_AUDIT
+               audit_failure(NewArgv, "authentication failure");
+#endif
                exit(1);                /* assume error msg already printed */
+           }
 
            if (NEEDS_USER(auth))
                set_perms(PERM_ROOT);
@@ -212,12 +231,18 @@ cleanup:
                    flags = 0;
                else
                    flags = NO_MAIL;
+#ifdef HAVE_BSM_AUDIT
+               audit_failure(NewArgv, "authentication failure");
+#endif
                log_error(flags, "%d incorrect password attempt%s",
                    def_passwd_tries - counter,
                    (def_passwd_tries - counter == 1) ? "" : "s");
            }
            /* FALLTHROUGH */
        case AUTH_FATAL:
+#ifdef HAVE_BSM_AUDIT
+           audit_failure(NewArgv, "authentication failure");
+#endif
            exit(1);
     }
     /* NOTREACHED */
diff --git a/bsm_audit.c b/bsm_audit.c
new file mode 100644 (file)
index 0000000..6075e9d
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2009 Christian S.J. Peron
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <bsm/audit.h>
+#include <bsm/libbsm.h>
+#include <bsm/audit_uevents.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pwd.h>
+#include <errno.h>
+#include <unistd.h>
+
+static int
+audit_sudo_selected(int sf)
+{
+       auditinfo_addr_t ainfo_addr;
+       struct au_mask *mask;
+       auditinfo_t ainfo;
+       int rc, sorf;
+
+       if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) {
+               if (errno == ENOSYS) {
+                       if (getaudit(&ainfo) < 0)
+                               log_error(0, "getaudit: failed");
+                       mask = &ainfo.ai_mask;
+               } else
+                       log_error(0, "getaudit: failed");
+        } else
+               mask = &ainfo_addr.ai_mask;
+       sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE;
+       rc = au_preselect(AUE_sudo, mask, sorf, AU_PRS_REREAD);
+        return (rc);
+}
+
+void
+audit_success(char **exec_args)
+{
+       auditinfo_addr_t ainfo_addr;
+       auditinfo_t ainfo;
+       token_t *tok;
+       au_id_t auid;
+       long au_cond;
+       int aufd;
+       pid_t pid;
+
+       pid = getpid();
+       /*
+        * If we are not auditing, don't cut an audit record; just return.
+        */
+       if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
+               if (errno == ENOSYS)
+                       return;
+               log_error(0, "Could not determine audit condition");
+       }
+       if (au_cond == AUC_NOAUDIT)
+               return;
+       /*
+        * Check to see if the preselection masks are interested in seeing
+        * this event.
+        */
+       if (!audit_sudo_selected(0))
+               return;
+       if (getauid(&auid) < 0)
+               log_error(0, "getauid failed");
+       if ((aufd = au_open()) == -1)
+               log_error(0, "au_open: failed");
+       if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
+               tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
+                   getuid(), pid, pid, &ainfo_addr.ai_termid);
+       } else if (errno == ENOSYS) {
+               /*
+                * NB: We should probably watch out for ERANGE here.
+                */
+               if (getaudit(&ainfo) < 0)
+                       log_error(0, "getaudit: failed");
+               tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
+                   getuid(), pid, pid, &ainfo.ai_termid);
+       } else
+               log_error(0, "getaudit: failed");
+       if (tok == NULL)
+               log_error(0, "au_to_subject: failed");
+       au_write(aufd, tok);
+       tok = au_to_exec_args(exec_args);
+       if (tok == NULL)
+               log_error(0, "au_to_exec_args: failed");
+       au_write(aufd, tok);
+       tok = au_to_return32(0, 0);
+       if (tok == NULL)
+               log_error(0, "au_to_return32: failed");
+       au_write(aufd, tok);
+       if (au_close(aufd, 1, AUE_sudo) == -1)
+               log_error(0, "unable to commit audit record");
+}
+
+void
+audit_failure(char **exec_args, char const *const fmt, ...)
+{
+       auditinfo_addr_t ainfo_addr;
+       auditinfo_t ainfo;
+       char text[256];
+       token_t *tok;
+       long au_cond;
+       au_id_t auid;
+       va_list ap;
+       pid_t pid;
+       int aufd;
+
+       pid = getpid();
+       /*
+        * If we are not auditing, don't cut an audit record; just return.
+        */
+       if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
+               if (errno == ENOSYS)
+                       return;
+               log_error(0, "Could not determine audit condition");
+       }
+       if (au_cond == AUC_NOAUDIT)
+               return;
+       if (!audit_sudo_selected(1))
+               return;
+       if (getauid(&auid) < 0)
+               log_error(0, "getauid: failed");
+       if ((aufd = au_open()) == -1)
+               log_error(0, "au_open: failed");
+       if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) { 
+               tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
+                   getuid(), pid, pid, &ainfo_addr.ai_termid);
+       } else if (errno == ENOSYS) {
+               if (getaudit(&ainfo) < 0) 
+                       log_error(0, "getaudit: failed");
+               tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
+                   getuid(), pid, pid, &ainfo.ai_termid);
+       } else
+               log_error(0, "getaudit: failed");
+       if (tok == NULL)
+               log_error(0, "au_to_subject: failed");
+       au_write(aufd, tok);
+       tok = au_to_exec_args(exec_args);
+       if (tok == NULL)
+               log_error(0, "au_to_exec_args: failed");
+       au_write(aufd, tok);
+       va_start(ap, fmt);
+       (void) vsnprintf(text, sizeof(text), fmt, ap);
+       va_end(ap);
+       tok = au_to_text(text);
+       if (tok == NULL)
+               log_error(0, "au_to_text: failed");
+       au_write(aufd, tok);
+       tok = au_to_return32(EPERM, 1);
+       if (tok == NULL)
+               log_error(0, "au_to_return32: failed");
+       au_write(aufd, tok);
+       if (au_close(aufd, 1, AUE_sudo) == -1)
+               log_error(0, "unable to commit audit record");
+}
diff --git a/bsm_audit.h b/bsm_audit.h
new file mode 100644 (file)
index 0000000..a23234b
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2009 Christian S.J. Peron
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SUDO_BSM_AUDIT_H
+#define        _SUDO_BSM_AUDIT_H
+
+void   audit_success(char **);
+void   audit_failure(char **, char const *const, ...);
+
+#endif /* _SUDO_BSM_AUDIT_H */
index 0bf4e23cf85afae991b60ba2825d13955efdb1ca..d4cab1a0db70b40a5bde7432933fbb29841ca480 100755 (executable)
--- a/configure
+++ b/configure
@@ -799,6 +799,7 @@ LIBS
 build_alias
 host_alias
 target_alias
+HAVE_BSM_AUDIT
 LIBTOOL
 CFLAGS
 PROGS
@@ -1517,6 +1518,7 @@ Optional Packages:
   --with-CC               C compiler to use
   --with-rpath            pass -R flag in addition to -L for lib paths
   --with-blibpath=PATH    pass -blibpath flag to ld for additional lib paths
+  --with-bsm-audit        enable BSM audit support
   --with-incpath          additional places to look for include files
   --with-libpath          additional places to look for libraries
   --with-libraries        additional libraries to link with
@@ -2103,6 +2105,7 @@ echo "$as_me: Configuring Sudo version 1.7" >&6;}
 
 
 
+
 
 
 timeout=5
@@ -2235,6 +2238,26 @@ fi
 
 
 
+# Check whether --with-bsm-audit was given.
+if test "${with_bsm_audit+set}" = set; then
+  withval=$with_bsm_audit; case $with_bsm_audit in
+    yes)       cat >>confdefs.h <<\_ACEOF
+#define HAVE_BSM_AUDIT 1
+_ACEOF
+
+               SUDO_LIBS="${SUDO_LIBS} -lbsm"
+               SUDO_OBJS="${SUDO_OBJS} bsm_audit.o"
+               ;;
+    no)                ;;
+    *)         { { echo "$as_me:$LINENO: error: \"--with-bsm-audit does not take an argument.\"" >&5
+echo "$as_me: error: \"--with-bsm-audit does not take an argument.\"" >&2;}
+   { (exit 1); exit 1; }; }
+               ;;
+esac
+fi
+
+
+
 # Check whether --with-incpath was given.
 if test "${with_incpath+set}" = set; then
   withval=$with_incpath; case $with_incpath in
@@ -6209,7 +6232,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6212 "configure"' > conftest.$ac_ext
+  echo '#line 6235 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -8068,11 +8091,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8071: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8094: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8075: \$? = $ac_status" >&5
+   echo "$as_me:8098: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8358,11 +8381,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8361: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8384: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8365: \$? = $ac_status" >&5
+   echo "$as_me:8388: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8462,11 +8485,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8465: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8488: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8469: \$? = $ac_status" >&5
+   echo "$as_me:8492: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -10822,7 +10845,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10825 "configure"
+#line 10848 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10922,7 +10945,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10925 "configure"
+#line 10948 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -24153,6 +24176,7 @@ LIBS!$LIBS$ac_delim
 build_alias!$build_alias$ac_delim
 host_alias!$host_alias$ac_delim
 target_alias!$target_alias$ac_delim
+HAVE_BSM_AUDIT!$HAVE_BSM_AUDIT$ac_delim
 LIBTOOL!$LIBTOOL$ac_delim
 CFLAGS!$CFLAGS$ac_delim
 PROGS!$PROGS$ac_delim
@@ -24212,7 +24236,6 @@ runas_default!$runas_default$ac_delim
 env_editor!$env_editor$ac_delim
 passwd_tries!$passwd_tries$ac_delim
 tty_tickets!$tty_tickets$ac_delim
-insults!$insults$ac_delim
 _ACEOF
 
   if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -24254,6 +24277,7 @@ _ACEOF
 ac_delim='%!_!# '
 for ac_last_try in false false false false false :; do
   cat >conf$$subs.sed <<_ACEOF
+insults!$insults$ac_delim
 root_sudo!$root_sudo$ac_delim
 path_info!$path_info$ac_delim
 ldap_conf!$ldap_conf$ac_delim
@@ -24297,7 +24321,7 @@ KRB5CONFIG!$KRB5CONFIG$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 41; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 42; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
@@ -24918,6 +24942,8 @@ fi
 
 
 
+
+
 
 
 
index 36c6305f91a2bd13eeb5cb19c6c0e1ab83330536..1e00c5c482b6a81a255dcc3421e6f2d0ac378164 100644 (file)
@@ -13,6 +13,7 @@ AC_MSG_NOTICE([Configuring Sudo version 1.7])
 dnl
 dnl Variables that get substituted in the Makefile and man pages
 dnl
+AC_SUBST(HAVE_BSM_AUDIT)
 AC_SUBST(LIBTOOL)
 AC_SUBST(CFLAGS)
 AC_SUBST(PROGS)
@@ -201,6 +202,20 @@ AC_ARG_WITH(blibpath, [  --with-blibpath[=PATH]    pass -blibpath flag to ld for
                ;;
 esac])
 
+dnl
+dnl Handle BSM auditing support.
+dnl
+AC_ARG_WITH(bsm-audit, [  --with-bsm-audit        enable BSM audit support],
+[case $with_bsm_audit in
+    yes)       AC_DEFINE(HAVE_BSM_AUDIT)
+               SUDO_LIBS="${SUDO_LIBS} -lbsm"
+               SUDO_OBJS="${SUDO_OBJS} bsm_audit.o"
+               ;;
+    no)                ;;
+    *)         AC_MSG_ERROR(["--with-bsm-audit does not take an argument."])
+               ;;
+esac])
+
 AC_ARG_WITH(incpath, [  --with-incpath          additional places to look for include files],
 [case $with_incpath in
     yes)       AC_MSG_ERROR(["must give --with-incpath an argument."])
@@ -2539,6 +2554,7 @@ AH_TEMPLATE(HAL_INSULTS, [Define to 1 if you want 2001-like insults.])
 AH_TEMPLATE(HAVE_AFS, [Define to 1 if you use AFS.])
 AH_TEMPLATE(HAVE_AIXAUTH, [Define to 1 if you use AIX general authentication.])
 AH_TEMPLATE(HAVE_BSD_AUTH_H, [Define to 1 if you use BSD authentication.])
+AH_TEMPLATE(HAVE_BSM_AUDIT, [Define to 1 to enable BSM auditing.])
 AH_TEMPLATE(HAVE_DCE, [Define to 1 if you use OSF DCE.])
 AH_TEMPLATE(HAVE_DD_FD, [Define to 1 if your `DIR' contains dd_fd.])
 AH_TEMPLATE(HAVE_DIRFD, [Define to 1 if you have the `dirfd' function or macro.])
diff --git a/sudo.c b/sudo.c
index 2ff8927fa343534b044f5177dc4cacacf8572f99..423382110e12f3844e1753a37dd3d70d80e0ee49 100644 (file)
--- a/sudo.c
+++ b/sudo.c
 #include "interfaces.h"
 #include "version.h"
 
+#ifdef HAVE_BSM_AUDIT
+# include "bsm_audit.h"
+#endif
+
 #ifndef lint
 __unused static const char rcsid[] = "$Sudo$";
 #endif /* lint */
@@ -382,9 +386,12 @@ main(argc, argv, envp)
 
     /* Bail if a tty is required and we don't have one.  */
     if (def_requiretty) {
-       if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1)
+       if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) {
+#ifdef HAVE_BSM_AUDIT
+           audit_failure(NewArgv, "no tty");
+#endif
            log_error(NO_MAIL, "sorry, you must have a tty to run sudo");
-       else
+       else
            (void) close(fd);
     }
 
@@ -419,10 +426,17 @@ main(argc, argv, envp)
 
     if (ISSET(validated, VALIDATE_OK)) {
        /* Finally tell the user if the command did not exist. */
-       if (cmnd_status == NOT_FOUND_DOT)
+       if (cmnd_status == NOT_FOUND_DOT) {
+#ifdef HAVE_BSM_AUDIT
+           audit_failure(NewArgv, "command in current directory");
+#endif
            errorx(1, "ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd);
-       else if (cmnd_status == NOT_FOUND)
+       } else if (cmnd_status == NOT_FOUND) {
+#ifdef HAVE_BSM_AUDIT
+           audit_failure(NewArgv, "%s: command not found", user_cmnd);
+#endif
            errorx(1, "%s: command not found", user_cmnd);
+       }
 
        /* If user specified env vars make sure sudoers allows it. */
        if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) {
@@ -509,13 +523,20 @@ main(argc, argv, envp)
        closefrom(def_closefrom + 1);
 
 #ifndef PROFILING
-       if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0)
+       if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0) {
+#ifdef HAVE_BSM_AUDIT
+               syslog(LOG_AUTH|LOG_ERR, "fork");
+           audit_success(NewArgv);
+#endif
            exit(0);
-       else {
+       else {
 #ifdef HAVE_SELINUX
            if (is_selinux_enabled() > 0 && user_role != NULL)
                selinux_exec(user_role, user_type, NewArgv,
                    ISSET(sudo_mode, MODE_LOGIN_SHELL));
+#endif
+#ifdef HAVE_BSM_AUDIT
+           audit_success(NewArgv);
 #endif
            execv(safe_cmnd, NewArgv);
        }
@@ -533,6 +554,9 @@ main(argc, argv, envp)
        } warning("unable to execute %s", safe_cmnd);
        exit(127);
     } else if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) {
+#ifdef HAVE_BSM_AUDIT
+       audit_failure(NewArgv, "No user or host");
+#endif
        log_denial(validated, 1);
        exit(1);
     } else {
@@ -554,6 +578,9 @@ main(argc, argv, envp)
            /* Just tell the user they are not allowed to run foo. */
            log_denial(validated, 1);
        }
+#ifdef HAVE_BSM_AUDIT
+       audit_failure(NewArgv, "validation failure");
+#endif
        exit(1);
     }
     exit(0);   /* not reached */
@@ -1315,8 +1342,12 @@ set_runaspw(user)
        if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
            runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
     } else {
-       if ((runas_pw = sudo_getpwnam(user)) == NULL)
+       if ((runas_pw = sudo_getpwnam(user)) == NULL) {
+#ifdef HAVE_BSM_AUDIT
+           audit_failure(NewArgv, "unknown user: %s", user);
+#endif
            log_error(NO_MAIL|MSG_ONLY, "unknown user: %s", user);
+       }
     }
 }