audit_ftpd.c revision 4321:a8930ec16e52
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
58static char		luser[16];
59
60static void generate_record(char *, int, char *);
61static int selected(uid_t, char *, au_event_t, int);
62
63void
64audit_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
76void
77audit_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
89void
90audit_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
102void
103audit_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
112void
113audit_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
122void
123audit_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
135static void
136generate_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
225static int
226selected(
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
256void
257audit_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