bsm_wrappers.c revision 155518
1155131Srwatson/* 2155131Srwatson * Copyright (c) 2004 Apple Computer, 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. 13155131Srwatson * 3. Neither the name of Apple Computer, 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 * 29155518Srwatson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_wrappers.c#16 $ 30155131Srwatson */ 31155131Srwatson 32155518Srwatson#ifdef __APPLE__ 33155518Srwatson#define _SYS_AUDIT_H /* Prevent include of sys/audit.h. */ 34155518Srwatson#endif 35155518Srwatson 36155131Srwatson#include <sys/param.h> 37155131Srwatson#include <sys/stat.h> 38155131Srwatson#include <sys/sysctl.h> 39155131Srwatson 40155131Srwatson#include <bsm/libbsm.h> 41155131Srwatson 42155131Srwatson#include <unistd.h> 43155131Srwatson#include <syslog.h> 44155131Srwatson#include <string.h> 45155131Srwatson#include <errno.h> 46155131Srwatson 47155131Srwatson/* These are not advertised in libbsm.h */ 48155131Srwatsonint audit_set_terminal_port(dev_t *p); 49155131Srwatsonint audit_set_terminal_host(uint32_t *m); 50155131Srwatson 51155131Srwatsonint 52155131Srwatsonaudit_set_terminal_port(dev_t *p) 53155131Srwatson{ 54155131Srwatson struct stat st; 55155131Srwatson 56155131Srwatson if (p == NULL) 57155131Srwatson return (kAUBadParamErr); 58155131Srwatson 59155131Srwatson *p = NODEV; 60155131Srwatson 61155131Srwatson /* for /usr/bin/login, try fstat() first */ 62155131Srwatson if (fstat(STDIN_FILENO, &st) != 0) { 63155131Srwatson if (errno != EBADF) { 64155131Srwatson syslog(LOG_ERR, "fstat() failed (%s)", 65155131Srwatson strerror(errno)); 66155131Srwatson return (kAUStatErr); 67155131Srwatson } 68155131Srwatson if (stat("/dev/console", &st) != 0) { 69155131Srwatson syslog(LOG_ERR, "stat() failed (%s)", 70155131Srwatson strerror(errno)); 71155131Srwatson return (kAUStatErr); 72155131Srwatson } 73155131Srwatson } 74155131Srwatson *p = st.st_rdev; 75155131Srwatson return (kAUNoErr); 76155131Srwatson} 77155131Srwatson 78155131Srwatsonint 79155131Srwatsonaudit_set_terminal_host(uint32_t *m) 80155131Srwatson{ 81155131Srwatson int name[2] = { CTL_KERN, KERN_HOSTID }; 82155131Srwatson size_t len; 83155131Srwatson 84155131Srwatson if (m == NULL) 85155131Srwatson return (kAUBadParamErr); 86155131Srwatson *m = 0; 87155131Srwatson len = sizeof(*m); 88155131Srwatson if (sysctl(name, 2, m, &len, NULL, 0) != 0) { 89155131Srwatson syslog(LOG_ERR, "sysctl() failed (%s)", strerror(errno)); 90155131Srwatson return (kAUSysctlErr); 91155131Srwatson } 92155131Srwatson return (kAUNoErr); 93155131Srwatson} 94155131Srwatson 95155131Srwatsonint 96155131Srwatsonaudit_set_terminal_id(au_tid_t *tid) 97155131Srwatson{ 98155131Srwatson int ret; 99155131Srwatson 100155131Srwatson if (tid == NULL) 101155131Srwatson return (kAUBadParamErr); 102155131Srwatson if ((ret = audit_set_terminal_port(&tid->port)) != kAUNoErr) 103155131Srwatson return (ret); 104155131Srwatson return (audit_set_terminal_host(&tid->machine)); 105155131Srwatson} 106155131Srwatson 107155131Srwatson/* 108155131Srwatson * This is OK for those callers who have only one token to write. If you have 109155131Srwatson * multiple tokens that logically form part of the same audit record, you need 110155131Srwatson * to use the existing au_open()/au_write()/au_close() API: 111155131Srwatson * 112155131Srwatson * aufd = au_open(); 113155131Srwatson * tok = au_to_random_token_1(...); 114155131Srwatson * au_write(aufd, tok); 115155131Srwatson * tok = au_to_random_token_2(...); 116155131Srwatson * au_write(aufd, tok); 117155131Srwatson * ... 118155131Srwatson * au_close(aufd, 1, AUE_your_event_type); 119155131Srwatson * 120155131Srwatson * Assumes, like all wrapper calls, that the caller has previously checked 121155131Srwatson * that auditing is enabled via the audit_get_state() call. 122155131Srwatson * 123155131Srwatson * XXX: Should be more robust against bad arguments. 124155131Srwatson */ 125155131Srwatsonint 126155131Srwatsonaudit_write(short event_code, token_t *subject, token_t *misctok, char retval, 127155131Srwatson int errcode) 128155131Srwatson{ 129155131Srwatson int aufd; 130155131Srwatson char *func = "audit_write()"; 131155131Srwatson token_t *rettok; 132155131Srwatson 133155131Srwatson if ((aufd = au_open()) == -1) { 134155131Srwatson au_free_token(subject); 135155131Srwatson au_free_token(misctok); 136155131Srwatson syslog(LOG_ERR, "%s: au_open() failed", func); 137155131Srwatson return (kAUOpenErr); 138155131Srwatson } 139155131Srwatson 140155131Srwatson /* Save subject. */ 141155131Srwatson if (subject && au_write(aufd, subject) == -1) { 142155131Srwatson au_free_token(subject); 143155131Srwatson au_free_token(misctok); 144155131Srwatson (void)au_close(aufd, 0, event_code); 145155131Srwatson syslog(LOG_ERR, "%s: write of subject failed", func); 146155131Srwatson return (kAUWriteSubjectTokErr); 147155131Srwatson } 148155131Srwatson 149155131Srwatson /* Save the event-specific token. */ 150155131Srwatson if (misctok && au_write(aufd, misctok) == -1) { 151155131Srwatson au_free_token(misctok); 152155131Srwatson (void)au_close(aufd, 0, event_code); 153155131Srwatson syslog(LOG_ERR, "%s: write of caller token failed", func); 154155131Srwatson return (kAUWriteCallerTokErr); 155155131Srwatson } 156155131Srwatson 157155131Srwatson /* Tokenize and save the return value. */ 158155131Srwatson if ((rettok = au_to_return32(retval, errcode)) == NULL) { 159155131Srwatson (void)au_close(aufd, 0, event_code); 160155131Srwatson syslog(LOG_ERR, "%s: au_to_return32() failed", func); 161155131Srwatson return (kAUMakeReturnTokErr); 162155131Srwatson } 163155131Srwatson 164155131Srwatson if (au_write(aufd, rettok) == -1) { 165155131Srwatson au_free_token(rettok); 166155131Srwatson (void)au_close(aufd, 0, event_code); 167155131Srwatson syslog(LOG_ERR, "%s: write of return code failed", func); 168155131Srwatson return (kAUWriteReturnTokErr); 169155131Srwatson } 170155131Srwatson 171155131Srwatson /* 172155131Srwatson * au_close()'s second argument is "keep": if keep == 0, the record is 173155131Srwatson * discarded. We assume the caller wouldn't have bothered with this 174155131Srwatson * function if it hadn't already decided to keep the record. 175155131Srwatson */ 176155131Srwatson if (au_close(aufd, 1, event_code) < 0) { 177155131Srwatson syslog(LOG_ERR, "%s: au_close() failed", func); 178155131Srwatson return (kAUCloseErr); 179155131Srwatson } 180155131Srwatson 181155131Srwatson return (kAUNoErr); 182155131Srwatson} 183155131Srwatson 184155131Srwatson/* 185155131Srwatson * Same caveats as audit_write(). In addition, this function explicitly 186155131Srwatson * assumes success; use audit_write_failure() on error. 187155131Srwatson */ 188155131Srwatsonint 189155131Srwatsonaudit_write_success(short event_code, token_t *tok, au_id_t auid, uid_t euid, 190155131Srwatson gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, 191155131Srwatson au_tid_t *tid) 192155131Srwatson{ 193155131Srwatson char *func = "audit_write_success()"; 194155131Srwatson token_t *subject = NULL; 195155131Srwatson 196155131Srwatson /* Tokenize and save subject. */ 197155131Srwatson subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, 198155131Srwatson tid); 199155131Srwatson if (subject == NULL) { 200155131Srwatson syslog(LOG_ERR, "%s: au_to_subject32() failed", func); 201155131Srwatson return kAUMakeSubjectTokErr; 202155131Srwatson } 203155131Srwatson 204155131Srwatson return (audit_write(event_code, subject, tok, 0, 0)); 205155131Srwatson} 206155131Srwatson 207155131Srwatson/* 208155131Srwatson * Same caveats as audit_write(). In addition, this function explicitly 209155131Srwatson * assumes success; use audit_write_failure_self() on error. 210155131Srwatson */ 211155131Srwatsonint 212155131Srwatsonaudit_write_success_self(short event_code, token_t *tok) 213155131Srwatson{ 214155131Srwatson token_t *subject; 215155131Srwatson char *func = "audit_write_success_self()"; 216155131Srwatson 217155131Srwatson if ((subject = au_to_me()) == NULL) { 218155131Srwatson syslog(LOG_ERR, "%s: au_to_me() failed", func); 219155131Srwatson return (kAUMakeSubjectTokErr); 220155131Srwatson } 221155131Srwatson 222155131Srwatson return (audit_write(event_code, subject, tok, 0, 0)); 223155131Srwatson} 224155131Srwatson 225155131Srwatson/* 226155131Srwatson * Same caveats as audit_write(). In addition, this function explicitly 227155131Srwatson * assumes failure; use audit_write_success() otherwise. 228155131Srwatson * 229155131Srwatson * XXX This should let the caller pass an error return value rather than 230155131Srwatson * hard-coding -1. 231155131Srwatson */ 232155131Srwatsonint 233155131Srwatsonaudit_write_failure(short event_code, char *errmsg, int errcode, au_id_t auid, 234155131Srwatson uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, 235155131Srwatson au_tid_t *tid) 236155131Srwatson{ 237155131Srwatson char *func = "audit_write_failure()"; 238155131Srwatson token_t *subject, *errtok; 239155131Srwatson 240155131Srwatson subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, tid); 241155131Srwatson if (subject == NULL) { 242155131Srwatson syslog(LOG_ERR, "%s: au_to_subject32() failed", func); 243155131Srwatson return (kAUMakeSubjectTokErr); 244155131Srwatson } 245155131Srwatson 246155131Srwatson /* tokenize and save the error message */ 247155131Srwatson if ((errtok = au_to_text(errmsg)) == NULL) { 248155131Srwatson au_free_token(subject); 249155131Srwatson syslog(LOG_ERR, "%s: au_to_text() failed", func); 250155131Srwatson return (kAUMakeTextTokErr); 251155131Srwatson } 252155131Srwatson 253155131Srwatson return (audit_write(event_code, subject, errtok, -1, errcode)); 254155131Srwatson} 255155131Srwatson 256155131Srwatson/* 257155131Srwatson * Same caveats as audit_write(). In addition, this function explicitly 258155131Srwatson * assumes failure; use audit_write_success_self() otherwise. 259155131Srwatson * 260155131Srwatson * XXX This should let the caller pass an error return value rather than 261155131Srwatson * hard-coding -1. 262155131Srwatson */ 263155131Srwatsonint 264155131Srwatsonaudit_write_failure_self(short event_code, char *errmsg, int errret) 265155131Srwatson{ 266155131Srwatson char *func = "audit_write_failure_self()"; 267155131Srwatson token_t *subject, *errtok; 268155131Srwatson 269155131Srwatson if ((subject = au_to_me()) == NULL) { 270155131Srwatson syslog(LOG_ERR, "%s: au_to_me() failed", func); 271155131Srwatson return (kAUMakeSubjectTokErr); 272155131Srwatson } 273155131Srwatson /* tokenize and save the error message */ 274155131Srwatson if ((errtok = au_to_text(errmsg)) == NULL) { 275155131Srwatson au_free_token(subject); 276155131Srwatson syslog(LOG_ERR, "%s: au_to_text() failed", func); 277155131Srwatson return (kAUMakeTextTokErr); 278155131Srwatson } 279155131Srwatson return (audit_write(event_code, subject, errtok, -1, errret)); 280155131Srwatson} 281155131Srwatson 282155131Srwatson/* 283155131Srwatson * For auditing errors during login. Such errors are implicitly 284155131Srwatson * non-attributable (i.e., not ascribable to any user). 285155131Srwatson * 286155131Srwatson * Assumes, like all wrapper calls, that the caller has previously checked 287155131Srwatson * that auditing is enabled via the audit_get_state() call. 288155131Srwatson */ 289155131Srwatsonint 290155131Srwatsonaudit_write_failure_na(short event_code, char *errmsg, int errret, uid_t euid, 291155131Srwatson uid_t egid, pid_t pid, au_tid_t *tid) 292155131Srwatson{ 293155131Srwatson 294155131Srwatson return (audit_write_failure(event_code, errmsg, errret, -1, euid, 295155131Srwatson egid, -1, -1, pid, -1, tid)); 296155131Srwatson} 297155131Srwatson 298155131Srwatson/* END OF au_write() WRAPPERS */ 299155131Srwatson 300155131Srwatson#ifdef __APPLE__ 301155131Srwatsonvoid 302155131Srwatsonaudit_token_to_au32(audit_token_t atoken, uid_t *auidp, uid_t *euidp, 303155131Srwatson gid_t *egidp, uid_t *ruidp, gid_t *rgidp, pid_t *pidp, au_asid_t *asidp, 304155131Srwatson au_tid_t *tidp) 305155131Srwatson{ 306155131Srwatson 307155131Srwatson if (auidp != NULL) 308155131Srwatson *auidp = (uid_t)atoken.val[0]; 309155131Srwatson if (euidp != NULL) 310155131Srwatson *euidp = (uid_t)atoken.val[1]; 311155131Srwatson if (egidp != NULL) 312155131Srwatson *egidp = (gid_t)atoken.val[2]; 313155131Srwatson if (ruidp != NULL) 314155131Srwatson *ruidp = (uid_t)atoken.val[3]; 315155131Srwatson if (rgidp != NULL) 316155131Srwatson *rgidp = (gid_t)atoken.val[4]; 317155131Srwatson if (pidp != NULL) 318155131Srwatson *pidp = (pid_t)atoken.val[5]; 319155131Srwatson if (asidp != NULL) 320155131Srwatson *asidp = (au_asid_t)atoken.val[6]; 321155131Srwatson if (tidp != NULL) { 322155131Srwatson audit_set_terminal_host(&tidp->machine); 323155131Srwatson tidp->port = (dev_t)atoken.val[7]; 324155131Srwatson } 325155131Srwatson} 326155131Srwatson#endif /* !__APPLE__ */ 327