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