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