xref: /freebsd/usr.bin/login/login_audit.c (revision 81b22a98)
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/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 #include <sys/types.h>
40 
41 #include <bsm/libbsm.h>
42 #include <bsm/audit_uevents.h>
43 
44 #include <err.h>
45 #include <errno.h>
46 #include <pwd.h>
47 #include <stdio.h>
48 #include <strings.h>
49 #include <unistd.h>
50 
51 #include "login.h"
52 
53 /*
54  * Audit data
55  */
56 static au_tid_t tid;
57 
58 /*
59  * The following tokens are included in the audit record for a successful
60  * login: header, subject, return.
61  */
62 void
63 au_login_success(void)
64 {
65 	token_t *tok;
66 	int aufd;
67 	au_mask_t aumask;
68 	auditinfo_t auinfo;
69 	uid_t uid = pwd->pw_uid;
70 	gid_t gid = pwd->pw_gid;
71 	pid_t pid = getpid();
72 	int au_cond;
73 
74 	/* If we are not auditing, don't cut an audit record; just return. */
75  	if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) {
76 		if (errno == ENOSYS)
77 			return;
78 		errx(1, "could not determine audit condition");
79 	}
80 	if (au_cond == AUC_NOAUDIT)
81 		return;
82 
83 	/* Compute and set the user's preselection mask. */
84 	if (au_user_mask(pwd->pw_name, &aumask) == -1)
85 		errx(1, "could not calculate audit mask");
86 
87 	/* Set the audit info for the user. */
88 	auinfo.ai_auid = uid;
89 	auinfo.ai_asid = pid;
90 	bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid));
91 	bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask));
92 	if (setaudit(&auinfo) != 0)
93 		err(1, "setaudit failed");
94 
95 	if ((aufd = au_open()) == -1)
96 		errx(1, "audit error: au_open() failed");
97 
98 	if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid,
99 	    pid, &tid)) == NULL)
100 		errx(1, "audit error: au_to_subject32() failed");
101 	au_write(aufd, tok);
102 
103 	if ((tok = au_to_return32(0, 0)) == NULL)
104 		errx(1, "audit error: au_to_return32() failed");
105 	au_write(aufd, tok);
106 
107 	if (au_close(aufd, 1, AUE_login) == -1)
108 		errx(1, "audit record was not committed.");
109 }
110 
111 /*
112  * The following tokens are included in the audit record for failed
113  * login attempts: header, subject, text, return.
114  */
115 void
116 au_login_fail(const char *errmsg, int na)
117 {
118 	token_t *tok;
119 	int aufd;
120 	int au_cond;
121 	uid_t uid;
122 	gid_t gid;
123 	pid_t pid = getpid();
124 
125 	/* If we are not auditing, don't cut an audit record; just return. */
126  	if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) {
127 		if (errno == ENOSYS)
128 			return;
129 		errx(1, "could not determine audit condition");
130 	}
131 	if (au_cond == AUC_NOAUDIT)
132 		return;
133 
134 	if ((aufd = au_open()) == -1)
135 		errx(1, "audit error: au_open() failed");
136 
137 	if (na) {
138 		/*
139 		 * Non attributable event.  Assuming that login is not called
140 		 * within a user's session => auid,asid == -1.
141 		 */
142 		if ((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1,
143 		    pid, -1, &tid)) == NULL)
144 			errx(1, "audit error: au_to_subject32() failed");
145 	} else {
146 		/* We know the subject -- so use its value instead. */
147 		uid = pwd->pw_uid;
148 		gid = pwd->pw_gid;
149 		if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid,
150 		    gid, pid, pid, &tid)) == NULL)
151 			errx(1, "audit error: au_to_subject32() failed");
152 	}
153 	au_write(aufd, tok);
154 
155 	/* Include the error message. */
156 	if ((tok = au_to_text(errmsg)) == NULL)
157 		errx(1, "audit error: au_to_text() failed");
158 	au_write(aufd, tok);
159 
160 	if ((tok = au_to_return32(1, errno)) == NULL)
161 		errx(1, "audit error: au_to_return32() failed");
162 	au_write(aufd, tok);
163 
164 	if (au_close(aufd, 1, AUE_login) == -1)
165 		errx(1, "audit error: au_close() was not committed");
166 }
167 
168 /*
169  * The following tokens are included in the audit record for a logout:
170  * header, subject, return.
171  */
172 void
173 audit_logout(void)
174 {
175 	token_t *tok;
176 	int aufd;
177 	uid_t uid = pwd->pw_uid;
178 	gid_t gid = pwd->pw_gid;
179 	pid_t pid = getpid();
180 	int au_cond;
181 
182 	/* If we are not auditing, don't cut an audit record; just return. */
183 	if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) {
184 		if (errno == ENOSYS)
185 			return;
186 		errx(1, "could not determine audit condition");
187 	}
188 	if (au_cond == AUC_NOAUDIT)
189 		return;
190 
191 	if ((aufd = au_open()) == -1)
192 		errx(1, "audit error: au_open() failed");
193 
194 	/* The subject that is created (euid, egid of the current process). */
195 	if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid,
196 	    pid, &tid)) == NULL)
197 		errx(1, "audit error: au_to_subject32() failed");
198 	au_write(aufd, tok);
199 
200 	if ((tok = au_to_return32(0, 0)) == NULL)
201 		errx(1, "audit error: au_to_return32() failed");
202 	au_write(aufd, tok);
203 
204 	if (au_close(aufd, 1, AUE_logout) == -1)
205 		errx(1, "audit record was not committed.");
206 }
207