1114522Sdougb/* 2114522Sdougb * Copyright (c) 2005 Apple Computer, Inc. 3114522Sdougb * All rights reserved. 4114522Sdougb * 5114522Sdougb * @APPLE_BSD_LICENSE_HEADER_START@ 6114522Sdougb * 7114522Sdougb * Redistribution and use in source and binary forms, with or without 8114522Sdougb * modification, are permitted provided that the following conditions 9114522Sdougb * are met: 10114522Sdougb * 11114522Sdougb * 1. Redistributions of source code must retain the above copyright 12114522Sdougb * notice, this list of conditions and the following disclaimer. 13114522Sdougb * 2. Redistributions in binary form must reproduce the above copyright 14114522Sdougb * notice, this list of conditions and the following disclaimer in the 15114522Sdougb * documentation and/or other materials provided with the distribution. 16114522Sdougb * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 17114522Sdougb * its contributors may be used to endorse or promote products derived 18114522Sdougb * from this software without specific prior written permission. 19114522Sdougb * 20114522Sdougb * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 21114522Sdougb * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22114522Sdougb * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23114522Sdougb * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 24114522Sdougb * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25114522Sdougb * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26114522Sdougb * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27114522Sdougb * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28114522Sdougb * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29114522Sdougb * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30114522Sdougb * 31114522Sdougb * @APPLE_BSD_LICENSE_HEADER_END@ 32114522Sdougb */ 33114522Sdougb 34114522Sdougb#include <sys/cdefs.h> 35114522Sdougb__FBSDID("$FreeBSD$"); 36114522Sdougb 37114522Sdougb#include <sys/types.h> 38114522Sdougb 39114522Sdougb#include <bsm/libbsm.h> 40114522Sdougb#include <bsm/audit_uevents.h> 41114522Sdougb 42114522Sdougb#include <err.h> 43114522Sdougb#include <errno.h> 44114522Sdougb#include <pwd.h> 45114522Sdougb#include <stdio.h> 46114522Sdougb#include <strings.h> 47114522Sdougb#include <unistd.h> 48114522Sdougb 49114522Sdougb#include "login.h" 50114522Sdougb 51114522Sdougb/* 52114522Sdougb * Audit data 53114522Sdougb */ 54114522Sdougbstatic au_tid_t tid; 55114522Sdougb 56114522Sdougb/* 57114522Sdougb * The following tokens are included in the audit record for a successful 58114522Sdougb * login: header, subject, return. 59114522Sdougb */ 60114522Sdougbvoid 61114522Sdougbau_login_success(void) 62114522Sdougb{ 63114522Sdougb token_t *tok; 64114522Sdougb int aufd; 65114522Sdougb au_mask_t aumask; 66114522Sdougb auditinfo_t auinfo; 67114522Sdougb uid_t uid = pwd->pw_uid; 68114522Sdougb gid_t gid = pwd->pw_gid; 69114522Sdougb pid_t pid = getpid(); 70114522Sdougb int au_cond; 71114522Sdougb 72114522Sdougb /* If we are not auditing, don't cut an audit record; just return. */ 73114522Sdougb if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) { 74114522Sdougb if (errno == ENOSYS) 75114522Sdougb return; 76114522Sdougb errx(1, "login: Could not determine audit condition"); 77114522Sdougb } 78114522Sdougb if (au_cond == AUC_NOAUDIT) 79114522Sdougb return; 80114522Sdougb 81114522Sdougb /* Compute and set the user's preselection mask. */ 82114522Sdougb if (au_user_mask(pwd->pw_name, &aumask) == -1) 83114522Sdougb errx(1, "login: Could not set audit mask\n"); 84114522Sdougb 85114522Sdougb /* Set the audit info for the user. */ 86114522Sdougb auinfo.ai_auid = uid; 87114522Sdougb auinfo.ai_asid = pid; 88114522Sdougb bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid)); 89114522Sdougb bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask)); 90114522Sdougb if (setaudit(&auinfo) != 0) 91114522Sdougb err(1, "login: setaudit failed"); 92114522Sdougb 93114522Sdougb if ((aufd = au_open()) == -1) 94114522Sdougb errx(1,"login: Audit Error: au_open() failed"); 95114522Sdougb 96114522Sdougb if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, 97114522Sdougb pid, &tid)) == NULL) 98114522Sdougb errx(1, "login: Audit Error: au_to_subject32() failed"); 99114522Sdougb au_write(aufd, tok); 100114522Sdougb 101114522Sdougb if ((tok = au_to_return32(0, 0)) == NULL) 102114522Sdougb errx(1, "login: Audit Error: au_to_return32() failed"); 103114522Sdougb au_write(aufd, tok); 104114522Sdougb 105114522Sdougb if (au_close(aufd, 1, AUE_login) == -1) 106114522Sdougb errx(1, "login: Audit Record was not committed."); 107114522Sdougb} 108114522Sdougb 109114522Sdougb/* 110114522Sdougb * The following tokens are included in the audit record for failed 111114522Sdougb * login attempts: header, subject, text, return. 112114522Sdougb */ 113114522Sdougbvoid 114114522Sdougbau_login_fail(const char *errmsg, int na) 115114522Sdougb{ 116114522Sdougb token_t *tok; 117114522Sdougb int aufd; 118114522Sdougb int au_cond; 119114522Sdougb uid_t uid; 120114522Sdougb gid_t gid; 121114522Sdougb pid_t pid = getpid(); 122114522Sdougb 123114522Sdougb /* If we are not auditing, don't cut an audit record; just return. */ 124114522Sdougb if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) { 125114522Sdougb if (errno == ENOSYS) 126114522Sdougb return; 127114522Sdougb errx(1, "login: Could not determine audit condition"); 128114522Sdougb } 129114522Sdougb if (au_cond == AUC_NOAUDIT) 130114522Sdougb return; 131114522Sdougb 132114522Sdougb if ((aufd = au_open()) == -1) 133114522Sdougb errx(1, "login: Audit Error: au_open() failed"); 134114522Sdougb 135114522Sdougb if (na) { 136114522Sdougb /* 137114522Sdougb * Non attributable event. Assuming that login is not called 138114522Sdougb * within a user's session => auid,asid == -1. 139114522Sdougb */ 140114522Sdougb if ((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1, 141114522Sdougb pid, -1, &tid)) == NULL) 142114522Sdougb errx(1, "login: Audit Error: au_to_subject32() failed"); 143114522Sdougb } else { 144114522Sdougb /* We know the subject -- so use its value instead. */ 145114522Sdougb uid = pwd->pw_uid; 146114522Sdougb gid = pwd->pw_gid; 147114522Sdougb if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, 148114522Sdougb gid, pid, pid, &tid)) == NULL) 149114522Sdougb errx(1, "login: Audit Error: au_to_subject32() failed"); 150114522Sdougb } 151114522Sdougb au_write(aufd, tok); 152114522Sdougb 153114522Sdougb /* Include the error message. */ 154114522Sdougb if ((tok = au_to_text(errmsg)) == NULL) 155114522Sdougb errx(1, "login: Audit Error: au_to_text() failed"); 156114522Sdougb au_write(aufd, tok); 157114522Sdougb 158114522Sdougb if ((tok = au_to_return32(1, errno)) == NULL) 159114522Sdougb errx(1, "login: Audit Error: au_to_return32() failed"); 160114522Sdougb au_write(aufd, tok); 161114522Sdougb 162114522Sdougb if (au_close(aufd, 1, AUE_login) == -1) 163114522Sdougb errx(1, "login: Audit Error: au_close() was not committed"); 164114522Sdougb} 165114522Sdougb 166114522Sdougb/* 167114522Sdougb * The following tokens are included in the audit record for a logout: 168114522Sdougb * header, subject, return. 169114522Sdougb */ 170114522Sdougbvoid 171114522Sdougbaudit_logout(void) 172114522Sdougb{ 173114522Sdougb token_t *tok; 174114522Sdougb int aufd; 175114522Sdougb uid_t uid = pwd->pw_uid; 176114522Sdougb gid_t gid = pwd->pw_gid; 177114522Sdougb pid_t pid = getpid(); 178114522Sdougb int au_cond; 179114522Sdougb 180114522Sdougb /* If we are not auditing, don't cut an audit record; just return. */ 181114522Sdougb if (auditon(A_GETCOND, &au_cond, sizeof(int)) < 0) { 182114522Sdougb if (errno == ENOSYS) 183114522Sdougb return; 184114522Sdougb errx(1, "login: Could not determine audit condition"); 185114522Sdougb } 186114522Sdougb if (au_cond == AUC_NOAUDIT) 187114522Sdougb return; 188114522Sdougb 189114522Sdougb if ((aufd = au_open()) == -1) 190114522Sdougb errx(1, "login: Audit Error: au_open() failed"); 191114522Sdougb 192114522Sdougb /* The subject that is created (euid, egid of the current process). */ 193114522Sdougb if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, 194114522Sdougb pid, &tid)) == NULL) 195 errx(1, "login: Audit Error: au_to_subject32() failed"); 196 au_write(aufd, tok); 197 198 if ((tok = au_to_return32(0, 0)) == NULL) 199 errx(1, "login: Audit Error: au_to_return32() failed"); 200 au_write(aufd, tok); 201 202 if (au_close(aufd, 1, AUE_logout) == -1) 203 errx(1, "login: Audit Record was not committed."); 204} 205