Add bsm audit support from Christian S.J. Peron

This commit is contained in:
Todd C. Miller
2009-02-11 01:18:02 +00:00
parent bd05b56a8d
commit f492e53056
7 changed files with 328 additions and 30 deletions

View File

@@ -102,14 +102,15 @@ SHELL = /bin/sh
PROGS = @PROGS@ PROGS = @PROGS@
SRCS = aix.c alias.c alloc.c check.c closefrom.c def_data.c defaults.c env.c \ SRCS = aix.c alias.c alloc.c bsm_audit.c check.c closefrom.c def_data.c \
error.c fileops.c find_path.c fnmatch.c getcwd.c getprogname.c \ defaults.c env.c error.c fileops.c find_path.c fnmatch.c getcwd.c \
getspwuid.c gettime.c glob.c goodpath.c gram.c gram.y interfaces.c \ getprogname.c getspwuid.c gettime.c glob.c goodpath.c gram.c gram.y \
isblank.c lbuf.c ldap.c list.c logging.c match.c mkstemp.c memrchr.c \ interfaces.c isblank.c lbuf.c ldap.c list.c logging.c match.c mkstemp.c \
parse.c pwutil.c set_perms.c sigaction.c snprintf.c strcasecmp.c \ memrchr.c parse.c pwutil.c set_perms.c sigaction.c snprintf.c \
strerror.c strlcat.c strlcpy.c sudo.c sudo_noexec.c sudo_edit.c \ strcasecmp.c strerror.c strlcat.c strlcpy.c sudo.c sudo_noexec.c \
sudo_nss.c term.c testsudoers.c tgetpass.c toke.c toke.l tsgetgrpw.c \ sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c toke.c toke.l \
utimes.c visudo.c zero_bytes.c redblack.c selinux.c sesh.c $(AUTH_SRCS) 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_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 \ 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 $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alias.c
alloc.o: $(srcdir)/alloc.c $(SUDODEP) alloc.o: $(srcdir)/alloc.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alloc.c $(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) check.o: $(srcdir)/check.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/check.c $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/check.c
closefrom.o: $(srcdir)/closefrom.c config.h closefrom.o: $(srcdir)/closefrom.c config.h

View File

@@ -100,6 +100,9 @@ verify_user(pw, prompt)
char *p; char *p;
sudo_auth *auth; sudo_auth *auth;
sigaction_t sa, osa; sigaction_t sa, osa;
#ifdef HAVE_BSM_AUDIT
extern char **NewArgv;
#endif
/* Enable suspend during password entry. */ /* Enable suspend during password entry. */
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
@@ -108,11 +111,15 @@ verify_user(pw, prompt)
(void) sigaction(SIGTSTP, &sa, &osa); (void) sigaction(SIGTSTP, &sa, &osa);
/* Make sure we have at least one auth method. */ /* 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", log_error(0, "%s %s %s",
"There are no authentication methods compiled into sudo!", "There are no authentication methods compiled into sudo!",
"If you want to turn off authentication, use the", "If you want to turn off authentication, use the",
"--disable-authentication configure option."); "--disable-authentication configure option.");
}
/* Set FLAG_ONEANDONLY if there is only one auth method. */ /* Set FLAG_ONEANDONLY if there is only one auth method. */
if (auth_switch[1].name == NULL) if (auth_switch[1].name == NULL)
@@ -127,8 +134,12 @@ verify_user(pw, prompt)
status = (auth->init)(pw, &prompt, auth); status = (auth->init)(pw, &prompt, auth);
if (status == AUTH_FAILURE) if (status == AUTH_FAILURE)
CLR(auth->flags, FLAG_CONFIGURED); 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 */ exit(1); /* assume error msg already printed */
}
if (NEEDS_USER(auth)) if (NEEDS_USER(auth))
set_perms(PERM_ROOT); set_perms(PERM_ROOT);
@@ -145,8 +156,12 @@ verify_user(pw, prompt)
status = (auth->setup)(pw, &prompt, auth); status = (auth->setup)(pw, &prompt, auth);
if (status == AUTH_FAILURE) if (status == AUTH_FAILURE)
CLR(auth->flags, FLAG_CONFIGURED); 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 */ exit(1); /* assume error msg already printed */
}
if (NEEDS_USER(auth)) if (NEEDS_USER(auth))
set_perms(PERM_ROOT); set_perms(PERM_ROOT);
@@ -193,8 +208,12 @@ cleanup:
set_perms(PERM_USER); set_perms(PERM_USER);
status = (auth->cleanup)(pw, auth); 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 */ exit(1); /* assume error msg already printed */
}
if (NEEDS_USER(auth)) if (NEEDS_USER(auth))
set_perms(PERM_ROOT); set_perms(PERM_ROOT);
@@ -212,12 +231,18 @@ cleanup:
flags = 0; flags = 0;
else else
flags = NO_MAIL; flags = NO_MAIL;
#ifdef HAVE_BSM_AUDIT
audit_failure(NewArgv, "authentication failure");
#endif
log_error(flags, "%d incorrect password attempt%s", log_error(flags, "%d incorrect password attempt%s",
def_passwd_tries - counter, def_passwd_tries - counter,
(def_passwd_tries - counter == 1) ? "" : "s"); (def_passwd_tries - counter == 1) ? "" : "s");
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case AUTH_FATAL: case AUTH_FATAL:
#ifdef HAVE_BSM_AUDIT
audit_failure(NewArgv, "authentication failure");
#endif
exit(1); exit(1);
} }
/* NOTREACHED */ /* NOTREACHED */

