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