1331722Seadler/* 2155312Swsalamon * Copyright (c) 2005 Apple Computer, Inc. 3155312Swsalamon * All rights reserved. 4155312Swsalamon * 5155312Swsalamon * @APPLE_BSD_LICENSE_HEADER_START@ 6155312Swsalamon * 7155312Swsalamon * Redistribution and use in source and binary forms, with or without 8155312Swsalamon * modification, are permitted provided that the following conditions 9155312Swsalamon * are met: 10155312Swsalamon * 11155312Swsalamon * 1. Redistributions of source code must retain the above copyright 12155312Swsalamon * notice, this list of conditions and the following disclaimer. 13155312Swsalamon * 2. Redistributions in binary form must reproduce the above copyright 14155312Swsalamon * notice, this list of conditions and the following disclaimer in the 15155312Swsalamon * documentation and/or other materials provided with the distribution. 16155312Swsalamon * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 17155312Swsalamon * its contributors may be used to endorse or promote products derived 18155312Swsalamon * from this software without specific prior written permission. 19155312Swsalamon * 20155312Swsalamon * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 21155312Swsalamon * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22155312Swsalamon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23155312Swsalamon * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 24155312Swsalamon * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25155312Swsalamon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26155312Swsalamon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27155312Swsalamon * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28155312Swsalamon * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29155312Swsalamon * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30155312Swsalamon * 31155312Swsalamon * @APPLE_BSD_LICENSE_HEADER_END@ 32155312Swsalamon */ 33155312Swsalamon 34155312Swsalamon#include <sys/cdefs.h> 35155312Swsalamon__FBSDID("$FreeBSD$"); 36155312Swsalamon 37155312Swsalamon#include <sys/types.h> 38155312Swsalamon 39155312Swsalamon#include <bsm/libbsm.h> 40155312Swsalamon#include <bsm/audit_uevents.h> 41155312Swsalamon 42155312Swsalamon#include <err.h> 43155312Swsalamon#include <errno.h> 44155312Swsalamon#include <pwd.h> 45155312Swsalamon#include <stdio.h> 46169342Sdwmalone#include <strings.h> 47169342Sdwmalone#include <unistd.h> 48155312Swsalamon 49155312Swsalamon#include "login.h" 50155312Swsalamon 51155312Swsalamon/* 52155312Swsalamon * Audit data 53155312Swsalamon */ 54155312Swsalamonstatic au_tid_t tid; 55155312Swsalamon 56155312Swsalamon/* 57155312Swsalamon * The following tokens are included in the audit record for a successful 58155312Swsalamon * login: header, subject, return. 59155312Swsalamon */ 60155312Swsalamonvoid 61155312Swsalamonau_login_success(void) 62155312Swsalamon{ 63155312Swsalamon token_t *tok; 64155312Swsalamon int aufd; 65155312Swsalamon au_mask_t aumask; 66155312Swsalamon auditinfo_t auinfo; 67155312Swsalamon uid_t uid = pwd->pw_uid; 68155312Swsalamon gid_t gid = pwd->pw_gid; 69155312Swsalamon pid_t pid = getpid(); 70191297Srwatson int au_cond; 71155312Swsalamon 72155312Swsalamon /* If we are not auditing, don't cut an audit record; just return. */ 73191297Srwatson if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) { 74155312Swsalamon if (errno == ENOSYS) 75155312Swsalamon return; 76155312Swsalamon errx(1, "login: Could not determine audit condition"); 77155312Swsalamon } 78155312Swsalamon if (au_cond == AUC_NOAUDIT) 79155312Swsalamon return; 80155312Swsalamon 81155312Swsalamon /* Compute and set the user's preselection mask. */ 82155312Swsalamon if (au_user_mask(pwd->pw_name, &aumask) == -1) 83155312Swsalamon errx(1, "login: Could not set audit mask\n"); 84155312Swsalamon 85155312Swsalamon /* Set the audit info for the user. */ 86155312Swsalamon auinfo.ai_auid = uid; 87155312Swsalamon auinfo.ai_asid = pid; 88155312Swsalamon bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid)); 89155312Swsalamon bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask)); 90155312Swsalamon if (setaudit(&auinfo) != 0) 91155312Swsalamon err(1, "login: setaudit failed"); 92155312Swsalamon 93155312Swsalamon if ((aufd = au_open()) == -1) 94155312Swsalamon errx(1,"login: Audit Error: au_open() failed"); 95155312Swsalamon 96155312Swsalamon if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, 97155312Swsalamon pid, &tid)) == NULL) 98155312Swsalamon errx(1, "login: Audit Error: au_to_subject32() failed"); 99155312Swsalamon au_write(aufd, tok); 100155312Swsalamon 101155312Swsalamon if ((tok = au_to_return32(0, 0)) == NULL) 102155312Swsalamon errx(1, "login: Audit Error: au_to_return32() failed"); 103155312Swsalamon au_write(aufd, tok); 104155312Swsalamon 105155312Swsalamon if (au_close(aufd, 1, AUE_login) == -1) 106155312Swsalamon errx(1, "login: Audit Record was not committed."); 107155312Swsalamon} 108155312Swsalamon 109155312Swsalamon/* 110155312Swsalamon * The following tokens are included in the audit record for failed 111155312Swsalamon * login attempts: header, subject, text, return. 112155312Swsalamon */ 113155312Swsalamonvoid 114169342Sdwmaloneau_login_fail(const char *errmsg, int na) 115155312Swsalamon{ 116155312Swsalamon token_t *tok; 117155312Swsalamon int aufd; 118191297Srwatson int au_cond; 119155312Swsalamon uid_t uid; 120155312Swsalamon gid_t gid; 121155312Swsalamon pid_t pid = getpid(); 122155312Swsalamon 123155312Swsalamon /* If we are not auditing, don't cut an audit record; just return. */ 124191297Srwatson if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) { 125155312Swsalamon if (errno == ENOSYS) 126155312Swsalamon return; 127155312Swsalamon errx(1, "login: Could not determine audit condition"); 128155312Swsalamon } 129155312Swsalamon if (au_cond == AUC_NOAUDIT) 130155312Swsalamon return; 131155312Swsalamon 132155312Swsalamon if ((aufd = au_open()) == -1) 133155312Swsalamon errx(1, "login: Audit Error: au_open() failed"); 134155312Swsalamon 135155312Swsalamon if (na) { 136155312Swsalamon /* 137155312Swsalamon * Non attributable event. Assuming that login is not called 138155312Swsalamon * within a user's session => auid,asid == -1. 139155312Swsalamon */ 140155312Swsalamon if ((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1, 141155312Swsalamon pid, -1, &tid)) == NULL) 142155312Swsalamon errx(1, "login: Audit Error: au_to_subject32() failed"); 143155312Swsalamon } else { 144155312Swsalamon /* We know the subject -- so use its value instead. */ 145155312Swsalamon uid = pwd->pw_uid; 146155312Swsalamon gid = pwd->pw_gid; 147155312Swsalamon if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, 148155312Swsalamon gid, pid, pid, &tid)) == NULL) 149155312Swsalamon errx(1, "login: Audit Error: au_to_subject32() failed"); 150155312Swsalamon } 151155312Swsalamon au_write(aufd, tok); 152155312Swsalamon 153155312Swsalamon /* Include the error message. */ 154155312Swsalamon if ((tok = au_to_text(errmsg)) == NULL) 155155312Swsalamon errx(1, "login: Audit Error: au_to_text() failed"); 156155312Swsalamon au_write(aufd, tok); 157155312Swsalamon 158155312Swsalamon if ((tok = au_to_return32(1, errno)) == NULL) 159155312Swsalamon errx(1, "login: Audit Error: au_to_return32() failed"); 160155312Swsalamon au_write(aufd, tok); 161155312Swsalamon 162155312Swsalamon if (au_close(aufd, 1, AUE_login) == -1) 163155312Swsalamon errx(1, "login: Audit Error: au_close() was not committed"); 164155312Swsalamon} 165155312Swsalamon 166155312Swsalamon/* 167155312Swsalamon * The following tokens are included in the audit record for a logout: 168155312Swsalamon * header, subject, return. 169155312Swsalamon */ 170155312Swsalamonvoid 171155312Swsalamonaudit_logout(void) 172155312Swsalamon{ 173155312Swsalamon token_t *tok; 174155312Swsalamon int aufd; 175155312Swsalamon uid_t uid = pwd->pw_uid; 176155312Swsalamon gid_t gid = pwd->pw_gid; 177155312Swsalamon pid_t pid = getpid(); 178191297Srwatson int au_cond; 179155312Swsalamon 180155312Swsalamon /* If we are not auditing, don't cut an audit record; just return. */ 181191297Srwatson if (auditon(A_GETCOND, &au_cond, sizeof(int)) < 0) { 182155312Swsalamon if (errno == ENOSYS) 183155312Swsalamon return; 184155312Swsalamon errx(1, "login: Could not determine audit condition"); 185155312Swsalamon } 186155312Swsalamon if (au_cond == AUC_NOAUDIT) 187155312Swsalamon return; 188155312Swsalamon 189155312Swsalamon if ((aufd = au_open()) == -1) 190155312Swsalamon errx(1, "login: Audit Error: au_open() failed"); 191155312Swsalamon 192155312Swsalamon /* The subject that is created (euid, egid of the current process). */ 193155312Swsalamon if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, 194155312Swsalamon pid, &tid)) == NULL) 195155312Swsalamon errx(1, "login: Audit Error: au_to_subject32() failed"); 196155312Swsalamon au_write(aufd, tok); 197155312Swsalamon 198155312Swsalamon if ((tok = au_to_return32(0, 0)) == NULL) 199155312Swsalamon errx(1, "login: Audit Error: au_to_return32() failed"); 200155312Swsalamon au_write(aufd, tok); 201155312Swsalamon 202155312Swsalamon if (au_close(aufd, 1, AUE_logout) == -1) 203155312Swsalamon errx(1, "login: Audit Record was not committed."); 204155312Swsalamon} 205