174
bsm_audit.c Normal file
View File

@@ -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");
}

23
bsm_audit.h Normal file
View File

@@ -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 */

48
configure vendored
View File

@@ -799,6 +799,7 @@ LIBS
build_alias build_alias
host_alias host_alias
target_alias target_alias
HAVE_BSM_AUDIT
LIBTOOL LIBTOOL
CFLAGS CFLAGS
PROGS PROGS
@@ -1517,6 +1518,7 @@ Optional Packages:
--with-CC C compiler to use --with-CC C compiler to use
--with-rpath pass -R flag in addition to -L for lib paths --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-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-incpath additional places to look for include files
--with-libpath additional places to look for libraries --with-libpath additional places to look for libraries
--with-libraries additional libraries to link with --with-libraries additional libraries to link with
@@ -2103,6 +2105,7 @@ echo "$as_me: Configuring Sudo version 1.7" >&6;}
timeout=5 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. # Check whether --with-incpath was given.
if test "${with_incpath+set}" = set; then if test "${with_incpath+set}" = set; then
withval=$with_incpath; case $with_incpath in withval=$with_incpath; case $with_incpath in
@@ -6209,7 +6232,7 @@ ia64-*-hpux*)
;; ;;
*-*-irix6*) *-*-irix6*)
# Find out which ABI we are using. # 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 if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5 (eval $ac_compile) 2>&5
ac_status=$? ac_status=$?
@@ -8068,11 +8091,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 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 if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>conftest.err)
ac_status=$? ac_status=$?
cat conftest.err >&5 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 if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output. # 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:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'` -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) (eval "$lt_compile" 2>out/conftest.err)
ac_status=$? ac_status=$?
cat out/conftest.err >&5 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 if (exit $ac_status) && test -s out/conftest2.$ac_objext
then then
# The compiler can only warn and ignore the option if not recognized # 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_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 10825 "configure" #line 10848 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
@@ -10922,7 +10945,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 10925 "configure" #line 10948 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
@@ -24153,6 +24176,7 @@ LIBS!$LIBS$ac_delim
build_alias!$build_alias$ac_delim build_alias!$build_alias$ac_delim
host_alias!$host_alias$ac_delim host_alias!$host_alias$ac_delim
target_alias!$target_alias$ac_delim target_alias!$target_alias$ac_delim
HAVE_BSM_AUDIT!$HAVE_BSM_AUDIT$ac_delim
LIBTOOL!$LIBTOOL$ac_delim LIBTOOL!$LIBTOOL$ac_delim
CFLAGS!$CFLAGS$ac_delim CFLAGS!$CFLAGS$ac_delim
PROGS!$PROGS$ac_delim PROGS!$PROGS$ac_delim
@@ -24212,7 +24236,6 @@ runas_default!$runas_default$ac_delim
env_editor!$env_editor$ac_delim env_editor!$env_editor$ac_delim
passwd_tries!$passwd_tries$ac_delim passwd_tries!$passwd_tries$ac_delim
tty_tickets!$tty_tickets$ac_delim tty_tickets!$tty_tickets$ac_delim
insults!$insults$ac_delim
_ACEOF _ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -24254,6 +24277,7 @@ _ACEOF
ac_delim='%!_!# ' ac_delim='%!_!# '
for ac_last_try in false false false false false :; do for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF cat >conf$$subs.sed <<_ACEOF
insults!$insults$ac_delim
root_sudo!$root_sudo$ac_delim root_sudo!$root_sudo$ac_delim
path_info!$path_info$ac_delim path_info!$path_info$ac_delim
ldap_conf!$ldap_conf$ac_delim ldap_conf!$ldap_conf$ac_delim
@@ -24297,7 +24321,7 @@ KRB5CONFIG!$KRB5CONFIG$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF _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 break
elif $ac_last_try; then elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
@@ -24918,6 +24942,8 @@ fi

