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