login_audit.c revision 155312
1155312Swsalamon/* 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: head/usr.bin/login/login_audit.c 155312 2006-02-04 20:20:02Z wsalamon $"); 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> 46155312Swsalamon 47155312Swsalamon#include "login.h" 48155312Swsalamon 49155312Swsalamon/* 50155312Swsalamon * Audit data 51155312Swsalamon */ 52155312Swsalamonstatic au_tid_t tid; 53155312Swsalamon 54155312Swsalamon/* 55155312Swsalamon * The following tokens are included in the audit record for a successful 56155312Swsalamon * login: header, subject, return. 57155312Swsalamon */ 58155312Swsalamonvoid 59155312Swsalamonau_login_success(void) 60155312Swsalamon{ 61155312Swsalamon token_t *tok; 62155312Swsalamon int aufd; 63155312Swsalamon au_mask_t aumask; 64155312Swsalamon auditinfo_t auinfo; 65155312Swsalamon uid_t uid = pwd->pw_uid; 66155312Swsalamon gid_t gid = pwd->pw_gid; 67155312Swsalamon pid_t pid = getpid(); 68155312Swsalamon long au_cond; 69155312Swsalamon 70155312Swsalamon /* If we are not auditing, don't cut an audit record; just return. */ 71155312Swsalamon if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { 72155312Swsalamon if (errno == ENOSYS) 73155312Swsalamon return; 74155312Swsalamon errx(1, "login: Could not determine audit condition"); 75155312Swsalamon } 76155312Swsalamon if (au_cond == AUC_NOAUDIT) 77155312Swsalamon return; 78155312Swsalamon 79155312Swsalamon /* Compute and set the user's preselection mask. */ 80155312Swsalamon if (au_user_mask(pwd->pw_name, &aumask) == -1) 81155312Swsalamon errx(1, "login: Could not set audit mask\n"); 82155312Swsalamon 83155312Swsalamon /* Set the audit info for the user. */ 84155312Swsalamon auinfo.ai_auid = uid; 85155312Swsalamon auinfo.ai_asid = pid; 86155312Swsalamon bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid)); 87155312Swsalamon bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask)); 88155312Swsalamon if (setaudit(&auinfo) != 0) 89155312Swsalamon err(1, "login: setaudit failed"); 90155312Swsalamon 91155312Swsalamon if ((aufd = au_open()) == -1) 92155312Swsalamon errx(1,"login: Audit Error: au_open() failed"); 93155312Swsalamon 94155312Swsalamon if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, 95155312Swsalamon pid, &tid)) == NULL) 96155312Swsalamon errx(1, "login: Audit Error: au_to_subject32() failed"); 97155312Swsalamon au_write(aufd, tok); 98155312Swsalamon 99155312Swsalamon if ((tok = au_to_return32(0, 0)) == NULL) 100155312Swsalamon errx(1, "login: Audit Error: au_to_return32() failed"); 101155312Swsalamon au_write(aufd, tok); 102155312Swsalamon 103155312Swsalamon if (au_close(aufd, 1, AUE_login) == -1) 104155312Swsalamon errx(1, "login: Audit Record was not committed."); 105155312Swsalamon} 106155312Swsalamon 107155312Swsalamon/* 108155312Swsalamon * The following tokens are included in the audit record for failed 109155312Swsalamon * login attempts: header, subject, text, return. 110155312Swsalamon */ 111155312Swsalamonvoid 112155312Swsalamonau_login_fail(char *errmsg, int na) 113155312Swsalamon{ 114155312Swsalamon token_t *tok; 115155312Swsalamon int aufd; 116155312Swsalamon long au_cond; 117155312Swsalamon uid_t uid; 118155312Swsalamon gid_t gid; 119155312Swsalamon pid_t pid = getpid(); 120155312Swsalamon 121155312Swsalamon /* If we are not auditing, don't cut an audit record; just return. */ 122155312Swsalamon if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { 123155312Swsalamon if (errno == ENOSYS) 124155312Swsalamon return; 125155312Swsalamon errx(1, "login: Could not determine audit condition"); 126155312Swsalamon } 127155312Swsalamon if (au_cond == AUC_NOAUDIT) 128155312Swsalamon return; 129155312Swsalamon 130155312Swsalamon if ((aufd = au_open()) == -1) 131155312Swsalamon errx(1, "login: Audit Error: au_open() failed"); 132155312Swsalamon 133155312Swsalamon if (na) { 134155312Swsalamon /* 135155312Swsalamon * Non attributable event. Assuming that login is not called 136155312Swsalamon * within a user's session => auid,asid == -1. 137155312Swsalamon */ 138155312Swsalamon if ((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1, 139155312Swsalamon pid, -1, &tid)) == NULL) 140155312Swsalamon errx(1, "login: Audit Error: au_to_subject32() failed"); 141155312Swsalamon } else { 142155312Swsalamon /* We know the subject -- so use its value instead. */ 143155312Swsalamon uid = pwd->pw_uid; 144155312Swsalamon gid = pwd->pw_gid; 145155312Swsalamon if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, 146155312Swsalamon gid, pid, pid, &tid)) == NULL) 147155312Swsalamon errx(1, "login: Audit Error: au_to_subject32() failed"); 148155312Swsalamon } 149155312Swsalamon au_write(aufd, tok); 150155312Swsalamon 151155312Swsalamon /* Include the error message. */ 152155312Swsalamon if ((tok = au_to_text(errmsg)) == NULL) 153155312Swsalamon errx(1, "login: Audit Error: au_to_text() failed"); 154155312Swsalamon au_write(aufd, tok); 155155312Swsalamon 156155312Swsalamon if ((tok = au_to_return32(1, errno)) == NULL) 157155312Swsalamon errx(1, "login: Audit Error: au_to_return32() failed"); 158155312Swsalamon au_write(aufd, tok); 159155312Swsalamon 160155312Swsalamon if (au_close(aufd, 1, AUE_login) == -1) 161155312Swsalamon errx(1, "login: Audit Error: au_close() was not committed"); 162155312Swsalamon} 163155312Swsalamon 164155312Swsalamon/* 165155312Swsalamon * The following tokens are included in the audit record for a logout: 166155312Swsalamon * header, subject, return. 167155312Swsalamon */ 168155312Swsalamonvoid 169155312Swsalamonaudit_logout(void) 170155312Swsalamon{ 171155312Swsalamon token_t *tok; 172155312Swsalamon int aufd; 173155312Swsalamon au_mask_t aumask; 174155312Swsalamon auditinfo_t auinfo; 175155312Swsalamon uid_t uid = pwd->pw_uid; 176155312Swsalamon gid_t gid = pwd->pw_gid; 177155312Swsalamon pid_t pid = getpid(); 178155312Swsalamon long au_cond; 179155312Swsalamon 180155312Swsalamon /* If we are not auditing, don't cut an audit record; just return. */ 181155312Swsalamon if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 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