View File

@@ -13,6 +13,7 @@ AC_MSG_NOTICE([Configuring Sudo version 1.7])
dnl dnl
dnl Variables that get substituted in the Makefile and man pages dnl Variables that get substituted in the Makefile and man pages
dnl dnl
AC_SUBST(HAVE_BSM_AUDIT)
AC_SUBST(LIBTOOL) AC_SUBST(LIBTOOL)
AC_SUBST(CFLAGS) AC_SUBST(CFLAGS)
AC_SUBST(PROGS) AC_SUBST(PROGS)
@@ -201,6 +202,20 @@ AC_ARG_WITH(blibpath, [ --with-blibpath[=PATH] pass -blibpath flag to ld for
;; ;;
esac]) 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], AC_ARG_WITH(incpath, [ --with-incpath additional places to look for include files],
[case $with_incpath in [case $with_incpath in
yes) AC_MSG_ERROR(["must give --with-incpath an argument."]) 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_AFS, [Define to 1 if you use AFS.])
AH_TEMPLATE(HAVE_AIXAUTH, [Define to 1 if you use AIX general authentication.]) 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_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_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_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.]) AH_TEMPLATE(HAVE_DIRFD, [Define to 1 if you have the `dirfd' function or macro.])

45
sudo.c
View File

@@ -101,6 +101,10 @@
#include "interfaces.h" #include "interfaces.h"
#include "version.h" #include "version.h"
#ifdef HAVE_BSM_AUDIT
# include "bsm_audit.h"
#endif
#ifndef lint #ifndef lint
__unused static const char rcsid[] = "$Sudo$"; __unused static const char rcsid[] = "$Sudo$";
#endif /* lint */ #endif /* lint */
@@ -382,9 +386,12 @@ main(argc, argv, envp)
/* Bail if a tty is required and we don't have one. */ /* Bail if a tty is required and we don't have one. */
if (def_requiretty) { 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"); log_error(NO_MAIL, "sorry, you must have a tty to run sudo");
else } else
(void) close(fd); (void) close(fd);
} }
@@ -419,10 +426,17 @@ main(argc, argv, envp)
if (ISSET(validated, VALIDATE_OK)) { if (ISSET(validated, VALIDATE_OK)) {
/* Finally tell the user if the command did not exist. */ /* 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); 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); errorx(1, "%s: command not found", user_cmnd);
}
/* If user specified env vars make sure sudoers allows it. */ /* If user specified env vars make sure sudoers allows it. */
if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) { if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) {
@@ -509,13 +523,20 @@ main(argc, argv, envp)
closefrom(def_closefrom + 1); closefrom(def_closefrom + 1);
#ifndef PROFILING #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); exit(0);
else { } else {
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
if (is_selinux_enabled() > 0 && user_role != NULL) if (is_selinux_enabled() > 0 && user_role != NULL)
selinux_exec(user_role, user_type, NewArgv, selinux_exec(user_role, user_type, NewArgv,
ISSET(sudo_mode, MODE_LOGIN_SHELL)); ISSET(sudo_mode, MODE_LOGIN_SHELL));
#endif
#ifdef HAVE_BSM_AUDIT
audit_success(NewArgv);
#endif #endif
execv(safe_cmnd, NewArgv); execv(safe_cmnd, NewArgv);
} }
@@ -533,6 +554,9 @@ main(argc, argv, envp)
} warning("unable to execute %s", safe_cmnd); } warning("unable to execute %s", safe_cmnd);
exit(127); exit(127);
} else if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) { } 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); log_denial(validated, 1);
exit(1); exit(1);
} else { } else {
@@ -554,6 +578,9 @@ main(argc, argv, envp)
/* Just tell the user they are not allowed to run foo. */ /* Just tell the user they are not allowed to run foo. */
log_denial(validated, 1); log_denial(validated, 1);
} }
#ifdef HAVE_BSM_AUDIT
audit_failure(NewArgv, "validation failure");
#endif
exit(1); exit(1);
} }
exit(0); /* not reached */ exit(0); /* not reached */
@@ -1315,8 +1342,12 @@ set_runaspw(user)
if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL) if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0); runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
} else { } 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); log_error(NO_MAIL|MSG_ONLY, "unknown user: %s", user);
}
} }
} }