1185573Srwatson/*- 2191273Srwatson * Copyright (c) 2004-2009 Apple Inc. 3155131Srwatson * All rights reserved. 4155131Srwatson * 5155131Srwatson * Redistribution and use in source and binary forms, with or without 6155131Srwatson * modification, are permitted provided that the following conditions 7155131Srwatson * are met: 8155131Srwatson * 1. Redistributions of source code must retain the above copyright 9155131Srwatson * notice, this list of conditions and the following disclaimer. 10155131Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11155131Srwatson * notice, this list of conditions and the following disclaimer in the 12155131Srwatson * documentation and/or other materials provided with the distribution. 13185573Srwatson * 3. Neither the name of Apple Inc. ("Apple") nor the names of 14155131Srwatson * its contributors may be used to endorse or promote products derived 15155131Srwatson * from this software without specific prior written permission. 16155131Srwatson * 17155131Srwatson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 18155131Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19155131Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20155131Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 21155131Srwatson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22155131Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23155131Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24155131Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25155131Srwatson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26155131Srwatson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27155131Srwatson * POSSIBILITY OF SUCH DAMAGE. 28155131Srwatson * 29191273Srwatson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_notify.c#17 $ 30155131Srwatson */ 31155131Srwatson 32155131Srwatson/* 33155131Srwatson * Based on sample code from Marc Majka. 34155131Srwatson */ 35156283Srwatson#include <sys/types.h> 36156283Srwatson 37156283Srwatson#include <config/config.h> 38156283Srwatson#ifdef HAVE_FULL_QUEUE_H 39156283Srwatson#include <sys/queue.h> 40156283Srwatson#else /* !HAVE_FULL_QUEUE_H */ 41156283Srwatson#include <compat/queue.h> 42156283Srwatson#endif /* !HAVE_FULL_QUEUE_H */ 43156283Srwatson 44156283Srwatson#include <bsm/audit_internal.h> 45155131Srwatson#include <bsm/libbsm.h> 46155131Srwatson 47156283Srwatson#include <errno.h> 48159985Srwatson#include <inttypes.h> 49156283Srwatson#include <stdarg.h> 50156283Srwatson#include <string.h> 51156283Srwatson#include <syslog.h> 52156283Srwatson 53156283Srwatson 54155518Srwatson#ifdef __APPLE__ 55155518Srwatson#include <notify.h> 56155131Srwatson/* If 1, assumes a kernel that sends the right notification. */ 57155131Srwatson#define AUDIT_NOTIFICATION_ENABLED 1 58155131Srwatson 59155131Srwatson#if AUDIT_NOTIFICATION_ENABLED 60155131Srwatsonstatic int token = 0; 61155131Srwatson#endif /* AUDIT_NOTIFICATION_ENABLED */ 62155131Srwatson 63191273Srwatsonstatic int au_cond = AUC_UNSET; /* <bsm/audit.h> */ 64155131Srwatson 65155131Srwatsonuint32_t 66155131Srwatsonau_notify_initialize(void) 67155131Srwatson{ 68155131Srwatson#if AUDIT_NOTIFICATION_ENABLED 69168777Srwatson uint32_t status; 70168777Srwatson int ignore_first; 71155131Srwatson 72155131Srwatson status = notify_register_check(__BSM_INTERNAL_NOTIFY_KEY, &token); 73155131Srwatson if (status != NOTIFY_STATUS_OK) 74155131Srwatson return (status); 75155131Srwatson status = notify_check(token, &ignore_first); 76155131Srwatson if (status != NOTIFY_STATUS_OK) 77155131Srwatson return (status); 78155131Srwatson#endif 79155131Srwatson 80191273Srwatson if (audit_get_cond(&au_cond) != 0) { 81155131Srwatson syslog(LOG_ERR, "Initial audit status check failed (%s)", 82155131Srwatson strerror(errno)); 83155131Srwatson if (errno == ENOSYS) /* auditon() unimplemented. */ 84155131Srwatson return (AU_UNIMPL); 85155131Srwatson return (NOTIFY_STATUS_FAILED); /* Is there a better code? */ 86155131Srwatson } 87155131Srwatson return (NOTIFY_STATUS_OK); 88155131Srwatson} 89155131Srwatson 90155131Srwatsonint 91155131Srwatsonau_notify_terminate(void) 92155131Srwatson{ 93155131Srwatson 94155131Srwatson#if AUDIT_NOTIFICATION_ENABLED 95155131Srwatson return ((notify_cancel(token) == NOTIFY_STATUS_OK) ? 0 : -1); 96155131Srwatson#else 97155131Srwatson return (0); 98155131Srwatson#endif 99155131Srwatson} 100155131Srwatson 101155131Srwatson/* 102155131Srwatson * On error of any notify(3) call, reset 'au_cond' to ensure we re-run 103155131Srwatson * au_notify_initialize() next time 'round--but assume auditing is on. This 104155131Srwatson * is a slight performance hit if auditing is off, but at least the system 105155131Srwatson * will behave correctly. The notification calls are unlikely to fail, 106155131Srwatson * anyway. 107155131Srwatson */ 108155131Srwatsonint 109155131Srwatsonau_get_state(void) 110155131Srwatson{ 111155131Srwatson#if AUDIT_NOTIFICATION_ENABLED 112168777Srwatson int did_notify; 113155131Srwatson#endif 114155131Srwatson int status; 115155131Srwatson 116155131Srwatson /* 117155131Srwatson * Don't make the client initialize this set of routines, but take the 118155131Srwatson * slight performance hit by checking ourselves every time. 119155131Srwatson */ 120155131Srwatson if (au_cond == AUC_UNSET) { 121155131Srwatson status = au_notify_initialize(); 122155131Srwatson if (status != NOTIFY_STATUS_OK) { 123155131Srwatson if (status == AU_UNIMPL) 124155131Srwatson return (AU_UNIMPL); 125155131Srwatson return (AUC_AUDITING); 126155131Srwatson } else 127155131Srwatson return (au_cond); 128155131Srwatson } 129155131Srwatson#if AUDIT_NOTIFICATION_ENABLED 130155131Srwatson status = notify_check(token, &did_notify); 131155131Srwatson if (status != NOTIFY_STATUS_OK) { 132155131Srwatson au_cond = AUC_UNSET; 133155131Srwatson return (AUC_AUDITING); 134155131Srwatson } 135155131Srwatson 136155131Srwatson if (did_notify == 0) 137155131Srwatson return (au_cond); 138155131Srwatson#endif 139155131Srwatson 140191273Srwatson if (audit_get_cond(&au_cond) != 0) { 141155131Srwatson /* XXX Reset au_cond to AUC_UNSET? */ 142155131Srwatson syslog(LOG_ERR, "Audit status check failed (%s)", 143155131Srwatson strerror(errno)); 144155131Srwatson if (errno == ENOSYS) /* Function unimplemented. */ 145155131Srwatson return (AU_UNIMPL); 146155131Srwatson return (errno); 147155131Srwatson } 148155131Srwatson 149155131Srwatson switch (au_cond) { 150155131Srwatson case AUC_NOAUDIT: /* Auditing suspended. */ 151155131Srwatson case AUC_DISABLED: /* Auditing shut off. */ 152155131Srwatson return (AUC_NOAUDIT); 153155131Srwatson 154155131Srwatson case AUC_UNSET: /* Uninitialized; shouldn't get here. */ 155155131Srwatson case AUC_AUDITING: /* Audit on. */ 156155131Srwatson default: 157155131Srwatson return (AUC_AUDITING); 158155131Srwatson } 159155131Srwatson} 160155518Srwatson#endif /* !__APPLE__ */ 161155131Srwatson 162155518Srwatsonint 163155518Srwatsoncannot_audit(int val __unused) 164155518Srwatson{ 165155518Srwatson#ifdef __APPLE__ 166155518Srwatson return (!(au_get_state() == AUC_AUDITING)); 167155518Srwatson#else 168191273Srwatson int cond; 169155518Srwatson 170191273Srwatson if (audit_get_cond(&cond) != 0) { 171155518Srwatson if (errno != ENOSYS) { 172155518Srwatson syslog(LOG_ERR, "Audit status check failed (%s)", 173155518Srwatson strerror(errno)); 174155518Srwatson } 175155518Srwatson return (1); 176155518Srwatson } 177191273Srwatson if (cond == AUC_NOAUDIT || cond == AUC_DISABLED) 178155518Srwatson return (1); 179155518Srwatson return (0); 180155518Srwatson#endif /* !__APPLE__ */ 181155518Srwatson} 182