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 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.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 static char		luser[16];
58 
59 static void generate_record(char *, int, char *);
60 static int selected(uid_t, char *, au_event_t, int);
61 
62 void
63 audit_ftpd_bad_pw(char *uname)
64 {
65 	if (cannot_audit(0)) {
66 		return;
67 	}
68 	(void) strncpy(luser, uname, 8);
69 	luser[8] = '\0';
70 	generate_record(luser, BAD_PASSWD, dgettext(bsm_dom,
71 		"bad password"));
72 }
73 
74 
75 void
76 audit_ftpd_unknown(char	*uname)
77 {
78 	if (cannot_audit(0)) {
79 		return;
80 	}
81 	(void) strncpy(luser, uname, 8);
82 	luser[8] = '\0';
83 	generate_record(luser, UNKNOWN_USER, dgettext(bsm_dom,
84 		"unknown user"));
85 }
86 
87 
88 void
89 audit_ftpd_excluded(char *uname)
90 {
91 	if (cannot_audit(0)) {
92 		return;
93 	}
94 	(void) strncpy(luser, uname, 8);
95 	luser[8] = '\0';
96 	generate_record(luser, EXCLUDED_USER, dgettext(bsm_dom,
97 		"excluded user"));
98 }
99 
100 
101 void
102 audit_ftpd_no_anon(void)
103 {
104 	if (cannot_audit(0)) {
105 		return;
106 	}
107 	generate_record("", NO_ANONYMOUS, dgettext(bsm_dom,
108 		"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,
118 		"misc failure"));
119 }
120 
121 void
122 audit_ftpd_success(char	*uname)
123 {
124 	if (cannot_audit(0)) {
125 		return;
126 	}
127 	(void) strncpy(luser, uname, 8);
128 	luser[8] = '\0';
129 	generate_record(luser, 0, "");
130 }
131 
132 
133 
134 static void
135 generate_record(
136 		char	*locuser,	/* username of local user */
137 		int	err,		/* error status */
138 					/* (=0 success, >0 error code) */
139 		char	*msg)		/* error message */
140 {
141 	int	rd;		/* audit record descriptor */
142 	char	buf[256];	/* temporary buffer */
143 	uid_t	uid;
144 	gid_t	gid;
145 	uid_t	ruid;		/* real uid */
146 	gid_t	rgid;		/* real gid */
147 	pid_t	pid;
148 	struct passwd *pwd;
149 	uid_t	ceuid;		/* current effective uid */
150 	struct auditinfo_addr info;
151 
152 	if (cannot_audit(0)) {
153 		return;
154 	}
155 
156 	pwd = getpwnam(locuser);
157 	if (pwd == NULL) {
158 		uid = -1;
159 		gid = -1;
160 	} else {
161 		uid = pwd->pw_uid;
162 		gid = pwd->pw_gid;
163 	}
164 
165 	ceuid = geteuid();	/* save current euid */
166 	(void) seteuid(0);	/* change to root so you can audit */
167 
168 	/* determine if we're preselected */
169 	if (!selected(uid, locuser, AUE_ftpd, err)) {
170 		(void) seteuid(ceuid);
171 		return;
172 	}
173 
174 	ruid = getuid();	/* get real uid */
175 	rgid = getgid();	/* get real gid */
176 
177 	pid = getpid();
178 
179 	/* see if terminal id already set */
180 	if (getaudit_addr(&info, sizeof (info)) < 0) {
181 		perror("getaudit");
182 	}
183 
184 	rd = au_open();
185 
186 	/* add subject token */
187 	(void) au_write(rd, au_to_subject_ex(uid, uid, gid,
188 		ruid, rgid, pid, pid, &info.ai_termid));
189 
190 	if (is_system_labeled())
191 		(void) au_write(rd, au_to_mylabel());
192 
193 	/* add return token */
194 	errno = 0;
195 	if (err) {
196 		/* add reason for failure */
197 		if (err == UNKNOWN_USER)
198 			(void) snprintf(buf, sizeof (buf),
199 			    "%s %s", msg, locuser);
200 		else
201 			(void) snprintf(buf, sizeof (buf), "%s", msg);
202 		(void) au_write(rd, au_to_text(buf));
203 #ifdef _LP64
204 		(void) au_write(rd, au_to_return64(-1, (int64_t)err));
205 #else
206 		(void) au_write(rd, au_to_return32(-1, (int32_t)err));
207 #endif
208 	} else {
209 #ifdef _LP64
210 		(void) au_write(rd, au_to_return64(0, (int64_t)0));
211 #else
212 		(void) au_write(rd, au_to_return32(0, (int32_t)0));
213 #endif
214 	}
215 
216 	/* write audit record */
217 	if (au_close(rd, 1, AUE_ftpd) < 0) {
218 		(void) au_close(rd, 0, 0);
219 	}
220 	(void) seteuid(ceuid);
221 }
222 
223 
224 static int
225 selected(
226 	uid_t		uid,
227 	char		*locuser,
228 	au_event_t	event,
229 	int	err)
230 {
231 	int	rc, sorf;
232 	char	naflags[512];
233 	struct au_mask mask;
234 
235 	mask.am_success = mask.am_failure = 0;
236 	if (uid < 0) {
237 		rc = getacna(naflags, 256); /* get non-attrib flags */
238 		if (rc == 0)
239 			(void) getauditflagsbin(naflags, &mask);
240 	} else {
241 		rc = au_user_mask(locuser, &mask);
242 	}
243 
244 	if (err == 0)
245 		sorf = AU_PRS_SUCCESS;
246 	else if (err >= 1)
247 		sorf = AU_PRS_FAILURE;
248 	else
249 		sorf = AU_PRS_BOTH;
250 	rc = au_preselect(event, &mask, sorf, AU_PRS_REREAD);
251 	return (rc);
252 }
253 
254 
255 void
256 audit_ftpd_logout(void)
257 {
258 	int	rd;		/* audit record descriptor */
259 	uid_t	euid;
260 	gid_t	egid;
261 	uid_t	uid;
262 	gid_t	gid;
263 	pid_t	pid;
264 	struct auditinfo_addr info;
265 
266 	if (cannot_audit(0)) {
267 		return;
268 	}
269 
270 	(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
271 
272 	/* see if terminal id already set */
273 	if (getaudit_addr(&info, sizeof (info)) < 0) {
274 		perror("getaudit");
275 	}
276 
277 	/* determine if we're preselected */
278 	if (au_preselect(AUE_ftpd_logout, &info.ai_mask, AU_PRS_SUCCESS,
279 		AU_PRS_USECACHE) == 0) {
280 		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT,
281 		    NULL);
282 		return;
283 	}
284 
285 	euid = geteuid();
286 	egid = getegid();
287 	uid = getuid();
288 	gid = getgid();
289 	pid = getpid();
290 
291 	rd = au_open();
292 
293 	/* add subject token */
294 	(void) au_write(rd, au_to_subject_ex(info.ai_auid, euid,
295 		egid, uid, gid, pid, pid, &info.ai_termid));
296 
297 	if (is_system_labeled())
298 		(void) au_write(rd, au_to_mylabel());
299 
300 	/* add return token */
301 	errno = 0;
302 #ifdef _LP64
303 	(void) au_write(rd, au_to_return64(0, (int64_t)0));
304 #else
305 	(void) au_write(rd, au_to_return32(0, (int32_t)0));
306 #endif
307 
308 	/* write audit record */
309 	if (au_close(rd, 1, AUE_ftpd_logout) < 0) {
310 		(void) au_close(rd, 0, 0);
311 	}
312 	(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL);
313 }
314