xref: /freebsd/usr.bin/login/login_audit.c (revision e0c4386e)
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  */
53 static 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  */
59 void
60 au_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  */
112 void
113 au_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  */
169 void
170 audit_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