bsm_wrappers.c revision 155518
1249259Sdim/* 2249259Sdim * Copyright (c) 2004 Apple Computer, Inc. 3249259Sdim * All rights reserved. 4249259Sdim * 5249259Sdim * Redistribution and use in source and binary forms, with or without 6249259Sdim * modification, are permitted provided that the following conditions 7249259Sdim * are met: 8249259Sdim * 1. Redistributions of source code must retain the above copyright 9249259Sdim * notice, this list of conditions and the following disclaimer. 10249259Sdim * 2. Redistributions in binary form must reproduce the above copyright 11249259Sdim * notice, this list of conditions and the following disclaimer in the 12249259Sdim * documentation and/or other materials provided with the distribution. 13249259Sdim * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14249259Sdim * its contributors may be used to endorse or promote products derived 15249259Sdim * from this software without specific prior written permission. 16263508Sdim * 17249259Sdim * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 18249259Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19263508Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20263508Sdim * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 21263508Sdim * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22263508Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23249259Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24249259Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25249259Sdim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26263508Sdim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27249259Sdim * POSSIBILITY OF SUCH DAMAGE. 28249259Sdim * 29249259Sdim * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_wrappers.c#16 $ 30249259Sdim */ 31249259Sdim 32249259Sdim#ifdef __APPLE__ 33249259Sdim#define _SYS_AUDIT_H /* Prevent include of sys/audit.h. */ 34249259Sdim#endif 35249259Sdim 36249259Sdim#include <sys/param.h> 37249259Sdim#include <sys/stat.h> 38249259Sdim#include <sys/sysctl.h> 39249259Sdim 40249259Sdim#include <bsm/libbsm.h> 41249259Sdim 42249259Sdim#include <unistd.h> 43249259Sdim#include <syslog.h> 44249259Sdim#include <string.h> 45249259Sdim#include <errno.h> 46249259Sdim 47249259Sdim/* These are not advertised in libbsm.h */ 48249259Sdimint audit_set_terminal_port(dev_t *p); 49249259Sdimint audit_set_terminal_host(uint32_t *m); 50249259Sdim 51249259Sdimint 52249259Sdimaudit_set_terminal_port(dev_t *p) 53249259Sdim{ 54249259Sdim struct stat st; 55249259Sdim 56249259Sdim if (p == NULL) 57249259Sdim return (kAUBadParamErr); 58249259Sdim 59249259Sdim *p = NODEV; 60249259Sdim 61249259Sdim /* for /usr/bin/login, try fstat() first */ 62249259Sdim if (fstat(STDIN_FILENO, &st) != 0) { 63249259Sdim if (errno != EBADF) { 64249259Sdim syslog(LOG_ERR, "fstat() failed (%s)", 65249259Sdim strerror(errno)); 66249259Sdim return (kAUStatErr); 67249259Sdim } 68249259Sdim if (stat("/dev/console", &st) != 0) { 69249259Sdim syslog(LOG_ERR, "stat() failed (%s)", 70249259Sdim strerror(errno)); 71249259Sdim return (kAUStatErr); 72263508Sdim } 73263508Sdim } 74263508Sdim *p = st.st_rdev; 75263508Sdim return (kAUNoErr); 76263508Sdim} 77263508Sdim 78249259Sdimint 79249259Sdimaudit_set_terminal_host(uint32_t *m) 80249259Sdim{ 81249259Sdim int name[2] = { CTL_KERN, KERN_HOSTID }; 82263508Sdim size_t len; 83263508Sdim 84263508Sdim if (m == NULL) 85249259Sdim return (kAUBadParamErr); 86249259Sdim *m = 0; 87249259Sdim len = sizeof(*m); 88263508Sdim if (sysctl(name, 2, m, &len, NULL, 0) != 0) { 89249259Sdim syslog(LOG_ERR, "sysctl() failed (%s)", strerror(errno)); 90249259Sdim return (kAUSysctlErr); 91249259Sdim } 92249259Sdim return (kAUNoErr); 93249259Sdim} 94249259Sdim 95249259Sdimint 96249259Sdimaudit_set_terminal_id(au_tid_t *tid) 97263508Sdim{ 98249259Sdim int ret; 99263508Sdim 100263508Sdim if (tid == NULL) 101263508Sdim return (kAUBadParamErr); 102249259Sdim if ((ret = audit_set_terminal_port(&tid->port)) != kAUNoErr) 103263508Sdim return (ret); 104263508Sdim return (audit_set_terminal_host(&tid->machine)); 105263508Sdim} 106249259Sdim 107249259Sdim/* 108263508Sdim * This is OK for those callers who have only one token to write. If you have 109249259Sdim * multiple tokens that logically form part of the same audit record, you need 110249259Sdim * to use the existing au_open()/au_write()/au_close() API: 111249259Sdim * 112249259Sdim * aufd = au_open(); 113249259Sdim * tok = au_to_random_token_1(...); 114249259Sdim * au_write(aufd, tok); 115249259Sdim * tok = au_to_random_token_2(...); 116249259Sdim * au_write(aufd, tok); 117249259Sdim * ... 118249259Sdim * au_close(aufd, 1, AUE_your_event_type); 119249259Sdim * 120249259Sdim * Assumes, like all wrapper calls, that the caller has previously checked 121249259Sdim * that auditing is enabled via the audit_get_state() call. 122249259Sdim * 123249259Sdim * XXX: Should be more robust against bad arguments. 124249259Sdim */ 125249259Sdimint 126249259Sdimaudit_write(short event_code, token_t *subject, token_t *misctok, char retval, 127249259Sdim int errcode) 128249259Sdim{ 129249259Sdim int aufd; 130249259Sdim char *func = "audit_write()"; 131249259Sdim token_t *rettok; 132249259Sdim 133249259Sdim if ((aufd = au_open()) == -1) { 134249259Sdim au_free_token(subject); 135249259Sdim au_free_token(misctok); 136249259Sdim syslog(LOG_ERR, "%s: au_open() failed", func); 137249259Sdim return (kAUOpenErr); 138249259Sdim } 139249259Sdim 140249259Sdim /* Save subject. */ 141249259Sdim if (subject && au_write(aufd, subject) == -1) { 142249259Sdim au_free_token(subject); 143249259Sdim au_free_token(misctok); 144249259Sdim (void)au_close(aufd, 0, event_code); 145249259Sdim syslog(LOG_ERR, "%s: write of subject failed", func); 146249259Sdim return (kAUWriteSubjectTokErr); 147249259Sdim } 148249259Sdim 149249259Sdim /* Save the event-specific token. */ 150249259Sdim if (misctok && au_write(aufd, misctok) == -1) { 151249259Sdim au_free_token(misctok); 152249259Sdim (void)au_close(aufd, 0, event_code); 153249259Sdim syslog(LOG_ERR, "%s: write of caller token failed", func); 154249259Sdim return (kAUWriteCallerTokErr); 155249259Sdim } 156249259Sdim 157249259Sdim /* Tokenize and save the return value. */ 158249259Sdim if ((rettok = au_to_return32(retval, errcode)) == NULL) { 159249259Sdim (void)au_close(aufd, 0, event_code); 160249259Sdim syslog(LOG_ERR, "%s: au_to_return32() failed", func); 161249259Sdim return (kAUMakeReturnTokErr); 162249259Sdim } 163249259Sdim 164249259Sdim if (au_write(aufd, rettok) == -1) { 165249259Sdim au_free_token(rettok); 166249259Sdim (void)au_close(aufd, 0, event_code); 167249259Sdim syslog(LOG_ERR, "%s: write of return code failed", func); 168249259Sdim return (kAUWriteReturnTokErr); 169249259Sdim } 170249259Sdim 171249259Sdim /* 172249259Sdim * au_close()'s second argument is "keep": if keep == 0, the record is 173249259Sdim * discarded. We assume the caller wouldn't have bothered with this 174249259Sdim * function if it hadn't already decided to keep the record. 175249259Sdim */ 176249259Sdim if (au_close(aufd, 1, event_code) < 0) { 177249259Sdim syslog(LOG_ERR, "%s: au_close() failed", func); 178249259Sdim return (kAUCloseErr); 179249259Sdim } 180249259Sdim 181249259Sdim return (kAUNoErr); 182249259Sdim} 183249259Sdim 184249259Sdim/* 185249259Sdim * Same caveats as audit_write(). In addition, this function explicitly 186249259Sdim * assumes success; use audit_write_failure() on error. 187249259Sdim */ 188249259Sdimint 189249259Sdimaudit_write_success(short event_code, token_t *tok, au_id_t auid, uid_t euid, 190249259Sdim gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, 191249259Sdim au_tid_t *tid) 192249259Sdim{ 193249259Sdim char *func = "audit_write_success()"; 194249259Sdim token_t *subject = NULL; 195249259Sdim 196249259Sdim /* Tokenize and save subject. */ 197249259Sdim subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, 198263508Sdim tid); 199263508Sdim if (subject == NULL) { 200249259Sdim syslog(LOG_ERR, "%s: au_to_subject32() failed", func); 201249259Sdim return kAUMakeSubjectTokErr; 202249259Sdim } 203249259Sdim 204249259Sdim return (audit_write(event_code, subject, tok, 0, 0)); 205249259Sdim} 206249259Sdim 207249259Sdim/* 208249259Sdim * Same caveats as audit_write(). In addition, this function explicitly 209263508Sdim * assumes success; use audit_write_failure_self() on error. 210263508Sdim */ 211263508Sdimint 212249259Sdimaudit_write_success_self(short event_code, token_t *tok) 213249259Sdim{ 214263508Sdim token_t *subject; 215249259Sdim char *func = "audit_write_success_self()"; 216249259Sdim 217249259Sdim if ((subject = au_to_me()) == NULL) { 218249259Sdim syslog(LOG_ERR, "%s: au_to_me() failed", func); 219249259Sdim return (kAUMakeSubjectTokErr); 220249259Sdim } 221249259Sdim 222249259Sdim return (audit_write(event_code, subject, tok, 0, 0)); 223263508Sdim} 224263508Sdim 225263508Sdim/* 226263508Sdim * Same caveats as audit_write(). In addition, this function explicitly 227263508Sdim * assumes failure; use audit_write_success() otherwise. 228263508Sdim * 229263508Sdim * XXX This should let the caller pass an error return value rather than 230263508Sdim * hard-coding -1. 231263508Sdim */ 232263508Sdimint 233263508Sdimaudit_write_failure(short event_code, char *errmsg, int errcode, au_id_t auid, 234263508Sdim uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, 235263508Sdim au_tid_t *tid) 236263508Sdim{ 237263508Sdim char *func = "audit_write_failure()"; 238263508Sdim token_t *subject, *errtok; 239263508Sdim 240263508Sdim subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, tid); 241263508Sdim if (subject == NULL) { 242263508Sdim syslog(LOG_ERR, "%s: au_to_subject32() failed", func); 243263508Sdim return (kAUMakeSubjectTokErr); 244263508Sdim } 245263508Sdim 246263508Sdim /* tokenize and save the error message */ 247263508Sdim if ((errtok = au_to_text(errmsg)) == NULL) { 248263508Sdim au_free_token(subject); 249263508Sdim syslog(LOG_ERR, "%s: au_to_text() failed", func); 250263508Sdim return (kAUMakeTextTokErr); 251263508Sdim } 252263508Sdim 253263508Sdim return (audit_write(event_code, subject, errtok, -1, errcode)); 254263508Sdim} 255263508Sdim 256263508Sdim/* 257263508Sdim * Same caveats as audit_write(). In addition, this function explicitly 258263508Sdim * assumes failure; use audit_write_success_self() otherwise. 259263508Sdim * 260263508Sdim * XXX This should let the caller pass an error return value rather than 261263508Sdim * hard-coding -1. 262263508Sdim */ 263263508Sdimint 264263508Sdimaudit_write_failure_self(short event_code, char *errmsg, int errret) 265263508Sdim{ 266263508Sdim char *func = "audit_write_failure_self()"; 267263508Sdim token_t *subject, *errtok; 268263508Sdim 269263508Sdim if ((subject = au_to_me()) == NULL) { 270263508Sdim syslog(LOG_ERR, "%s: au_to_me() failed", func); 271263508Sdim return (kAUMakeSubjectTokErr); 272263508Sdim } 273263508Sdim /* tokenize and save the error message */ 274263508Sdim if ((errtok = au_to_text(errmsg)) == NULL) { 275263508Sdim au_free_token(subject); 276263508Sdim syslog(LOG_ERR, "%s: au_to_text() failed", func); 277263508Sdim return (kAUMakeTextTokErr); 278263508Sdim } 279263508Sdim return (audit_write(event_code, subject, errtok, -1, errret)); 280263508Sdim} 281263508Sdim 282263508Sdim/* 283263508Sdim * For auditing errors during login. Such errors are implicitly 284263508Sdim * non-attributable (i.e., not ascribable to any user). 285263508Sdim * 286263508Sdim * Assumes, like all wrapper calls, that the caller has previously checked 287263508Sdim * that auditing is enabled via the audit_get_state() call. 288263508Sdim */ 289263508Sdimint 290263508Sdimaudit_write_failure_na(short event_code, char *errmsg, int errret, uid_t euid, 291263508Sdim uid_t egid, pid_t pid, au_tid_t *tid) 292263508Sdim{ 293263508Sdim 294263508Sdim return (audit_write_failure(event_code, errmsg, errret, -1, euid, 295263508Sdim egid, -1, -1, pid, -1, tid)); 296263508Sdim} 297263508Sdim 298263508Sdim/* END OF au_write() WRAPPERS */ 299263508Sdim 300263508Sdim#ifdef __APPLE__ 301263508Sdimvoid 302263508Sdimaudit_token_to_au32(audit_token_t atoken, uid_t *auidp, uid_t *euidp, 303263508Sdim gid_t *egidp, uid_t *ruidp, gid_t *rgidp, pid_t *pidp, au_asid_t *asidp, 304263508Sdim au_tid_t *tidp) 305263508Sdim{ 306263508Sdim 307263508Sdim if (auidp != NULL) 308263508Sdim *auidp = (uid_t)atoken.val[0]; 309263508Sdim if (euidp != NULL) 310263508Sdim *euidp = (uid_t)atoken.val[1]; 311263508Sdim if (egidp != NULL) 312263508Sdim *egidp = (gid_t)atoken.val[2]; 313263508Sdim if (ruidp != NULL) 314263508Sdim *ruidp = (uid_t)atoken.val[3]; 315263508Sdim if (rgidp != NULL) 316263508Sdim *rgidp = (gid_t)atoken.val[4]; 317263508Sdim if (pidp != NULL) 318263508Sdim *pidp = (pid_t)atoken.val[5]; 319263508Sdim if (asidp != NULL) 320263508Sdim *asidp = (au_asid_t)atoken.val[6]; 321263508Sdim if (tidp != NULL) { 322263508Sdim audit_set_terminal_host(&tidp->machine); 323263508Sdim tidp->port = (dev_t)atoken.val[7]; 324263508Sdim } 325263508Sdim} 326263508Sdim#endif /* !__APPLE__ */ 327263508Sdim