xref: /illumos-gate/usr/src/lib/libbsm/common/audit_ftpd.c (revision 09a48d4ca0ddda4ad26cc885769745870d989baf)
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
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
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
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
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
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
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
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
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
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