From 733af6d04db20f642c7cbc543ddc5157d1f1993c Mon Sep 17 00:00:00 2001 From: Apple Date: Tue, 13 Apr 2004 00:06:30 +0000 Subject: [PATCH] system_cmds-279.6.tar.gz --- Makefile | 12 +- PB.project | 11 +- audit.tproj/Makefile | 50 ++ audit.tproj/Makefile.postamble | 86 ++++ audit.tproj/Makefile.preamble | 19 + audit.tproj/PB.project | 32 ++ audit.tproj/audit.1 | 43 ++ audit.tproj/audit.c | 91 ++++ audit.tproj/auditd_control.defs | 25 + auditd.tproj/Makefile | 52 ++ auditd.tproj/Makefile.postamble | 121 +++++ auditd.tproj/Makefile.preamble | 18 + auditd.tproj/PB.project | 38 ++ auditd.tproj/audit_triggers.defs | 1 + auditd.tproj/audit_warn.c | 207 ++++++++ auditd.tproj/auditd.8 | 48 ++ auditd.tproj/auditd.c | 791 +++++++++++++++++++++++++++++++ auditd.tproj/auditd.h | 51 ++ auditd.tproj/auditd_control.defs | 39 ++ auditd.tproj/rc.audit | 25 + login.tproj/Makefile | 4 +- login.tproj/PB.project | 32 +- login.tproj/login.c | 206 +++++++- mach_init.tproj/Makefile | 2 +- mach_init.tproj/PB.project | 2 +- mach_init.tproj/bootstrap.c | 55 ++- mach_init.tproj/bootstrap.defs | 4 +- mach_init.tproj/lists.c | 9 +- mach_init.tproj/lists.h | 10 +- mach_init.tproj/rpc_services.c | 32 +- shutdown.tproj/Makefile | 4 +- shutdown.tproj/PB.project | 50 +- shutdown.tproj/shutdown.c | 63 ++- 33 files changed, 2144 insertions(+), 89 deletions(-) create mode 100644 audit.tproj/Makefile create mode 100644 audit.tproj/Makefile.postamble create mode 100644 audit.tproj/Makefile.preamble create mode 100644 audit.tproj/PB.project create mode 100644 audit.tproj/audit.1 create mode 100644 audit.tproj/audit.c create mode 100644 audit.tproj/auditd_control.defs create mode 100644 auditd.tproj/Makefile create mode 100644 auditd.tproj/Makefile.postamble create mode 100644 auditd.tproj/Makefile.preamble create mode 100644 auditd.tproj/PB.project create mode 100644 auditd.tproj/audit_triggers.defs create mode 100644 auditd.tproj/audit_warn.c create mode 100644 auditd.tproj/auditd.8 create mode 100644 auditd.tproj/auditd.c create mode 100644 auditd.tproj/auditd.h create mode 100644 auditd.tproj/auditd_control.defs create mode 100644 auditd.tproj/rc.audit diff --git a/Makefile b/Makefile index 9d65a8d..4957594 100644 --- a/Makefile +++ b/Makefile @@ -12,15 +12,15 @@ NAME = system_cmds PROJECTVERSION = 2.8 PROJECT_TYPE = Aggregate -TOOLS = dynamic_pager.tproj ac.tproj accton.tproj arch.tproj at.tproj\ - atrun.tproj chkpasswd.tproj chpass.tproj dmesg.tproj\ - getty.tproj hostinfo.tproj init.tproj iostat.tproj kgmon.tproj\ - ktrace.tproj login.tproj mach_init.tproj makekey.tproj\ - mkfile.tproj nvram.tproj passwd.tproj pwd_mkdb.tproj\ +TOOLS = ac.tproj accton.tproj arch.tproj at.tproj atrun.tproj\ + auditd.tproj audit.tproj chkpasswd.tproj chpass.tproj dmesg.tproj\ + dynamic_pager.tproj getty.tproj hostinfo.tproj init.tproj\ + iostat.tproj kgmon.tproj ktrace.tproj login.tproj mach_init.tproj\ + makekey.tproj mkfile.tproj nvram.tproj passwd.tproj pwd_mkdb.tproj\ reboot.tproj shutdown.tproj sync.tproj sysctl.tproj\ update.tproj vipw.tproj zic.tproj zdump.tproj vm_stat.tproj\ zprint.tproj latency.tproj sc_usage.tproj fs_usage.tproj\ - kdump.tproj sadc.tproj sar.tproj + kdump.tproj sadc.tproj sar.tproj LIBRARIES = dp_notify_lib diff --git a/PB.project b/PB.project index 5d1d356..77f4a66 100644 --- a/PB.project +++ b/PB.project @@ -13,16 +13,18 @@ "PROJECT_HEADERS" = (); "PUBLIC_HEADERS" = (); SUBPROJECTS = ( - "dynamic_pager.tproj", - "dp_notify_lib", "ac.tproj", "accton.tproj", "arch.tproj", "at.tproj", - "atrun.tproj", + "atrun.tproj", + "audit.tproj", + "auditd.tproj", "chkpasswd.tproj", "chpass.tproj", "dmesg.tproj", + "dp_notify_lib", + "dynamic_pager.tproj", "getty.tproj", "hostinfo.tproj", "init.tproj", @@ -53,8 +55,7 @@ "fs_usage.tproj", "kdump.tproj", "sadc.tproj", - "sar.tproj" - ); + "sar.tproj" ); }; LANGUAGE = English; "LOCALIZABLE_FILES" = {}; diff --git a/audit.tproj/Makefile b/audit.tproj/Makefile new file mode 100644 index 0000000..3ad050e --- /dev/null +++ b/audit.tproj/Makefile @@ -0,0 +1,50 @@ +# +# Generated by the Apple Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = audit + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = audit.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ + auditd_control.defs audit.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /Library/Executables +PDO_UNIX_INSTALLDIR = /bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +HEADER_PATHS = -I../auditd.tproj + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/audit.tproj/Makefile.postamble b/audit.tproj/Makefile.postamble new file mode 100644 index 0000000..f093dff --- /dev/null +++ b/audit.tproj/Makefile.postamble @@ -0,0 +1,86 @@ +############################################################################### +# Makefile.postamble +# Copyright 2004, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGES: langages in which the project is written (default "English") +# English_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. +MIGFLAGS = +MIG = $(NEXT_ROOT)/usr/bin/mig + +auditd_control_user.c auditd_control.h: auditd_control.defs + cp $(SRCROOT)/auditd.tproj/auditd_control.defs $(SYM_DIR); + cd $(SYM_DIR) && \ + $(MIG) $(MIGFLAGS) -user auditd_control_user.c -header auditd_control.h \ + -server /dev/null -sheader /dev/null auditd_control.defs + + install-man-page: + install -d $(DSTROOT)/usr/share/man/man1 + install -c -m 444 audit.1 $(DSTROOT)/usr/share/man/man1/audit.1 diff --git a/audit.tproj/Makefile.preamble b/audit.tproj/Makefile.preamble new file mode 100644 index 0000000..e196000 --- /dev/null +++ b/audit.tproj/Makefile.preamble @@ -0,0 +1,19 @@ +############################################################################### +# Makefile.preamble +# Copyright 2004, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +OTHER_GENERATED_OFILES = $(VERS_OFILE) +BEFORE_BUILD = auditd_control.h auditd_control_user.c +OTHER_OFILES = auditd_control_user.o +AFTER_INSTALL += install-man-page + diff --git a/audit.tproj/PB.project b/audit.tproj/PB.project new file mode 100644 index 0000000..e0c75af --- /dev/null +++ b/audit.tproj/PB.project @@ -0,0 +1,32 @@ +{ + "DYNAMIC_CODE_GEN" = YES; + FILESTABLE = { + FRAMEWORKS = (); + HEADERSEARCH = ("../auditd.tproj"); + "OTHER_LINKED" = ("audit.c"); + "OTHER_SOURCES" = ( + "Makefile.preamble", + Makefile, + "Makefile.postamble", + "auditd_control.defs", + "audit.1" + ); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + "NEXTSTEP_BUILDTOOL" = "/usr/bin/gnumake"; + "NEXTSTEP_INSTALLDIR" = "/usr/sbin"; + "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac"; + "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc"; + "PDO_UNIX_BUILDTOOL" = "$NEXT_ROOT/Developer/bin/make"; + "PDO_UNIX_INSTALLDIR" = "/bin"; + "PDO_UNIX_JAVA_COMPILER" = "$(JDKBINDIR)/javac"; + "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = audit; + PROJECTTYPE = Tool; + PROJECTVERSION = "2.8"; + "WINDOWS_BUILDTOOL" = "$NEXT_ROOT/Developer/Executables/make"; + "WINDOWS_INSTALLDIR" = "/Library/Executables"; + "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe"; + "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc"; +} diff --git a/audit.tproj/audit.1 b/audit.tproj/audit.1 new file mode 100644 index 0000000..3b800a8 --- /dev/null +++ b/audit.tproj/audit.1 @@ -0,0 +1,43 @@ +.\" Copyright (c) 2004, Apple Computer, Inc. All rights reserved. +.\" +.Dd Jan 24, 2004 +.Dt AUDIT 1 +.Os "Mac OS X" +.Sh NAME +.Nm audit +.Nd audit management utility +.Sh SYNOPSIS +.Nm audit +.Op Fl nst +.Op Ar file +.Sh DESCRIPTION +The +.Nm +utility controls the state of auditing system. The optional +.Ar file +operand specifies the location of the audit control input file (default +/etc/security/audit_control). +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl n +Forces the audit system to close the existing audit log file and rotate to +a new log file in a location specified in the audit control file. +.It Fl s +Specifies that the audit system should [re]synchronize its +configuration from the audit control file. A new log file will be +created. +.It Fl t +Specifies that the audit system should terminate. Log files are closed +and renamed to indicate the time of the shutdown. +.El +.Sh NOTES +The auditd(8) daemon must already be running. +.Sh FILES +.Bl -tag -width "/etc/security/audit_control" -compact +.It Pa /etc/security/audit_control +Default audit policy file used to configure the auditing system. +.El +.Sh SEE ALSO +.Xr auditd 8 +.Xr audit_control 5 diff --git a/audit.tproj/audit.c b/audit.tproj/audit.c new file mode 100644 index 0000000..54b251f --- /dev/null +++ b/audit.tproj/audit.c @@ -0,0 +1,91 @@ +/* + * Program to trigger the audit daemon with a message that is either: + * - Open a new audit log file + * - Read the audit control file and take action on it + * - Close the audit log file and exit + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +mach_port_t serverPort; +mach_port_t bootstrapPort; + +void init(); +void process(int flags); + +/* + * Main routine to process command line options. + */ +int main(int argc, char **argv) +{ + char ch; + int flags = 0; + while ((ch = getopt(argc, argv, "nst")) != -1) { + switch(ch) { + + case 'n': + flags = OPEN_NEW; + break; + + case 's': + flags = READ_FILE; + break; + + case 't': + flags = CLOSE_AND_DIE; + break; + + case '?': + default: + (void)fprintf(stderr, + "usage: audit -n | -s | -t \n"); + exit(1); + } + } + init(); + process(flags); + return 0; +} + +/* + * Program initialization: + * Look up the server port and store it away. + */ +void init() +{ + if(host_get_audit_control_port(mach_host_self(), &serverPort) != KERN_SUCCESS) { + fprintf(stderr, "Cannot get auditd_control\n"); + exit(1); + } + + printf("Server port is %d\n", serverPort); +} + +/* + * Do all the real work. + * Send a message to the audit daemon and check the return code. + */ +void process(int flags) +{ + kern_return_t retcode; + retcode = auditd_control(serverPort, flags); + if(retcode != KERN_SUCCESS) { + mach_error("error doing IPC: ", retcode); + exit(1); + } + printf("Client call successful\n"); +} diff --git a/audit.tproj/auditd_control.defs b/audit.tproj/auditd_control.defs new file mode 100644 index 0000000..a4267ee --- /dev/null +++ b/audit.tproj/auditd_control.defs @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 2004 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "../auditd.tproj/auditd_control.defs" diff --git a/auditd.tproj/Makefile b/auditd.tproj/Makefile new file mode 100644 index 0000000..edb12d0 --- /dev/null +++ b/auditd.tproj/Makefile @@ -0,0 +1,52 @@ +# +# Generated by the Apple Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = auditd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = auditd.h + +CFILES = audit_warn.c auditd.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ + audit_triggers.defs auditd_control.defs auditd.8 rc.audit + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /Library/Executables +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_LDFLAGS = -lbsm + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/auditd.tproj/Makefile.postamble b/auditd.tproj/Makefile.postamble new file mode 100644 index 0000000..3b19087 --- /dev/null +++ b/auditd.tproj/Makefile.postamble @@ -0,0 +1,121 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGES: langages in which the project is written (default "English") +# English_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +ETCDIR = $(DSTROOT)/private/etc +MIGFLAGS = -no-cpp-precomp -R -untyped -DNO_DIRECT_RPC +MIG = $(NEXT_ROOT)/usr/bin/mig + +auditd_control_server.c : auditd_control.defs + cp $(SRCROOT)/auditd.tproj/auditd_control.defs $(SYM_DIR); + cd $(SYM_DIR) && \ + $(MIG) $(MIGFLAGS) -user /dev/null -server auditd_control_server.c -sheader auditd_control_server.h auditd_control.defs + +audit_triggers_server.c: audit_triggers.defs + cp $(SRCROOT)/auditd.tproj/audit_triggers.defs $(SYM_DIR); + cd $(SYM_DIR) && \ + $(MIG) $(MIGFLAGS) -user /dev/null -server audit_triggers_server.c -sheader audit_triggers_server.h audit_triggers.defs + +install-startup: + install -d $(ETCDIR)/security + install -c -m 400 rc.audit $(ETCDIR)/security/rc.audit + +install-man-page: + install -d $(DSTROOT)/usr/share/man/man8 + install -c -m 444 auditd.8 $(DSTROOT)/usr/share/man/man8/auditd.8 diff --git a/auditd.tproj/Makefile.preamble b/auditd.tproj/Makefile.preamble new file mode 100644 index 0000000..162794a --- /dev/null +++ b/auditd.tproj/Makefile.preamble @@ -0,0 +1,18 @@ +############################################################################### +# Makefile.preamble +# Copyright 2004, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +OTHER_GENERATED_OFILES = $(VERS_OFILE) +BEFORE_BUILD = auditd_control_server.c auditd_control_server.h \ + audit_triggers_server.c audit_triggers_server.h +OTHER_OFILES = auditd_control_server.o audit_triggers_server.o +AFTER_INSTALL += install-startup install-man-page diff --git a/auditd.tproj/PB.project b/auditd.tproj/PB.project new file mode 100644 index 0000000..f3df43c --- /dev/null +++ b/auditd.tproj/PB.project @@ -0,0 +1,38 @@ +{ + "DYNAMIC_CODE_GEN" = YES; + FILESTABLE = { + FRAMEWORKS = (); + "H_FILES" = ("auditd.h"); + "OTHER_LINKED" = ("audit_warn.c", "auditd.c"); + "OTHER_SOURCES" = ( + "Makefile.preamble", + Makefile, + "Makefile.postamble", + "audit_triggers.defs", + "auditd_control.defs", + "auditd.8", + "rc.audit" + ); + "PRECOMPILED_HEADERS" = (); + "PROJECT_HEADERS" = (); + "PUBLIC_HEADERS" = (); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + "NEXTSTEP_BUILDTOOL" = "/usr/bin/gnumake"; + "NEXTSTEP_INSTALLDIR" = "/usr/sbin"; + "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac"; + "NEXTSTEP_LINKEROPTIONS" = "-lbsm"; + "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc"; + "PDO_UNIX_BUILDTOOL" = "$NEXT_ROOT/Developer/bin/make"; + "PDO_UNIX_INSTALLDIR" = "/bin"; + "PDO_UNIX_JAVA_COMPILER" = "$(JDKBINDIR)/javac"; + "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = auditd; + PROJECTTYPE = Tool; + PROJECTVERSION = "2.8"; + "WINDOWS_BUILDTOOL" = "$NEXT_ROOT/Developer/Executables/make"; + "WINDOWS_INSTALLDIR" = "/Library/Executables"; + "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe"; + "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc"; +} diff --git a/auditd.tproj/audit_triggers.defs b/auditd.tproj/audit_triggers.defs new file mode 100644 index 0000000..9fe2c35 --- /dev/null +++ b/auditd.tproj/audit_triggers.defs @@ -0,0 +1 @@ +#include diff --git a/auditd.tproj/audit_warn.c b/auditd.tproj/audit_warn.c new file mode 100644 index 0000000..22657a1 --- /dev/null +++ b/auditd.tproj/audit_warn.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 2004 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include + +#include + +/* Write to the audit log. */ +static int auditwarnlog(char *args[]) +{ + char *loc_args[9]; + int i; + pid_t pid; + loc_args[0] = AUDITWARN_SCRIPT; + for (i = 0; args[i] != NULL && i < 8; i++) { + loc_args[i+1] = args[i]; + } + loc_args[i+1] = NULL; + + pid = fork(); + if (pid == 0) { + return execv(AUDITWARN_SCRIPT, loc_args); + /* not reached */ + exit(1); + } else if (pid == -1) { + return -1; + } else { + return 0; + } +} + +/* + * Indicates that the hard limit for all filesystems + * has been exceeded count times + */ +int audit_warn_allhard(int count) +{ + char intstr[12]; + char *args[3]; + + snprintf(intstr, 12, "%d", count); + + args[0] = HARDLIM_ALL_WARN; + args[1] = intstr; + args[2] = NULL; + + return auditwarnlog(args); +} + +/* + * Indicates that the soft limit for all filesystems + * has been exceeded + */ +int audit_warn_allsoft() +{ + char *args[2]; + + args[0] = SOFTLIM_ALL_WARN; + args[1] = NULL; + + return auditwarnlog(args); +} + +/* + * Indicates that someone other than the audit daemon + * turned off auditing + * XXX Its not clear at this point how this function will + * XXX be invoked + */ +int audit_warn_auditoff() +{ + char *args[2]; + + args[0] = AUDITOFF_WARN; + args[1] = NULL; + + return auditwarnlog(args); +} + +/* + * Indicates that the audit deammn is already running + */ +int audit_warn_ebusy() +{ + char *args[2]; + + args[0] = EBUSY_WARN; + args[1] = NULL; + + return auditwarnlog(args); + +} + +/* + * Indicates that there is a problem getting the directory + * from audit_control + * + * XXX Note that we take the filename instead of a count + * XXX as the argument here (different from BSM) + */ +int audit_warn_getacdir(char *filename) +{ + char *args[3]; + + args[0] = GETACDIR_WARN; + args[1] = filename; + args[2] = NULL; + + return auditwarnlog(args); +} + + +/* + * Indicates that the hard limit for this file has been + * exceeded + */ +int audit_warn_hard(char *filename) +{ + char *args[3]; + + args[0] = HARDLIM_WARN; + args[1] = filename; + args[2] = NULL; + + return auditwarnlog(args); + +} + +/* + * Indicates that auditing could not be started + */ +int audit_warn_nostart() +{ + char *args[2]; + + args[0] = NOSTART_WARN; + args[1] = NULL; + + return auditwarnlog(args); +} + +/* + * Indicaes that an error occrred during the orderly shutdown + * of the audit daemon + */ +int audit_warn_postsigterm() +{ + char *args[2]; + + args[0] = POSTSIGTERM_WARN; + args[1] = NULL; + + return auditwarnlog(args); +} + +/* + * Indicates that the soft limit for this file has been + * exceeded + */ +int audit_warn_soft(char *filename) +{ + char *args[3]; + + args[0] = SOFTLIM_WARN; + args[1] = filename; + args[2] = NULL; + + return auditwarnlog(args); + +} + +/* + * Indicates that the temporary audit file already exists + * indicating a fatal error + */ +int audit_warn_tmpfile() +{ + char *args[2]; + + args[0] = TMPFILE_WARN; + args[1] = NULL; + + return auditwarnlog(args); +} diff --git a/auditd.tproj/auditd.8 b/auditd.tproj/auditd.8 new file mode 100644 index 0000000..c5a9b15 --- /dev/null +++ b/auditd.tproj/auditd.8 @@ -0,0 +1,48 @@ +.\" Copyright (c) 2004, Apple Computer, Inc. All rights reserved. +.\" +.Dd Jan 24, 2004 +.Dt AUDITD 8 +.Os "Mac OS X" +.Sh NAME +.Nm auditd +.Nd audit log management daemon +.Sh SYNOPSIS +.Nm auditd +.Op Fl dhs +.Sh DESCRIPTION +The +.Nm +daemon responds to requests from the audit(1) utility and notifications +from the kernel. It manages the resulting audit log files and specified +log file locations. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl d +Starts the daemon in debug mode - it will not daemonize. +.It Fl h +Specifies that if auditing cannot be performed as specified, the system should +halt (panic). Normally, the system will attempt to proceed - although individual +processes may be stopped (see the -s option). +.It Fl s +Specifies that individual processes should stop rather than perform operations +that may cause audit records to be lost due to log file full conditions +.El +.Sh NOTE +.Pp +To assure uninterrupted audit support, the +.Nm auditd +daemon should not be started and stopped manually. Instead, the audit(1) command +should be used to inform the daemon to change state/configuration after altering +the audit_control file. +.Pp +Sending a SIGHUP to a running +.Nm auditd +daemon will force it to exit. +.Sh FILES +.Bl -tag -width "/var/audit" -compact +.It Pa /var/audit +Default directory for storing audit log files. +.El +.Sh SEE ALSO +.Xr audit 1 diff --git a/auditd.tproj/auditd.c b/auditd.tproj/auditd.c new file mode 100644 index 0000000..459bee3 --- /dev/null +++ b/auditd.tproj/auditd.c @@ -0,0 +1,791 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 2004 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "auditd_control_server.h" +#include "audit_triggers_server.h" +#define NA_EVENT_STR_SIZE 25 + +static int ret, minval; +static char *lastfile = NULL; + +static int allhardcount = 0; + +mach_port_t bp = MACH_PORT_NULL; +mach_port_t control_port = MACH_PORT_NULL; +mach_port_t signal_port = MACH_PORT_NULL; +mach_port_t port_set = MACH_PORT_NULL; + +#ifndef __BSM_INTERNAL_NOTIFY_KEY +#define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" +#endif /* __BSM_INTERNAL_NOTIFY_KEY */ + +TAILQ_HEAD(, dir_ent) dir_q; + + +/* Error starting auditd */ +void fail_exit() +{ + audit_warn_nostart(); + exit(1); +} + +/* + * Free our local list of directory names + */ +void free_dir_q() +{ + struct dir_ent *dirent; + + while ((dirent = TAILQ_FIRST(&dir_q))) { + TAILQ_REMOVE(&dir_q, dirent, dirs); + free(dirent->dirname); + free(dirent); + } +} + +/* + * generate the timestamp string + */ +int getTSstr(char *buf, int len) +{ + struct timeval ts; + struct timezone tzp; + time_t tt; + + if(gettimeofday(&ts, &tzp) != 0) { + return -1; + } + tt = (time_t)ts.tv_sec; + if(!strftime(buf, len, "%Y%m%d%H%M%S", gmtime(&tt))) { + return -1; + } + + return 0; +} + +/* + * Concat the directory name to the given file name + * XXX We should affix the hostname also + */ +char *affixdir(char *name, struct dir_ent *dirent) +{ + char *fn; + char *curdir; + const char *sep = "/"; + + curdir = dirent->dirname; + syslog(LOG_INFO, "dir = %s\n", dirent->dirname); + + fn = (char *) malloc (strlen(curdir) + strlen(sep) + + (2 * POSTFIX_LEN) + 1); + if(fn == NULL) { + return NULL; + } + strcpy(fn, curdir); + strcat(fn, sep); + strcat(fn, name); + + return fn; +} + +/* Close the previous audit trail file */ +int close_lastfile(char *TS) +{ + char *ptr; + char *oldname; + + if(lastfile != NULL) { + oldname = (char *)malloc(strlen(lastfile) + 1); + if(oldname == NULL) { + return -1; + } + strcpy(oldname, lastfile); + + /* rename the last file -- append timestamp */ + + if((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) { + *ptr = '.'; + strcpy(ptr+1, TS); + if(rename(oldname, lastfile) != 0) { + syslog(LOG_ERR, "Could not rename %s to %s \n", + oldname, lastfile); + } + else { + syslog(LOG_INFO, "renamed %s to %s \n", + oldname, lastfile); + } + } + + free(lastfile); + free(oldname); + + lastfile = NULL; + } + + return 0; +} + +/* + * Create the new file name, swap with existing audit file + */ +int swap_audit_file() +{ + char timestr[2 * POSTFIX_LEN]; + char *fn; + char TS[POSTFIX_LEN]; + struct dir_ent *dirent; + + if(getTSstr(TS, POSTFIX_LEN) != 0) { + return -1; + } + + strcpy(timestr, TS); + strcat(timestr, NOT_TERMINATED); + + /* try until we succeed */ + while((dirent = TAILQ_FIRST(&dir_q))) { + if((fn = affixdir(timestr, dirent)) == NULL) { + return -1; + } + + syslog(LOG_INFO, "New audit file is %s\n", fn); + if (open(fn, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP) < 0) { + perror("File open"); + } + else if (auditctl(fn) != 0) { + syslog(LOG_ERR, "auditctl failed! : %s\n", + strerror(errno)); + } + else { + /* Success */ + close_lastfile(TS); + lastfile = fn; + return 0; + } + + /* Tell the administrator about lack of permissions for dirent */ + audit_warn_getacdir(dirent->dirname); + + /* Try again with a different directory */ + TAILQ_REMOVE(&dir_q, dirent, dirs); + free(dirent->dirname); + free(dirent); + } + return -1; +} + +/* + * Read the audit_control file contents + */ +int read_control_file() +{ + char cur_dir[MAX_DIR_SIZE]; + struct dir_ent *dirent; + au_qctrl_t qctrl; + + /* Clear old values */ + free_dir_q(); + endac(); // force a re-read of the file the next time + + /* Post that the audit config changed */ + notify_post(__BSM_INTERNAL_NOTIFY_KEY); + + /* Read the list of directories into a local linked list */ + /* XXX We should use the reentrant interfaces once they are available */ + while(getacdir(cur_dir, MAX_DIR_SIZE) >= 0) { + dirent = (struct dir_ent *) malloc (sizeof(struct dir_ent)); + if(dirent == NULL) { + return -1; + } + + dirent->softlim = 0; + dirent->dirname = (char *) malloc (MAX_DIR_SIZE); + if(dirent->dirname == NULL) { + free(dirent); + return -1; + } + + strcpy(dirent->dirname, cur_dir); + TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); + } + + allhardcount = 0; + + if(swap_audit_file() == -1) { + syslog(LOG_ERR, "Could not swap audit file\n"); + /* + * XXX Faulty directory listing? - user should be given + * XXX an opportunity to change the audit_control file + * XXX switch to a reduced mode of auditing? + */ + return -1; + } + + /* + * XXX There are synchronization problems here + * XXX what should we do if a trigger for the earlier limit + * XXX is generated here? + */ + if(0 == (ret = getacmin(&minval))) { + + syslog(LOG_INFO, "min free = %d\n", minval); + + if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) { + syslog(LOG_ERR, + "could not get audit queue settings\n"); + return -1; + } + qctrl.aq_minfree = minval; + if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) { + syslog(LOG_ERR, + "could not set audit queue settings\n"); + return -1; + } + } + + return 0; +} + +/* + * Close all log files, control files, and tell the audit system. + */ +int close_all() +{ + int err_ret = 0; + char TS[POSTFIX_LEN]; + int aufd; + token_t *tok; + + /* Generate an audit record */ + if((aufd = au_open()) == -1) { + syslog(LOG_ERR, "Could not create audit shutdown event.\n"); + } else { + + if((tok = au_to_text("auditd::Audit shutdown")) != NULL) { + au_write(aufd, tok); + } + + if(au_close(aufd, 1, AUE_audit_shutdown) == -1) { + syslog(LOG_ERR, "Could not close audit shutdown event.\n"); + } + } + + /* flush contents */ + err_ret = auditctl(NULL); + if (err_ret != 0) { + syslog(LOG_ERR, "auditctl failed! : %s\n", + strerror(errno)); + err_ret = 1; + } + if(getTSstr(TS, POSTFIX_LEN) == 0) { + close_lastfile(TS); + } + if(lastfile != NULL) + free(lastfile); + + free_dir_q(); + if((remove(AUDITD_PIDFILE) == -1) || err_ret) { + syslog(LOG_ERR, "Could not unregister\n"); + audit_warn_postsigterm(); + return (1); + } + endac(); + syslog(LOG_INFO, "Finished.\n"); + return (0); +} + +/* + * When we get a signal, we are often not at a clean point. + * So, little can be done in the signal handler itself. Instead, + * we send a message to the main servicing loop to do proper + * handling from a non-signal-handler context. + */ +static void +relay_signal(int signal) +{ + mach_msg_empty_send_t msg; + + msg.header.msgh_id = signal; + msg.header.msgh_remote_port = signal_port; + msg.header.msgh_local_port = MACH_PORT_NULL; + msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); + mach_msg(&(msg.header), MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof(msg), + 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); +} + +/* registering the daemon */ +int register_daemon() +{ + FILE * pidfile; + int fd; + pid_t pid; + + /* Set up the signal hander */ + if (signal(SIGTERM, relay_signal) == SIG_ERR) { + fail_exit(); + } + if (signal(SIGCHLD, relay_signal) == SIG_ERR) { + fail_exit(); + } + + if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { + audit_warn_tmpfile(); + return -1; + } + + /* attempt to lock the pid file; if a lock is present, exit */ + fd = fileno(pidfile); + if(flock(fd, LOCK_EX | LOCK_NB) < 0) { + syslog(LOG_ERR, "PID file is locked (is another auditd running?).\n"); + audit_warn_ebusy(); + return -1; + } + + pid = getpid(); + ftruncate(fd, 0); + if(fprintf(pidfile, "%u\n", pid) < 0) { + /* should not start the daemon */ + fail_exit(); + } + + fflush(pidfile); + return 0; +} + +/* + * React to input from the audit tool + */ +kern_return_t auditd_control(auditd_port, flags) + mach_port_t auditd_port; + int flags; +{ + int err_ret = 0; + + switch(flags) { + + case OPEN_NEW : + /* create a new file and swap with the one being used in kernel */ + if(swap_audit_file() == -1) { + syslog(LOG_ERR, "Error swapping audit file\n"); + } + break; + + case READ_FILE : + if(read_control_file() == -1) { + syslog(LOG_ERR, "Error in audit control file\n"); + } + break; + + case CLOSE_AND_DIE : + err_ret = close_all(); + exit (err_ret); + break; + + default : + break; + } + + return KERN_SUCCESS; +} + +/* + * Suppress duplicate messages within a 30 second interval. + * This should be enough to time to rotate log files without + * thrashing from soft warnings generated before the log is + * actually rotated. + */ +#define DUPLICATE_INTERVAL 30 +/* + * Implementation of the audit_triggers() MIG routine. + */ +kern_return_t audit_triggers(audit_port, flags) + mach_port_t audit_port; + int flags; +{ + static int last_flags; + static time_t last_time; + struct dir_ent *dirent; + + /* + * Suppres duplicate messages from the kernel within the specified interval + */ + struct timeval ts; + struct timezone tzp; + time_t tt; + + if(gettimeofday(&ts, &tzp) == 0) { + tt = (time_t)ts.tv_sec; + if ((flags == last_flags) && (tt < (last_time + DUPLICATE_INTERVAL))) { + return KERN_SUCCESS; + } + last_flags = flags; + last_time = tt; + } + + syslog(LOG_INFO, + "audit_triggers() called within auditd with flags = %d\n", + flags); + /* + * XXX Message processing is done here + */ + dirent = TAILQ_FIRST(&dir_q); + if(flags == AUDIT_TRIGGER_LOW_SPACE) { + if(dirent && (dirent->softlim != 1)) { + TAILQ_REMOVE(&dir_q, dirent, dirs); + /* add this node to the end of the list */ + TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); + audit_warn_soft(dirent->dirname); + dirent->softlim = 1; + + if (TAILQ_NEXT(TAILQ_FIRST(&dir_q), dirs) != NULL && swap_audit_file() == -1) { + syslog(LOG_ERR, "Error swapping audit file\n"); + } + + /* + * check if the next dir has already reached its + * soft limit + */ + dirent = TAILQ_FIRST(&dir_q); + if(dirent->softlim == 1) { + /* all dirs have reached their soft limit */ + audit_warn_allsoft(); + } + } + else { + /* + * Continue auditing to the current file + * Also generate an allsoft warning + * XXX do we want to do this ? + */ + audit_warn_allsoft(); + } + } + else if (flags == AUDIT_TRIGGER_FILE_FULL) { + + /* delete current dir, go on to next */ + TAILQ_REMOVE(&dir_q, dirent, dirs); + audit_warn_hard(dirent->dirname); + free(dirent->dirname); + free(dirent); + + if(swap_audit_file() == -1) { + syslog(LOG_ERR, "Error swapping audit file in response to AUDIT_TRIGGER_FILE_FULL message\n"); + + /* Nowhere to write to */ + audit_warn_allhard(++allhardcount); + } + } + return KERN_SUCCESS; +} + +/* + * Reap our children. + */ +static void +reap_children(void) +{ + pid_t child; + int wstatus; + + while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { + if (wstatus) { + syslog(LOG_INFO, "warn process [pid=%d] %s %d.\n", child, + ((WIFEXITED(wstatus)) ? + "exited with non-zero status" : + "exited as a result of signal"), + ((WIFEXITED(wstatus)) ? + WEXITSTATUS(wstatus) : + WTERMSIG(wstatus))); + } + } +} + +/* + * Handle an RPC call + */ +boolean_t auditd_combined_server( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP) +{ + mach_port_t local_port = InHeadP->msgh_local_port; + + if (local_port == signal_port) { + int signo = InHeadP->msgh_id; + int ret; + + if (SIGTERM == signo) { + ret = close_all(); + exit (ret); + } else if (SIGCHLD == signo) { + reap_children(); + return TRUE; + } else { + syslog(LOG_INFO, "Recevied signal %d.\n", signo); + return TRUE; + } + } else if (local_port == control_port) { + boolean_t result; + + result = audit_triggers_server(InHeadP, OutHeadP); + if (!result) + result = auditd_control_server(InHeadP, OutHeadP); + return result; + } + syslog(LOG_INFO, "Recevied msg on bad port 0x%x.\n", local_port); + return FALSE; +} + +void wait_on_audit_trigger(port_set) + mach_port_t port_set; +{ + kern_return_t result; + result = mach_msg_server(auditd_combined_server, 4096, port_set, MACH_MSG_OPTION_NONE); + syslog(LOG_ERR, "abnormal exit\n"); +} + +/* + * Configure the audit controls in the kernel: the event to class mapping, + * kernel preselection mask, etc. + */ +int config_audit_controls(long flags) +{ + au_event_ent_t *ev; + au_evclass_map_t evc_map; + au_mask_t aumask; + int ctr = 0; + char naeventstr[NA_EVENT_STR_SIZE]; + + /* Process the audit event file, obtaining a class mapping for each + * event, and send that mapping into the kernel. + * XXX There's a risk here that the BSM library will return NULL + * for an event when it can't properly map it to a class. In that + * case, we will not process any events beyond the one that failed, + * but should. We need a way to get a count of the events. + */ + + setauevent(); + while((ev = getauevent()) != NULL) { + evc_map.ec_number = ev->ae_number; + evc_map.ec_class = ev->ae_class; + if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t)) != 0) { + syslog(LOG_ERR, + "Failed to register class mapping for event %s", + ev->ae_name); + } else { + ctr++; + } + free(ev->ae_name); + free(ev->ae_desc); + free(ev); + } + endauevent(); + if (ctr == 0) + syslog(LOG_ERR, "No events to class mappings registered."); + else + syslog(LOG_INFO, "Registered %d event to class mappings.", ctr); + + /* Get the non-attributable event string and set the kernel mask + * from that. + */ + if ((getacna(naeventstr, NA_EVENT_STR_SIZE) == 0) + && ( getauditflagsbin(naeventstr, &aumask) == 0)) { + + if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t))){ + syslog(LOG_ERR, + "Failed to register non-attributable event mask."); + } else { + syslog(LOG_INFO, "Registered non-attributable event mask."); + } + + } else { + syslog(LOG_ERR,"Failed to obtain non-attributable event mask."); + } + + /* + * Set the audit policy flags based on passed in parameter values. + */ + if (auditon(A_SETPOLICY, &flags, sizeof(flags))) { + syslog(LOG_ERR, + "Failed to set audit policy."); + } + + return 0; +} + +void setup(long flags) +{ + mach_msg_type_name_t poly; + int aufd; + token_t *tok; + + /* Allocate a port set */ + if (mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_PORT_SET, + &port_set) != KERN_SUCCESS) { + syslog(LOG_ERR, "allocation of port set failed\n"); + fail_exit(); + } + + /* Allocate a signal reflection port */ + if (mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_RECEIVE, + &signal_port) != KERN_SUCCESS || + mach_port_move_member(mach_task_self(), + signal_port, + port_set) != KERN_SUCCESS) { + syslog(LOG_ERR, "allocation of signal port failed\n"); + fail_exit(); + } + + /* Allocate a trigger port */ + if (mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_RECEIVE, + &control_port) != KERN_SUCCESS || + mach_port_move_member(mach_task_self(), + control_port, + port_set) != KERN_SUCCESS) { + syslog(LOG_ERR, "allocation of trigger port failed\n"); + fail_exit(); + } + + /* create a send right on our trigger port */ + mach_port_extract_right(mach_task_self(), control_port, + MACH_MSG_TYPE_MAKE_SEND, &control_port, &poly); + + TAILQ_INIT(&dir_q); + + /* register the trigger port with the kernel */ + if(host_set_audit_control_port(mach_host_self(), control_port) != KERN_SUCCESS) { + syslog(LOG_ERR, "Cannot set Mach control port\n"); + fail_exit(); + } + else { + syslog(LOG_ERR, "Mach control port registered\n"); + } + + if(read_control_file() == -1) { + syslog(LOG_ERR, "Error reading control file\n"); + fail_exit(); + } + + /* Generate an audit record */ + if((aufd = au_open()) == -1) { + syslog(LOG_ERR, "Could not create audit startup event.\n"); + } else { + + if((tok = au_to_text("auditd::Audit startup")) != NULL) { + au_write(aufd, tok); + } + + if(au_close(aufd, 1, AUE_audit_startup) == -1) { + syslog(LOG_ERR, "Could not close audit startup event.\n"); + } + } + + if (config_audit_controls(flags) == 0) + syslog(LOG_INFO, "Initialization successful\n"); + else + syslog(LOG_INFO, "Initialization failed\n"); +} + + +int main(int argc, char **argv) +{ + char ch; + long flags = AUDIT_CNT; + int debug = 0; + + while ((ch = getopt(argc, argv, "dhs")) != -1) { + switch(ch) { + + /* debug option */ + case 'd': + debug = 1; + break; + + /* fail-stop option */ + case 's': + flags &= ~(AUDIT_CNT); + break; + + /* halt-stop option */ + case 'h': + flags |= AUDIT_AHLT; + break; + + case '?': + default: + (void)fprintf(stderr, + "usage: auditd [-h | -s]\n"); + exit(1); + } + } + + openlog("auditd", LOG_CONS | LOG_PID, LOG_DAEMON); + syslog(LOG_INFO, "starting...\n"); + + if (debug == 0 && daemon(0, 0) == -1) { + syslog(LOG_ERR, "Failed to daemonize\n"); + exit(1); + } + + if(register_daemon() == -1) { + syslog(LOG_ERR, "Could not register as daemon\n"); + exit(1); + } + + setup(flags); + wait_on_audit_trigger(port_set); + syslog(LOG_INFO, "exiting.\n"); + + exit(1); +} diff --git a/auditd.tproj/auditd.h b/auditd.tproj/auditd.h new file mode 100644 index 0000000..5866377 --- /dev/null +++ b/auditd.tproj/auditd.h @@ -0,0 +1,51 @@ +#ifndef _AUDITD_H_ +#define _AUDITD_H_ + +#include +#include +#include + +#define MAX_DIR_SIZE 255 +#define AUDITD_NAME "auditd" + +#define POSTFIX_LEN 16 +#define NOT_TERMINATED ".not_terminated" + +struct dir_ent { + char *dirname; + char softlim; + TAILQ_ENTRY(dir_ent) dirs; +}; + +/* audit utility flags */ +#define OPEN_NEW 0x1 +#define READ_FILE 0x2 +#define CLOSE_AND_DIE 0x4 + +#define HARDLIM_ALL_WARN "allhard" +#define SOFTLIM_ALL_WARN "allsoft" +#define AUDITOFF_WARN "aditoff" +#define EBUSY_WARN "ebusy" +#define GETACDIR_WARN "getacdir" +#define HARDLIM_WARN "hard" +#define NOSTART_WARN "nostart" +#define POSTSIGTERM_WARN "postsigterm" +#define SOFTLIM_WARN "soft" +#define TMPFILE_WARN "tmpfile" + +#define AUDITWARN_SCRIPT "/etc/security/audit_warn" +#define AUDITD_PIDFILE "/var/run/auditd.pid" + +int audit_warn_allhard(int count); +int audit_warn_allsoft(); +int audit_warn_auditoff(); +int audit_warn_ebusy(); +int audit_warn_getacdir(char *filename); +int audit_warn_hard(char *filename); +int audit_warn_nostart(); +int audit_warn_postsigterm(); +int audit_warn_soft(char *filename); +int audit_warn_tmpfile(); + +#endif /* !_AUDITD_H_ */ + diff --git a/auditd.tproj/auditd_control.defs b/auditd.tproj/auditd_control.defs new file mode 100644 index 0000000..1cf8346 --- /dev/null +++ b/auditd.tproj/auditd_control.defs @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 2004 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Exported client calls to the auditd facility. + */ + +subsystem + KernelUser + auditd_control 456; + +#include +#include + +simpleroutine auditd_control( + auditd_port : mach_port_t; + in flags : int); + diff --git a/auditd.tproj/rc.audit b/auditd.tproj/rc.audit new file mode 100644 index 0000000..799dc3c --- /dev/null +++ b/auditd.tproj/rc.audit @@ -0,0 +1,25 @@ +## +# Startup script for Common Criteria Auditing function. +## +# Copyright 2004 Apple Computer, Inc. +## + +. /etc/rc.common + +## +# Start the audit daemon (if present) +## +if [ "${AUDIT:=-NO-}" == "-YES-" ]; then + if [ -f /usr/sbin/auditd ]; then + /usr/sbin/auditd + fi +elif [ "${AUDIT:=-NO-}" == "-FAILSTOP-" ]; then + if [ -f /usr/sbin/auditd ]; then + /usr/sbin/auditd -s + fi +elif [ "${AUDIT:=-NO-}" == "-FAILHALT-" ]; then + if [ -f /usr/sbin/auditd ]; then + /usr/sbin/auditd -h + fi + +fi diff --git a/login.tproj/Makefile b/login.tproj/Makefile index 66d930a..fda2a0c 100644 --- a/login.tproj/Makefile +++ b/login.tproj/Makefile @@ -1,5 +1,5 @@ # -# Generated by the NeXT Project Builder. +# Generated by the Apple Project Builder. # # NOTE: Do NOT change this file -- Project Builder maintains it. # @@ -25,7 +25,7 @@ MAKEFILE = tool.make NEXTSTEP_INSTALLDIR = /usr/bin WINDOWS_INSTALLDIR = /usr/bin PDO_UNIX_INSTALLDIR = /usr/bin -LIBS = -lpam -lpam_misc +LIBS = -lbsm -lpam -lpam_misc DEBUG_LIBS = $(LIBS) PROF_LIBS = $(LIBS) diff --git a/login.tproj/PB.project b/login.tproj/PB.project index 5ee51ca..dbf43ab 100644 --- a/login.tproj/PB.project +++ b/login.tproj/PB.project @@ -1,25 +1,25 @@ { DOCICONFILES = (); FILESTABLE = { - C_FILES = (); - H_FILES = (pathnames.h); - OTHER_LIBS = (); - OTHER_LINKED = (klogin.c, login.c); - OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, login.1); + "C_FILES" = (); + "H_FILES" = ("pathnames.h"); + "OTHER_LIBS" = (bsm, pam, "pam_misc"); + "OTHER_LINKED" = ("klogin.c", "login.c"); + "OTHER_SOURCES" = ("Makefile.preamble", Makefile, "Makefile.postamble", "login.1"); SUBPROJECTS = (); }; LANGUAGE = English; - LOCALIZABLE_FILES = {}; - NEXTSTEP_INSTALLDIR = /usr/bin; - NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; - NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; - PDO_UNIX_INSTALLDIR = /usr/bin; - PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + "LOCALIZABLE_FILES" = {}; + "NEXTSTEP_INSTALLDIR" = "/usr/bin"; + "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac"; + "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc"; + "PDO_UNIX_INSTALLDIR" = "/usr/bin"; + "PDO_UNIX_JAVA_COMPILER" = "$(NEXTDEV_BIN)/javac"; + "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc"; PROJECTNAME = login; PROJECTTYPE = Tool; - PROJECTVERSION = 2.8; - WINDOWS_INSTALLDIR = /usr/bin; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; + PROJECTVERSION = "2.8"; + "WINDOWS_INSTALLDIR" = "/usr/bin"; + "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe"; + "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc"; } diff --git a/login.tproj/login.c b/login.tproj/login.c index 4bcf731..ebedd0e 100644 --- a/login.tproj/login.c +++ b/login.tproj/login.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -87,6 +87,15 @@ static char copyright[] = #include #include +#include +#include +#include +#include +#include + +#include +#include + #ifdef USE_PAM #include #include @@ -107,6 +116,9 @@ void timedout __P((int)); #ifdef KERBEROS int klogin __P((struct passwd *, char *, char *, char *)); #endif +void au_success(); +void au_fail(char *, int); + extern void login __P((struct utmp *)); @@ -129,6 +141,9 @@ struct passwd *pwd; int failures; char term[64], *hostname, *username = NULL, *tty; +#define NA_EVENT_STR_SIZE 25 +au_tid_t tid; + int main(argc, argv) int argc; @@ -153,6 +168,8 @@ main(argc, argv) pid_t pid; #endif + char auditsuccess = 1; + (void)signal(SIGALRM, timedout); (void)alarm(timeout); (void)signal(SIGQUIT, SIG_IGN); @@ -161,6 +178,7 @@ main(argc, argv) openlog("login", LOG_ODELAY, LOG_AUTH); + /* * -p is used by getty to tell login not to destroy the environment * -f is used to skip a second login authentication @@ -228,27 +246,44 @@ main(argc, argv) else tty = ttyn; + /* Set the terminal id */ + audit_set_terminal_id(&tid); + if (fstat(STDIN_FILENO, &st) < 0) { + fprintf(stderr, "login: Unable to stat terminal\n"); + au_fail("Unable to stat terminal", 1); + exit(-1); + } + if (S_ISCHR(st.st_mode)) { + tid.port = st.st_rdev; + } else { + tid.port = 0; + } + #ifdef USE_PAM rval = pam_start("login", username, &conv, &pamh); if( rval != PAM_SUCCESS ) { fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval)); + au_fail("PAM Error", 1); exit(1); } rval = pam_set_item(pamh, PAM_TTY, tty); if( rval != PAM_SUCCESS ) { fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval)); + au_fail("PAM Error", 1); exit(1); } rval = pam_set_item(pamh, PAM_RHOST, hostname); if( rval != PAM_SUCCESS ) { fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval)); + au_fail("PAM Error", 1); exit(1); } rval = pam_set_item(pamh, PAM_USER_PROMPT, "login: "); if( rval != PAM_SUCCESS ) { fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval)); + au_fail("PAM Error", 1); exit(1); } @@ -261,6 +296,7 @@ main(argc, argv) if( (pwd != NULL) && fflag && ((uid == 0) || (uid == pwd->pw_uid)) ){ rval = 0; + auditsuccess = 0; /* we've simply opened a terminal window */ } else { rval = pam_authenticate(pamh, 0); @@ -268,6 +304,11 @@ main(argc, argv) (rval == PAM_USER_UNKNOWN) || (rval == PAM_CRED_INSUFFICIENT) || (rval == PAM_AUTHINFO_UNAVAIL))) { + /* + * we are not exiting here, but this corresponds to + * a failed login event, so set exitstatus to 1 + */ + au_fail("Login incorrect", 1); badlogin(username); printf("Login incorrect\n"); rootlogin = 0; @@ -283,6 +324,7 @@ main(argc, argv) pam_get_item(pamh, PAM_USER, (void *)&username); badlogin(username); printf("Login incorrect\n"); + au_fail("Login incorrect", 1); exit(1); } @@ -292,8 +334,10 @@ main(argc, argv) } if( rval != PAM_SUCCESS ) { fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval)); + au_fail("PAM error", 1); exit(1); } + } rval = pam_get_item(pamh, PAM_USER, (void *)&username); @@ -303,12 +347,14 @@ main(argc, argv) rval = pam_open_session(pamh, 0); if( rval != PAM_SUCCESS ) { fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval)); + au_fail("PAM error", 1); exit(1); } rval = pam_setcred(pamh, PAM_ESTABLISH_CRED); if( rval != PAM_SUCCESS ) { fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval)); + au_fail("PAM error", 1); exit(1); } @@ -336,8 +382,9 @@ main(argc, argv) * for nonexistent name (mistyped username). */ if (failures && strcmp(tbuf, username)) { - if (failures > (pwd ? 0 : 1)) + if (failures > (pwd ? 0 : 1)) { badlogin(tbuf); + } failures = 0; } (void)strcpy(tbuf, username); @@ -400,6 +447,7 @@ main(argc, argv) syslog(LOG_NOTICE, "LOGIN %s REFUSED ON TTY %s", pwd->pw_name, tty); + au_fail("Login refused on terminal", 0); continue; } @@ -412,8 +460,10 @@ main(argc, argv) if (++cnt > 3) { if (cnt >= 10) { badlogin(username); + au_fail("Login incorrect", 1); sleepexit(1); } + au_fail("Login incorrect", 1); sleep((u_int)((cnt - 3) * 5)); } } @@ -428,25 +478,32 @@ main(argc, argv) if (!rootlogin) checknologin(); + /* Audit successful login */ + if (auditsuccess) + au_success(); + setegid(pwd->pw_gid); seteuid(rootlogin ? 0 : pwd->pw_uid); - /* First do a stat in case the homedir is automounted */ - stat(pwd->pw_dir,&st); + /* First do a stat in case the homedir is automounted */ + stat(pwd->pw_dir,&st); if (chdir(pwd->pw_dir) < 0) { (void)printf("No home directory %s!\n", pwd->pw_dir); - if (chdir("/")) + if (chdir("/")) { exit(0); + } pwd->pw_dir = "/"; (void)printf("Logging in with home = \"/\".\n"); } + seteuid(euid); setegid(egid); quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; /* Nothing else left to fail -- really log in. */ + memset((void *)&utmp, 0, sizeof(utmp)); (void)time(&utmp.ut_time); (void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); @@ -546,6 +603,7 @@ main(argc, argv) else (void) setuid(pwd->pw_uid); + execlp(pwd->pw_shell, tbuf, 0); err(1, "%s", pwd->pw_shell); } @@ -556,6 +614,142 @@ main(argc, argv) #define NBUFSIZ (MAXLOGNAME + 1) #endif +/* + * The following tokens are included in the audit record for successful login attempts + * header + * subject + * return + */ +void au_success() +{ + token_t *tok; + int aufd; + au_mask_t aumask; + auditinfo_t auinfo; + uid_t uid = pwd->pw_uid; + gid_t gid = pwd->pw_gid; + pid_t pid = getpid(); + long au_cond; + + /* If we are not auditing, don't cut an audit record; just return */ + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + fprintf(stderr, "login: Could not determine audit condition\n"); + exit(1); + } + if (au_cond == AUC_NOAUDIT) + return; + + /* Compute and Set the user's preselection mask */ + if(au_user_mask(pwd->pw_name, &aumask) == -1) { + fprintf(stderr, "login: Could not set audit mask\n"); + exit(1); + } + + /* Set the audit info for the user */ + auinfo.ai_auid = uid; + auinfo.ai_asid = pid; + bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid)); + bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask)); + if(setaudit(&auinfo) != 0) { + fprintf(stderr, "login: setaudit failed: %s\n", strerror(errno)); + exit(1); + } + + if((aufd = au_open()) == -1) { + fprintf(stderr, "login: Audit Error: au_open() failed\n"); + exit(1); + } + + /* The subject that is created (euid, egid of the current process) */ + if((tok = au_to_subject32(uid, geteuid(), getegid(), + uid, gid, pid, pid, &tid)) == NULL) { + fprintf(stderr, "login: Audit Error: au_to_subject32() failed\n"); + exit(1); + } + au_write(aufd, tok); + + if((tok = au_to_return32(0, 0)) == NULL) { + fprintf(stderr, "login: Audit Error: au_to_return32() failed\n"); + exit(1); + } + au_write(aufd, tok); + + if(au_close(aufd, 1, AUE_login) == -1) { + fprintf(stderr, "login: Audit Record was not committed.\n"); + exit(1); + } +} + +/* + * The following tokens are included in the audit record for successful login attempts + * header + * subject + * text + * return + */ +void au_fail(char *errmsg, int na) +{ + token_t *tok; + int aufd; + long au_cond; + uid_t uid; + gid_t gid; + pid_t pid = getpid(); + + /* If we are not auditing, don't cut an audit record; just return */ + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + fprintf(stderr, "login: Could not determine audit condition\n"); + exit(1); + } + if (au_cond == AUC_NOAUDIT) + return; + + if((aufd = au_open()) == -1) { + fprintf(stderr, "login: Audit Error: au_open() failed\n"); + exit(1); + } + + if(na) { + /* Non attributable event */ + /* Assuming that login is not called within a users' session => auid,asid == -1 */ + if((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1, + pid, -1, &tid)) == NULL) { + + fprintf(stderr, "login: Audit Error: au_to_subject32() failed\n"); + exit(1); + } + } + else { + /* we know the subject -- so use its value instead */ + uid = pwd->pw_uid; + gid = pwd->pw_gid; + if((tok = au_to_subject32(uid, geteuid(), getegid(), + uid, gid, pid, pid, &tid)) == NULL) { + fprintf(stderr, "login: Audit Error: au_to_subject32() failed\n"); + exit(1); + } + } + au_write(aufd, tok); + + /* Include the error message */ + if((tok = au_to_text(errmsg)) == NULL) { + fprintf(stderr, "login: Audit Error: au_to_text() failed\n"); + exit(1); + } + au_write(aufd, tok); + + if((tok = au_to_return32(1, errno)) == NULL) { + fprintf(stderr, "login: Audit Error: au_to_return32() failed\n"); + exit(1); + } + au_write(aufd, tok); + + if(au_close(aufd, 1, AUE_login) == -1) { + fprintf(stderr, "login: Audit Error: au_close() was not committed\n"); + exit(1); + } +} + void getloginname() { @@ -642,6 +836,8 @@ checknologin() if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) (void)write(fileno(stdout), tbuf, nchars); + + au_fail("No login", 0); sleepexit(0); } } diff --git a/mach_init.tproj/Makefile b/mach_init.tproj/Makefile index 57431eb..6bb2bb1 100644 --- a/mach_init.tproj/Makefile +++ b/mach_init.tproj/Makefile @@ -26,7 +26,7 @@ MAKEFILE = tool.make NEXTSTEP_INSTALLDIR = /sbin WINDOWS_INSTALLDIR = /sbin PDO_UNIX_INSTALLDIR = /sbin -LIBS = +LIBS = -lbsm DEBUG_LIBS = $(LIBS) PROF_LIBS = $(LIBS) diff --git a/mach_init.tproj/PB.project b/mach_init.tproj/PB.project index c099428..0fec588 100644 --- a/mach_init.tproj/PB.project +++ b/mach_init.tproj/PB.project @@ -9,7 +9,7 @@ HEADERSEARCH = (); "H_FILES" = ("bootstrap_internal.h", "error_log.h", "lists.h"); "M_FILES" = (); - "OTHER_LIBS" = (); + "OTHER_LIBS" = (bsm); "OTHER_LINKED" = ("bootstrap.c", "error_log.c", "lists.c", "rpc_services.c"); "OTHER_SOURCES" = ( "Makefile.preamble", diff --git a/mach_init.tproj/bootstrap.c b/mach_init.tproj/bootstrap.c index adc03f8..81e49bc 100644 --- a/mach_init.tproj/bootstrap.c +++ b/mach_init.tproj/bootstrap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -55,6 +55,10 @@ #import #import #import +#import + +#include +#include #import "bootstrap.h" @@ -74,7 +78,8 @@ const char *program_name; /* our name for error messages */ #define INIT_PATH "/sbin/init" /* default init path */ #endif INIT_PATH -uid_t inherited_uid; +uid_t inherited_uid = 0; +auditinfo_t inherited_audit; mach_port_t inherited_bootstrap_port = MACH_PORT_NULL; boolean_t forward_ok = FALSE; boolean_t shutdown_in_progress = FALSE; @@ -202,16 +207,6 @@ main(int argc, char * argv[]) pid = getpid(); if (pid == 1) { - close(0); - freopen("/dev/console", "r", stdin); - setbuf(stdin, NULL); - close(1); - freopen("/dev/console", "w", stdout); - setbuf(stdout, NULL); - close(2); - freopen("/dev/console", "w", stderr); - setbuf(stderr, NULL); - result = mach_port_allocate( mach_task_self(), MACH_PORT_RIGHT_RECEIVE, @@ -274,6 +269,14 @@ main(int argc, char * argv[]) bootstrap_port); if (result != KERN_SUCCESS) kern_fatal(result, "task_get_bootstrap_port"); + + close(0); + open("/dev/null", O_RDONLY, 0); + close(1); + open("/dev/null", O_WRONLY, 0); + close(2); + open("/dev/null", O_WRONLY, 0); + } else init_notify_port = MACH_PORT_NULL; @@ -330,6 +333,7 @@ main(int argc, char * argv[]) */ bootstrap_self = mach_task_self(); inherited_uid = getuid(); + getaudit(&inherited_audit); init_lists(); init_ports(); @@ -406,8 +410,9 @@ main(int argc, char * argv[]) setenv("PATH", _PATH_STDPATH, 1); init_errlog(pid == 0); /* are we a daemon? */ - notice("Started with uid=%d%s%s%s", + notice("Started with uid=%d audit-uid=%d%s%s%s", inherited_uid, + inherited_audit.ai_auid, (register_self) ? " registered-as=" : "", (register_self) ? register_name : "", (debugging) ? " in debug-mode" : ""); @@ -791,6 +796,30 @@ exec_server(server_t *serverp) argv = argvize(serverp->cmd); close_errlog(); + /* + * Set up the audit state for the user (if necessesary). + */ + if (inherited_uid == 0 && + (serverp->auinfo.ai_auid != inherited_uid || + serverp->auinfo.ai_asid != inherited_audit.ai_asid)) { + struct passwd *pwd = NULL; + + pwd = getpwuid(serverp->auinfo.ai_auid); + if (pwd == NULL) { + unix_fatal("Disabled server %x bootstrap %x: \"%s\": getpwuid(%d) failed", + serverp->port, serverp->bootstrap->bootstrap_port, + serverp->cmd, serverp->auinfo.ai_auid); + + } else if (au_user_mask(pwd->pw_name, &serverp->auinfo.ai_mask) != 0) { + unix_fatal("Disabled server %x bootstrap %x: \"%s\": au_user_mask(%s) failed", + serverp->port, serverp->bootstrap->bootstrap_port, + serverp->cmd, pwd->pw_name); + } else if (setaudit(&serverp->auinfo) != 0) + unix_fatal("Disabled server %x bootstrap %x: \"%s\": setaudit()", + serverp->port, serverp->bootstrap->bootstrap_port, + serverp->cmd); + } + if (serverp->uid != inherited_uid) if (setuid(serverp->uid) < 0) unix_fatal("Disabled server %x bootstrap %x: \"%s\": setuid(%d)", diff --git a/mach_init.tproj/bootstrap.defs b/mach_init.tproj/bootstrap.defs index 55c0b32..de1819d 100644 --- a/mach_init.tproj/bootstrap.defs +++ b/mach_init.tproj/bootstrap.defs @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -140,7 +140,7 @@ routine bootstrap_create_server( server_cmd : cmd_t; server_uid : integer_t; on_demand : boolean_t; - ServerSecToken token : security_token_t; + ServerAuditToken token : audit_token_t; out server_port : mach_port_make_send_t); /* diff --git a/mach_init.tproj/lists.c b/mach_init.tproj/lists.c index 770ba82..646fe83 100644 --- a/mach_init.tproj/lists.c +++ b/mach_init.tproj/lists.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -35,6 +35,8 @@ #import #import +#import + #import "bootstrap_internal.h" #import "lists.h" #import "error_log.h" @@ -75,7 +77,8 @@ new_server( bootstrap_info_t *bootstrap, const char *cmd, int uid, - servertype_t servertype) + servertype_t servertype, + auditinfo_t auinfo) { server_t *serverp; @@ -93,7 +96,9 @@ new_server( serverp->pid = NO_PID; serverp->task_port = MACH_PORT_NULL; + serverp->uid = uid; + serverp->auinfo = auinfo; serverp->port = MACH_PORT_NULL; serverp->servertype = servertype; diff --git a/mach_init.tproj/lists.h b/mach_init.tproj/lists.h index f09942e..23e8ce5 100644 --- a/mach_init.tproj/lists.h +++ b/mach_init.tproj/lists.h @@ -34,6 +34,8 @@ #import #import +#import + #ifndef NULL #define NULL ((void *)0) #endif NULL @@ -87,14 +89,15 @@ struct server { server_t *next; /* list of all servers */ server_t *prev; servertype_t servertype; - cmd_t cmd; /* server command to exec */ - int uid; /* uid to exec server with */ + int uid; /* uid to exec server with */ + auditinfo_t auinfo; /* server's audit information */ mach_port_t port; /* server's priv bootstrap port */ mach_port_t task_port; /* server's task port */ pid_t pid; /* server's pid */ int activity; /* count of checkins/registers this instance */ int active_services;/* count of active services */ bootstrap_info_t *bootstrap; /* bootstrap context */ + cmd_t cmd; /* server command to exec */ }; #define NO_PID (-1) @@ -105,7 +108,8 @@ extern server_t *new_server( bootstrap_info_t *bootstrap, const char *cmd, int uid, - servertype_t servertype); + servertype_t servertype, + auditinfo_t auinfo); extern service_t *new_service( bootstrap_info_t *bootstrap, diff --git a/mach_init.tproj/rpc_services.c b/mach_init.tproj/rpc_services.c index eba0cc2..69168ef 100644 --- a/mach_init.tproj/rpc_services.c +++ b/mach_init.tproj/rpc_services.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -32,6 +32,9 @@ #import #import +#import +#import + #import "bootstrap_internal.h" #import "error_log.h" #import "lists.h" @@ -74,12 +77,15 @@ x_bootstrap_create_server( cmd_t server_cmd, int server_uid, boolean_t on_demand, - security_token_t sectoken, + audit_token_t client_audit_token, mach_port_t *server_portp) { server_t *serverp; + struct auditinfo audit_info; bootstrap_info_t *bootstrap; + uid_t client_euid; + bootstrap = lookup_bootstrap_by_port(bootstrap_port); debug("Server create attempt: \"%s\" bootstrap %x", server_cmd, bootstrap_port); @@ -91,17 +97,29 @@ x_bootstrap_create_server( return BOOTSTRAP_NOT_PRIVILEGED; } - /* only same uid (or root client) */ - if (sectoken.val[0] && sectoken.val[0] != server_uid) { - notice("Server create: \"%s\": invalid security token (%d != %d)", - server_cmd, sectoken.val[0], server_uid); + /* get the identity of the requestor and set up audit_info of server */ + audit_token_to_au32(client_audit_token, + &audit_info.ai_auid, + &client_euid, + NULL /* egid */, + NULL /* ruid */, + NULL /* rgid */, + NULL /* pid */, + &audit_info.ai_asid, + &audit_info.ai_termid); + + if (client_euid != 0 && client_euid != server_uid) { + notice("Server create: \"%s\": insufficient privilege for specified uid (euid-%d != requested-%d)", + server_cmd, client_euid, server_uid); return BOOTSTRAP_NOT_PRIVILEGED; } + serverp = new_server( bootstrap, server_cmd, server_uid, - (on_demand) ? DEMAND : RESTARTABLE); + (on_demand) ? DEMAND : RESTARTABLE, + audit_info); setup_server(serverp); info("New server %x in bootstrap %x: \"%s\"", diff --git a/shutdown.tproj/Makefile b/shutdown.tproj/Makefile index 73d25a8..e402bec 100644 --- a/shutdown.tproj/Makefile +++ b/shutdown.tproj/Makefile @@ -1,5 +1,5 @@ # -# Generated by the NeXT Project Builder. +# Generated by the Apple Project Builder. # # NOTE: Do NOT change this file -- Project Builder maintains it. # @@ -26,7 +26,7 @@ MAKEFILE = tool.make NEXTSTEP_INSTALLDIR = /sbin WINDOWS_INSTALLDIR = /sbin PDO_UNIX_INSTALLDIR = /sbin -LIBS = +LIBS = -lbsm DEBUG_LIBS = $(LIBS) PROF_LIBS = $(LIBS) diff --git a/shutdown.tproj/PB.project b/shutdown.tproj/PB.project index 87cbc03..920e663 100644 --- a/shutdown.tproj/PB.project +++ b/shutdown.tproj/PB.project @@ -2,31 +2,37 @@ APPCLASS = NSApplication; FILESTABLE = { FRAMEWORKS = (); - H_FILES = (pathnames.h); - M_FILES = (); - OTHER_LIBS = (); - OTHER_LINKED = (shutdown.c); - OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, shutdown.8); - PRECOMPILED_HEADERS = (); - PROJECT_HEADERS = (); - PUBLIC_HEADERS = (); + "H_FILES" = ("pathnames.h"); + "M_FILES" = (); + "OTHER_LIBS" = (bsm); + "OTHER_LINKED" = ("shutdown.c"); + "OTHER_SOURCES" = ( + "Makefile.preamble", + Makefile, + "Makefile.postamble", + "Makefile.dist", + "shutdown.8" + ); + "PRECOMPILED_HEADERS" = (); + "PROJECT_HEADERS" = (); + "PUBLIC_HEADERS" = (); SUBPROJECTS = (); }; LANGUAGE = English; - LOCALIZABLE_FILES = {}; - NEXTSTEP_INSTALLDIR = /sbin; - NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; - NEXTSTEP_MAINNIB = shutdown; - NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; - PDO_UNIX_INSTALLDIR = /sbin; - PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; - PDO_UNIX_MAINNIB = shutdown; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + "LOCALIZABLE_FILES" = {}; + "NEXTSTEP_INSTALLDIR" = "/sbin"; + "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac"; + "NEXTSTEP_MAINNIB" = shutdown; + "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc"; + "PDO_UNIX_INSTALLDIR" = "/sbin"; + "PDO_UNIX_JAVA_COMPILER" = "$(NEXTDEV_BIN)/javac"; + "PDO_UNIX_MAINNIB" = shutdown; + "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc"; PROJECTNAME = shutdown; PROJECTTYPE = Tool; - PROJECTVERSION = 2.8; - WINDOWS_INSTALLDIR = /sbin; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_MAINNIB = shutdown; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; + PROJECTVERSION = "2.8"; + "WINDOWS_INSTALLDIR" = "/sbin"; + "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe"; + "WINDOWS_MAINNIB" = shutdown; + "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc"; } diff --git a/shutdown.tproj/shutdown.c b/shutdown.tproj/shutdown.c index 3b1b795..2bd4045 100644 --- a/shutdown.tproj/shutdown.c +++ b/shutdown.tproj/shutdown.c @@ -61,6 +61,11 @@ static const char rcsid[] = #include #include +#include +#include +#include + + #include "pathnames.h" #ifdef __APPLE__ @@ -110,6 +115,7 @@ void nolog(void); void timeout(int); void timewarn(int); void usage(const char *); +int audit_shutdown(int); int main(argc, argv) @@ -222,7 +228,9 @@ main(argc, argv) if (!(whom = getlogin())) whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; + #ifdef DEBUG + audit_shutdown(0); (void)putc('\n', stdout); #else (void)setpriority(PRIO_PROCESS, 0, PRIO_MIN); @@ -230,11 +238,15 @@ main(argc, argv) int forkpid; forkpid = fork(); - if (forkpid == -1) + if (forkpid == -1) { + audit_shutdown(1); err(1, "fork"); - if (forkpid) + } + if (forkpid) { errx(0, "[pid %d]", forkpid); + } } + audit_shutdown(0); setsid(); #endif openlog("shutdown", LOG_CONS, LOG_AUTH); @@ -557,3 +569,50 @@ usage(cp) " time [warning-message ...]\n"); exit(1); } + +/* + * The following tokens are included in the audit record for shutdown + * header + * subject + * return + */ +int audit_shutdown(int exitstatus) +{ + int aufd; + token_t *tok; + long au_cond; + + /* If we are not auditing, don't cut an audit record; just return */ + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + fprintf(stderr, "shutdown: Could not determine audit condition\n"); + return 0; + } + if (au_cond == AUC_NOAUDIT) + return 0; + + if((aufd = au_open()) == -1) { + fprintf(stderr, "shutdown: Audit Error: au_open() failed\n"); + exit(1); + } + + /* The subject that performed the operation */ + if((tok = au_to_me()) == NULL) { + fprintf(stderr, "shutdown: Audit Error: au_to_me() failed\n"); + exit(1); + } + au_write(aufd, tok); + + /* success and failure status */ + if((tok = au_to_return32(exitstatus, errno)) == NULL) { + fprintf(stderr, "shutdown: Audit Error: au_to_return32() failed\n"); + exit(1); + } + au_write(aufd, tok); + + if(au_close(aufd, 1, AUE_shutdown) == -1) { + fprintf(stderr, "shutdown: Audit Error: au_close() failed\n"); + exit(1); + } + return 1; +} + -- 2.47.2