Index: contrib/openbsm/bin/praudit/praudit.c =================================================================== --- contrib/openbsm/bin/praudit/praudit.c +++ contrib/openbsm/bin/praudit/praudit.c @@ -36,12 +36,29 @@ * praudit [-lnpx] [-r | -s] [-d del] [file ...] */ +#include + +#ifdef HAVE_CAPSICUM +#include +#endif + #include +#include +#include #include #include #include +#ifdef HAVE_CAPSICUM +/* For catopen() */ +#include +/* For TIOCGETA */ +#include +/* For tzset() */ +#include +#endif + extern char *optarg; extern int optind, optopt, opterr,optreset; @@ -106,8 +123,14 @@ int main(int argc, char **argv) { - int ch; - int i; +#ifdef HAVE_CAPSICUM + cap_rights_t rights; + unsigned long cmd; + uint32_t fcntls; + size_t n; +#endif + size_t nfds; + int *fds, fd, ch, i; FILE *fp; while ((ch = getopt(argc, argv, "d:lnprsx")) != -1) { @@ -153,18 +176,96 @@ if (oflags & AU_OFLAG_XML) au_print_xml_header(stdout); - /* For each of the files passed as arguments dump the contents. */ +#ifdef HAVE_CAPSICUM + /* Cache timezone information before entering Capsicum sandbox. */ + tzset(); + + /* Cache /etc/security/audit_event. */ + (void)getauevent(); + + /* + * Cache NLS data, for strerror, for err(3), before entering capability + * mode. + */ + (void)catopen("libc", NL_CAT_LOCALE); + + cap_rights_init(&rights, CAP_FSTAT, CAP_IOCTL, CAP_WRITE); + if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) + err(1, "unable to limit rights for stdout"); + if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) + err(1, "unable to limit rights for stderr"); + + /* For isatty(). */ + cmd = TIOCGETA; + if (cap_ioctls_limit(STDOUT_FILENO, &cmd, 1) < 0 && errno != ENOSYS) + err(1, "unable to limit ioctls for stdout"); + if (cap_ioctls_limit(STDERR_FILENO, &cmd, 1) < 0 && errno != ENOSYS) + err(1, "unable to limit ioctls for stderr"); +#endif /* HAVE_CAPSICUM */ + + /* Pre-open input files before entering Capsicum sandbox */ if (optind == argc) { - print_tokens(stdin); - return (1); + nfds = 1; + fds = malloc(sizeof(*fds)); + if (fds == NULL) + err(1, "unable to allocate fd array"); + fds[0] = STDIN_FILENO; + } else { + nfds = argc - optind; + fds = malloc(sizeof(*fds) * nfds); + if (fds == NULL) + err(1, "unable to allocate fd array"); + for (i = optind; i < argc; i++) { + fd = open(argv[i], O_RDONLY); + if (fd < 0) + perror(argv[i]); + /* + * Files that failed to open (fd == -1) are preserved + * in the fds array so that a 1:1 relationship to + * argv[] names is preserved. This is used for perror + * below in the case of parsing errors. + */ + fds[i - optind] = fd; + } } + +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_READ); + fcntls = CAP_FCNTL_GETFL; + + for (n = 0; n < nfds; n++) { + if (fds[n] < 0) + continue; + + if (cap_rights_limit(fds[n], &rights) < 0 && errno != ENOSYS) + err(1, "unable to limit rights for %s", + (optind == argc) ? "stdin" : argv[n + optind]); + + /* Required for fdopen(3). */ + if (cap_fcntls_limit(fds[n], fcntls) < 0 && errno != ENOSYS) + err(1, "unable to limit fcntls for %s", + (optind == argc) ? "stdin" : argv[n + optind]); + } + + /* Enter Capsicum sandbox. */ + if (cap_enter() < 0 && errno != ENOSYS) + err(1, "unable to enter capability mode"); +#endif /* HAVE_CAPSICUM */ + + /* For each of the files passed as arguments dump the contents. */ for (i = optind; i < argc; i++) { - fp = fopen(argv[i], "r"); - if ((fp == NULL) || (print_tokens(fp) == -1)) - perror(argv[i]); - if (fp != NULL) - fclose(fp); + if (fds[i - optind] < 0) + continue; + + fp = fdopen(fds[i - optind], "r"); + if (fp == NULL) + perror((optind == argc) ? "stdin" : argv[i]); + + if (print_tokens(fp) == -1) + perror((optind == argc) ? "stdin" : argv[i]); + fclose(fp); } + free(fds); if (oflags & AU_OFLAG_XML) au_print_xml_footer(stdout); Index: contrib/openbsm/config/config.h =================================================================== --- contrib/openbsm/config/config.h +++ contrib/openbsm/config/config.h @@ -16,6 +16,9 @@ /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 +/* Define if Capsicum should be used */ +#define HAVE_CAPSICUM /**/ + /* Define to 1 if you have the `cap_enter' function. */ #define HAVE_CAP_ENTER 1 @@ -181,6 +184,9 @@ /* Define to 1 if `st_rdev' is a member of `struct stat'. */ #define HAVE_STRUCT_STAT_ST_RDEV 1 +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_CAPSICUM_H 1 + /* Define to 1 if you have the header file. */ #define HAVE_SYS_ENDIAN_H 1 Index: contrib/openbsm/config/config.h.in =================================================================== --- contrib/openbsm/config/config.h.in +++ contrib/openbsm/config/config.h.in @@ -15,6 +15,9 @@ /* Define to 1 if you have the `bzero' function. */ #undef HAVE_BZERO +/* Define if Capsicum should be used */ +#undef HAVE_CAPSICUM + /* Define to 1 if you have the `cap_enter' function. */ #undef HAVE_CAP_ENTER @@ -180,6 +183,9 @@ /* Define to 1 if `st_rdev' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_RDEV +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_CAPSICUM_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_ENDIAN_H Index: contrib/openbsm/configure =================================================================== --- contrib/openbsm/configure +++ contrib/openbsm/configure @@ -13595,6 +13595,39 @@ rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext +# +# Check for the presence of FreeBSD Capsicum. +# +for ac_header in sys/capsicum.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sys/capsicum.h" "ac_cv_header_sys_capsicum_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_capsicum_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_CAPSICUM_H 1 +_ACEOF + + have_sys_capsicum_h=yes + +else + + have_sys_capsicum_h=no + +fi + +done + + +if test $have_sys_capsicum_h = yes; then + +$as_echo "#define HAVE_CAPSICUM /**/" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Capsicum" >&5 +$as_echo "using Capsicum" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not using Capsicum" >&5 +$as_echo "Not using Capsicum" >&6; } +fi + # Check to see if Mach IPC is used for trigger messages. If so, use Mach IPC # instead of the default for sending trigger messages to the audit components. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/mach/audit_triggers.defs" >&5 Index: contrib/openbsm/configure.ac =================================================================== --- contrib/openbsm/configure.ac +++ contrib/openbsm/configure.ac @@ -230,6 +230,22 @@ AC_MSG_RESULT([using compat/endian_enc.h]) ]) +# +# Check for the presence of FreeBSD Capsicum. +# +AC_CHECK_HEADERS([sys/capsicum.h], [ + have_sys_capsicum_h=yes +], [ + have_sys_capsicum_h=no +]) + +if test $have_sys_capsicum_h = yes; then + AC_DEFINE(HAVE_CAPSICUM,, Define if Capsicum should be used) + AC_MSG_RESULT([Using Capsicum]) +else + AC_MSG_RESULT([Not using Capsicum]) +fi + # Check to see if Mach IPC is used for trigger messages. If so, use Mach IPC # instead of the default for sending trigger messages to the audit components. AC_CHECK_FILE([/usr/include/mach/audit_triggers.defs], [ Index: usr.sbin/praudit/Makefile =================================================================== --- usr.sbin/praudit/Makefile +++ usr.sbin/praudit/Makefile @@ -5,6 +5,8 @@ OPENBSMDIR=${.CURDIR}/../../contrib/openbsm .PATH: ${OPENBSMDIR}/bin/praudit +CFLAGS+= -I${OPENBSMDIR} + PROG= praudit MAN= praudit.1