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