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