1/* 2 * Copyright (c) 2005 Apple Computer, Inc. 3 * All rights reserved. 4 * 5 * @APPLE_BSD_LICENSE_HEADER_START@ 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * @APPLE_BSD_LICENSE_HEADER_END@ 32 */ 33 34#ifdef USE_BSM_AUDIT 35 36#include <sys/cdefs.h> 37__FBSDID("$FreeBSD: src/usr.bin/login/login_audit.c,v 1.2 2007/05/07 11:01:36 dwmalone Exp $"); 38 39#include <sys/types.h> 40 41#include <bsm/libbsm.h> 42#include <bsm/audit_uevents.h> 43#include <bsm/audit_session.h> 44 45#include <err.h> 46#include <errno.h> 47#include <pwd.h> 48#include <stdio.h> 49#include <stdlib.h> 50#include <strings.h> 51#include <unistd.h> 52 53#include "login.h" 54 55/* 56 * Audit data 57 */ 58au_tid_addr_t tid; 59 60/* 61 * The following tokens are included in the audit record for a successful 62 * login: header, subject, return. 63 */ 64void 65au_login_success(int fflag) 66{ 67 token_t *tok; 68 int aufd; 69 auditinfo_addr_t auinfo; 70 uid_t uid = pwd->pw_uid; 71 gid_t gid = pwd->pw_gid; 72 pid_t pid = getpid(); 73 long au_cond; 74 75 /* Determine whether auditing is enabled. */ 76 if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { 77 if (errno == ENOSYS) 78 return; 79 errx(1, "login: Could not determine audit condition"); 80 } 81 82 /* Initialize with the current audit info. */ 83 if (getaudit_addr(&auinfo, sizeof(auinfo)) < 0) { 84 err(1, "getaudit_addr"); 85 } 86 auinfo.ai_auid = pwd->pw_uid; 87 memcpy(&auinfo.ai_termid, &tid, sizeof(auinfo.ai_termid)); 88 89 /* Do the SessionCreate() equivalent. */ 90 if (!fflag) { 91 auinfo.ai_asid = AU_ASSIGN_ASID; 92 auinfo.ai_flags |= AU_SESSION_FLAG_HAS_TTY; 93 auinfo.ai_flags |= AU_SESSION_FLAG_HAS_AUTHENTICATED; 94 } 95 96 if (au_cond != AUC_NOAUDIT) { 97 /* Compute and set the user's preselection mask. */ 98 if (au_user_mask(pwd->pw_name, &auinfo.ai_mask) < 0) { 99 errx(1, "login: Could not set audit mask\n"); 100 } 101 } 102 103 if (setaudit_addr(&auinfo, sizeof(auinfo)) < 0) 104 err(1, "login: setaudit_addr failed"); 105 106 char *session = NULL; 107 asprintf(&session, "%x", auinfo.ai_asid); 108 if (NULL == session) { 109 errx(1, "asprintf failed"); 110 } 111 setenv("SECURITYSESSIONID", session, 1); 112 free(session); 113 114 /* If we are not auditing, don't cut an audit record; just return. */ 115 if (au_cond == AUC_NOAUDIT) 116 return; 117 118 if ((aufd = au_open()) == -1) 119 errx(1,"login: Audit Error: au_open() failed"); 120 121 if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, gid, pid, 122 pid, &tid)) == NULL) 123 errx(1, "login: Audit Error: au_to_subject32() failed"); 124 au_write(aufd, tok); 125 126 if ((tok = au_to_return32(0, 0)) == NULL) 127 errx(1, "login: Audit Error: au_to_return32() failed"); 128 au_write(aufd, tok); 129 130 if (au_close(aufd, 1, AUE_login) == -1) 131 errx(1, "login: Audit Record was not committed."); 132} 133 134/* 135 * The following tokens are included in the audit record for failed 136 * login attempts: header, subject, text, return. 137 */ 138void 139au_login_fail(const char *errmsg, int na) 140{ 141 token_t *tok; 142 int aufd; 143 long au_cond; 144 uid_t uid; 145 gid_t gid; 146 pid_t pid = getpid(); 147 148 /* If we are not auditing, don't cut an audit record; just return. */ 149 if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { 150 if (errno == ENOSYS) 151 return; 152 errx(1, "login: Could not determine audit condition"); 153 } 154 if (au_cond == AUC_NOAUDIT) 155 return; 156 157 if ((aufd = au_open()) == -1) 158 errx(1, "login: Audit Error: au_open() failed"); 159 160 if (na) { 161 /* 162 * Non attributable event. Assuming that login is not called 163 * within a user's session => auid,asid == -1. 164 */ 165 if ((tok = au_to_subject32_ex(-1, geteuid(), getegid(), -1, -1, 166 pid, -1, &tid)) == NULL) 167 errx(1, "login: Audit Error: au_to_subject32() failed"); 168 } else { 169 /* We know the subject -- so use its value instead. */ 170 uid = pwd->pw_uid; 171 gid = pwd->pw_gid; 172 if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, 173 gid, pid, pid, &tid)) == NULL) 174 errx(1, "login: Audit Error: au_to_subject32() failed"); 175 } 176 au_write(aufd, tok); 177 178 /* Include the error message. */ 179 if ((tok = au_to_text(errmsg)) == NULL) 180 errx(1, "login: Audit Error: au_to_text() failed"); 181 au_write(aufd, tok); 182 183 if ((tok = au_to_return32(1, errno)) == NULL) 184 errx(1, "login: Audit Error: au_to_return32() failed"); 185 au_write(aufd, tok); 186 187 if (au_close(aufd, 1, AUE_login) == -1) 188 errx(1, "login: Audit Error: au_close() was not committed"); 189} 190 191/* 192 * The following tokens are included in the audit record for a logout: 193 * header, subject, return. 194 */ 195void 196audit_logout(void) 197{ 198 token_t *tok; 199 int aufd; 200 uid_t uid = pwd->pw_uid; 201 gid_t gid = pwd->pw_gid; 202 pid_t pid = getpid(); 203 long au_cond; 204 205 /* If we are not auditing, don't cut an audit record; just return. */ 206 if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { 207 if (errno == ENOSYS) 208 return; 209 errx(1, "login: Could not determine audit condition"); 210 } 211 if (au_cond == AUC_NOAUDIT) 212 return; 213 214 if ((aufd = au_open()) == -1) 215 errx(1, "login: Audit Error: au_open() failed"); 216 217 /* The subject that is created (euid, egid of the current process). */ 218 if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, gid, pid, 219 pid, &tid)) == NULL) 220 errx(1, "login: Audit Error: au_to_subject32() failed"); 221 au_write(aufd, tok); 222 223 if ((tok = au_to_return32(0, 0)) == NULL) 224 errx(1, "login: Audit Error: au_to_return32() failed"); 225 au_write(aufd, tok); 226 227 if (au_close(aufd, 1, AUE_logout) == -1) 228 errx(1, "login: Audit Record was not committed."); 229} 230 231#endif /* USE_BSM_AUDIT */ 232