1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2013 Gary Mills
23 *
24 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <stdio.h>
30 #include <sys/fcntl.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <syslog.h>
34 #include <unistd.h>
35
36 #include <sys/socket.h>
37 #include <sys/sockio.h>
38 #include <netinet/in.h>
39 #include <tsol/label.h>
40
41 #include <bsm/audit.h>
42 #include <bsm/audit_record.h>
43 #include <bsm/audit_uevents.h>
44 #include <bsm/libbsm.h>
45 #include <bsm/audit_private.h>
46
47 #include <locale.h>
48 #include <pwd.h>
49 #include <generic.h>
50
51 #define BAD_PASSWD (1)
52 #define UNKNOWN_USER (2)
53 #define EXCLUDED_USER (3)
54 #define NO_ANONYMOUS (4)
55 #define MISC_FAILURE (5)
56
57 #ifdef LOGNAME_MAX_ILLUMOS
58 #define _LOGNAME_MAX LOGNAME_MAX_ILLUMOS
59 #else /* LOGNAME_MAX_ILLUMOS */
60 #define _LOGNAME_MAX LOGNAME_MAX
61 #endif /* LOGNAME_MAX_ILLUMOS */
62
63 static char luser[_LOGNAME_MAX + 1];
64
65 static void generate_record(char *, int, char *);
66 static int selected(uid_t, char *, au_event_t, int);
67
68 void
69 audit_ftpd_bad_pw(char *uname)
70 {
71 if (cannot_audit(0)) {
72 return;
73 }
74 (void) strncpy(luser, uname, _LOGNAME_MAX);
75 generate_record(luser, BAD_PASSWD, dgettext(bsm_dom, "bad password"));
76 }
77
78
79 void
80 audit_ftpd_unknown(char *uname)
81 {
82 if (cannot_audit(0)) {
83 return;
84 }
85 (void) strncpy(luser, uname, _LOGNAME_MAX);
86 generate_record(luser, UNKNOWN_USER, dgettext(bsm_dom, "unknown user"));
87 }
88
89
90 void
91 audit_ftpd_excluded(char *uname)
92 {
93 if (cannot_audit(0)) {
94 return;
95 }
96 (void) strncpy(luser, uname, _LOGNAME_MAX);
97 generate_record(luser, EXCLUDED_USER, dgettext(bsm_dom,
98 "excluded user"));
99 }
100
101
102 void
103 audit_ftpd_no_anon(void)
104 {
105 if (cannot_audit(0)) {
106 return;
107 }
108 generate_record("", NO_ANONYMOUS, dgettext(bsm_dom, "no anonymous"));
109 }
110
111 void
112 audit_ftpd_failure(char *uname)
113 {
114 if (cannot_audit(0)) {
115 return;
116 }
117 generate_record(uname, MISC_FAILURE, dgettext(bsm_dom, "misc failure"));
118 }
119
120 void
121 audit_ftpd_success(char *uname)
122 {
123 if (cannot_audit(0)) {
124 return;
125 }
126 (void) strncpy(luser, uname, _LOGNAME_MAX);
127 generate_record(luser, 0, "");
128 }
129
130
131
132 static void
133 generate_record(
134 char *locuser, /* username of local user */
135 int err, /* error status */
136 /* (=0 success, >0 error code) */
137 char *msg) /* error message */
138 {
139 int rd; /* audit record descriptor */
140 char buf[256]; /* temporary buffer */
141 uid_t uid;
142 gid_t gid;
143 uid_t ruid; /* real uid */
144 gid_t rgid; /* real gid */
145 pid_t pid;
146 struct passwd *pwd;
147 uid_t ceuid; /* current effective uid */
148 struct auditinfo_addr info;
149
150 if (cannot_audit(0)) {
151 return;
152 }
153
154 pwd = getpwnam(locuser);
155 if (pwd == NULL) {
156 uid = (uid_t)-1;
157 gid = (gid_t)-1;
158 } else {
159 uid = pwd->pw_uid;
160 gid = pwd->pw_gid;
161 }
162
163 ceuid = geteuid(); /* save current euid */
164 (void) seteuid(0); /* change to root so you can audit */
165
166 /* determine if we're preselected */
167 if (!selected(uid, locuser, AUE_ftpd, err)) {
168 (void) seteuid(ceuid);
169 return;
170 }
171
172 ruid = getuid(); /* get real uid */
173 rgid = getgid(); /* get real gid */
174
175 pid = getpid();
176
177 /* see if terminal id already set */
178 if (getaudit_addr(&info, sizeof (info)) < 0) {
179 perror("getaudit");
180 }
181
182 rd = au_open();
183
184 /* add subject token */
185 (void) au_write(rd, au_to_subject_ex(uid, uid, gid,
186 ruid, rgid, pid, pid, &info.ai_termid));
187
188 if (is_system_labeled())
189 (void) au_write(rd, au_to_mylabel());
190
191 /* add return token */
192 errno = 0;
193 if (err) {
194 /* add reason for failure */
195 if (err == UNKNOWN_USER)
196 (void) snprintf(buf, sizeof (buf),
197 "%s %s", msg, locuser);
198 else
199 (void) snprintf(buf, sizeof (buf), "%s", msg);
200 (void) au_write(rd, au_to_text(buf));
201 #ifdef _LP64
202 (void) au_write(rd, au_to_return64(-1, (int64_t)err));
203 #else
204 (void) au_write(rd, au_to_return32(-1, (int32_t)err));
205 #endif
206 } else {
207 #ifdef _LP64
208 (void) au_write(rd, au_to_return64(0, (int64_t)0));
209 #else
210 (void) au_write(rd, au_to_return32(0, (int32_t)0));
211 #endif
212 }
213
214 /* write audit record */
215 if (au_close(rd, 1, AUE_ftpd) < 0) {
216 (void) au_close(rd, 0, 0);
217 }
218 (void) seteuid(ceuid);
219 }
220
221
222 static int
223 selected(
224 uid_t uid,
225 char *locuser,
226 au_event_t event,
227 int err)
228 {
229 int sorf;
230 struct au_mask mask;
231
232 mask.am_success = mask.am_failure = 0;
233 if (uid > MAXEPHUID) {
234 /* get non-attrib flags */
235 (void) auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask));
236 } else {
237 (void) au_user_mask(locuser, &mask);
238 }
239
240 if (err == 0) {
241 sorf = AU_PRS_SUCCESS;
242 } else if (err >= 1) {
243 sorf = AU_PRS_FAILURE;
244 } else {
245 sorf = AU_PRS_BOTH;
246 }
247
248 return (au_preselect(event, &mask, sorf, AU_PRS_REREAD));
249 }
250
251
252 void
253 audit_ftpd_logout(void)
254 {
255 int rd; /* audit record descriptor */
256 uid_t euid;
257 gid_t egid;
258 uid_t uid;
259 gid_t gid;
260 pid_t pid;
261 struct auditinfo_addr info;
262
263 if (cannot_audit(0)) {
264 return;
265 }
266
267 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
268
269 /* see if terminal id already set */
270 if (getaudit_addr(&info, sizeof (info)) < 0) {
271 perror("getaudit");
272 }
273
274 /* determine if we're preselected */
275 if (au_preselect(AUE_ftpd_logout, &info.ai_mask, AU_PRS_SUCCESS,
276 AU_PRS_USECACHE) == 0) {
277 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT,
278 NULL);
279 return;
280 }
281
282 euid = geteuid();
283 egid = getegid();
284 uid = getuid();
285 gid = getgid();
286 pid = getpid();
287
288 rd = au_open();
289
290 /* add subject token */
291 (void) au_write(rd, au_to_subject_ex(info.ai_auid, euid,
292 egid, uid, gid, pid, pid, &info.ai_termid));
293
294 if (is_system_labeled())
295 (void) au_write(rd, au_to_mylabel());
296
297 /* add return token */
298 errno = 0;
299 #ifdef _LP64
300 (void) au_write(rd, au_to_return64(0, (int64_t)0));
301 #else
302 (void) au_write(rd, au_to_return32(0, (int32_t)0));
303 #endif
304
305 /* write audit record */
306 if (au_close(rd, 1, AUE_ftpd_logout) < 0) {
307 (void) au_close(rd, 0, 0);
308 }
309 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
310 }