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
55static char		luser[LOGNAME_MAX + 1];
56
57static void generate_record(char *, int, char *);
58static int selected(uid_t, char *, au_event_t, int);
59
60void
61audit_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
71void
72audit_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
82void
83audit_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
94void
95audit_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
103void
104audit_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
112void
113audit_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
124static void
125generate_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
214static int
215selected(
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
244void
245audit_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