1331722Seadler/*
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$");
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>
46169342Sdwmalone#include <strings.h>
47169342Sdwmalone#include <unistd.h>
48155312Swsalamon
49155312Swsalamon#include "login.h"
50155312Swsalamon
51155312Swsalamon/*
52155312Swsalamon * Audit data
53155312Swsalamon */
54155312Swsalamonstatic au_tid_t tid;
55155312Swsalamon
56155312Swsalamon/*
57155312Swsalamon * The following tokens are included in the audit record for a successful
58155312Swsalamon * login: header, subject, return.
59155312Swsalamon */
60155312Swsalamonvoid
61155312Swsalamonau_login_success(void)
62155312Swsalamon{
63155312Swsalamon	token_t *tok;
64155312Swsalamon	int aufd;
65155312Swsalamon	au_mask_t aumask;
66155312Swsalamon	auditinfo_t auinfo;
67155312Swsalamon	uid_t uid = pwd->pw_uid;
68155312Swsalamon	gid_t gid = pwd->pw_gid;
69155312Swsalamon	pid_t pid = getpid();
70191297Srwatson	int au_cond;
71155312Swsalamon
72155312Swsalamon	/* If we are not auditing, don't cut an audit record; just return. */
73191297Srwatson 	if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) {
74155312Swsalamon		if (errno == ENOSYS)
75155312Swsalamon			return;
76155312Swsalamon		errx(1, "login: Could not determine audit condition");
77155312Swsalamon	}
78155312Swsalamon	if (au_cond == AUC_NOAUDIT)
79155312Swsalamon		return;
80155312Swsalamon
81155312Swsalamon	/* Compute and set the user's preselection mask. */
82155312Swsalamon	if (au_user_mask(pwd->pw_name, &aumask) == -1)
83155312Swsalamon		errx(1, "login: Could not set audit mask\n");
84155312Swsalamon
85155312Swsalamon	/* Set the audit info for the user. */
86155312Swsalamon	auinfo.ai_auid = uid;
87155312Swsalamon	auinfo.ai_asid = pid;
88155312Swsalamon	bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid));
89155312Swsalamon	bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask));
90155312Swsalamon	if (setaudit(&auinfo) != 0)
91155312Swsalamon		err(1, "login: setaudit failed");
92155312Swsalamon
93155312Swsalamon	if ((aufd = au_open()) == -1)
94155312Swsalamon		errx(1,"login: Audit Error: au_open() failed");
95155312Swsalamon
96155312Swsalamon	if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid,
97155312Swsalamon	    pid, &tid)) == NULL)
98155312Swsalamon		errx(1, "login: Audit Error: au_to_subject32() failed");
99155312Swsalamon	au_write(aufd, tok);
100155312Swsalamon
101155312Swsalamon	if ((tok = au_to_return32(0, 0)) == NULL)
102155312Swsalamon		errx(1, "login: Audit Error: au_to_return32() failed");
103155312Swsalamon	au_write(aufd, tok);
104155312Swsalamon
105155312Swsalamon	if (au_close(aufd, 1, AUE_login) == -1)
106155312Swsalamon		errx(1, "login: Audit Record was not committed.");
107155312Swsalamon}
108155312Swsalamon
109155312Swsalamon/*
110155312Swsalamon * The following tokens are included in the audit record for failed
111155312Swsalamon * login attempts: header, subject, text, return.
112155312Swsalamon */
113155312Swsalamonvoid
114169342Sdwmaloneau_login_fail(const char *errmsg, int na)
115155312Swsalamon{
116155312Swsalamon	token_t *tok;
117155312Swsalamon	int aufd;
118191297Srwatson	int au_cond;
119155312Swsalamon	uid_t uid;
120155312Swsalamon	gid_t gid;
121155312Swsalamon	pid_t pid = getpid();
122155312Swsalamon
123155312Swsalamon	/* If we are not auditing, don't cut an audit record; just return. */
124191297Srwatson 	if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) {
125155312Swsalamon		if (errno == ENOSYS)
126155312Swsalamon			return;
127155312Swsalamon		errx(1, "login: Could not determine audit condition");
128155312Swsalamon	}
129155312Swsalamon	if (au_cond == AUC_NOAUDIT)
130155312Swsalamon		return;
131155312Swsalamon
132155312Swsalamon	if ((aufd = au_open()) == -1)
133155312Swsalamon		errx(1, "login: Audit Error: au_open() failed");
134155312Swsalamon
135155312Swsalamon	if (na) {
136155312Swsalamon		/*
137155312Swsalamon		 * Non attributable event.  Assuming that login is not called
138155312Swsalamon		 * within a user's session => auid,asid == -1.
139155312Swsalamon		 */
140155312Swsalamon		if ((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1,
141155312Swsalamon		    pid, -1, &tid)) == NULL)
142155312Swsalamon			errx(1, "login: Audit Error: au_to_subject32() failed");
143155312Swsalamon	} else {
144155312Swsalamon		/* We know the subject -- so use its value instead. */
145155312Swsalamon		uid = pwd->pw_uid;
146155312Swsalamon		gid = pwd->pw_gid;
147155312Swsalamon		if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid,
148155312Swsalamon		    gid, pid, pid, &tid)) == NULL)
149155312Swsalamon			errx(1, "login: Audit Error: au_to_subject32() failed");
150155312Swsalamon	}
151155312Swsalamon	au_write(aufd, tok);
152155312Swsalamon
153155312Swsalamon	/* Include the error message. */
154155312Swsalamon	if ((tok = au_to_text(errmsg)) == NULL)
155155312Swsalamon		errx(1, "login: Audit Error: au_to_text() failed");
156155312Swsalamon	au_write(aufd, tok);
157155312Swsalamon
158155312Swsalamon	if ((tok = au_to_return32(1, errno)) == NULL)
159155312Swsalamon		errx(1, "login: Audit Error: au_to_return32() failed");
160155312Swsalamon	au_write(aufd, tok);
161155312Swsalamon
162155312Swsalamon	if (au_close(aufd, 1, AUE_login) == -1)
163155312Swsalamon		errx(1, "login: Audit Error: au_close() was not committed");
164155312Swsalamon}
165155312Swsalamon
166155312Swsalamon/*
167155312Swsalamon * The following tokens are included in the audit record for a logout:
168155312Swsalamon * header, subject, return.
169155312Swsalamon */
170155312Swsalamonvoid
171155312Swsalamonaudit_logout(void)
172155312Swsalamon{
173155312Swsalamon	token_t *tok;
174155312Swsalamon	int aufd;
175155312Swsalamon	uid_t uid = pwd->pw_uid;
176155312Swsalamon	gid_t gid = pwd->pw_gid;
177155312Swsalamon	pid_t pid = getpid();
178191297Srwatson	int au_cond;
179155312Swsalamon
180155312Swsalamon	/* If we are not auditing, don't cut an audit record; just return. */
181191297Srwatson 	if (auditon(A_GETCOND, &au_cond, sizeof(int)) < 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