xref: /illumos-gate/usr/src/lib/libbsm/common/audit_rexd.c (revision d3d50737e566cade9a08d73d2af95105ac7cd960)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
26 
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <sys/fcntl.h>
32 #include <bsm/audit.h>
33 #include <bsm/audit_record.h>
34 #include <bsm/audit_uevents.h>
35 #include <bsm/libbsm.h>
36 #include <bsm/audit_private.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <syslog.h>
40 #include <pwd.h>
41 #include <netinet/in.h>
42 #include <tsol/label.h>
43 #include <locale.h>
44 #include "generic.h"
45 
46 #ifdef C2_DEBUG
47 #define	dprintf(x) { printf x; }
48 #else
49 #define	dprintf(x)
50 #endif
51 
52 #define	UNKNOWN_CMD	"???"
53 
54 static au_event_t	event;
55 static int		audit_rexd_status = 0;
56 
57 static char *
58 build_cmd(char **cmd)
59 {
60 	int i, l;
61 	char *r;
62 
63 	if (cmd == NULL)
64 		return (NULL);
65 	/* count the total length of command line */
66 	for (i = 0, l = 0; cmd[i] != NULL; i++)
67 		l += strlen(cmd[i]) + 1;
68 
69 	if (l == 0)
70 		return (NULL);
71 	r = malloc(l);
72 	if (r != NULL) {
73 		for (i = 0; cmd[i] != NULL; i++) {
74 			(void) strcat(r, cmd[i]);
75 			if (cmd[i + 1] != NULL)
76 				(void) strcat(r, " ");
77 		}
78 	}
79 	return (r);
80 }
81 
82 static int
83 selected(uid, user, event, sf)
84 uid_t uid;
85 char	*user;
86 au_event_t	event;
87 int	sf;
88 {
89 	int	rc, sorf;
90 	char	naflags[512];
91 	struct au_mask mask;
92 
93 	mask.am_success = mask.am_failure = 0;
94 	if (uid > MAXEPHUID) {
95 		rc = getacna(naflags, 256); /* get non-attrib flags */
96 		if (rc == 0)
97 			(void) getauditflagsbin(naflags, &mask);
98 	} else {
99 		rc = au_user_mask(user, &mask);
100 	}
101 
102 	if (sf == 0)
103 		sorf = AU_PRS_SUCCESS;
104 	else if (sf == -1)
105 		sorf = AU_PRS_FAILURE;
106 	else
107 		sorf = AU_PRS_BOTH;
108 	rc = au_preselect(event, &mask, sorf, AU_PRS_REREAD);
109 	return (rc);
110 }
111 
112 void
113 audit_rexd_setup()
114 {
115 	dprintf(("audit_rexd_setup()\n"));
116 
117 	event = AUE_rexd;
118 }
119 
120 /* ARGSUSED */
121 static void
122 audit_rexd_session_setup(char *name, char *mach, uid_t uid)
123 {
124 	int			rc;
125 	au_mask_t		mask;
126 	struct auditinfo_addr	info;
127 
128 	if (getaudit_addr(&info, sizeof (info)) < 0) {
129 		perror("getaudit_addr");
130 		exit(1);
131 	}
132 
133 	info.ai_auid = uid;
134 	info.ai_asid = getpid();
135 
136 	mask.am_success = 0;
137 	mask.am_failure = 0;
138 
139 	(void) au_user_mask(name, &mask);
140 
141 	info.ai_mask.am_success  = mask.am_success;
142 	info.ai_mask.am_failure  = mask.am_failure;
143 
144 	rc = setaudit_addr(&info, sizeof (info));
145 	if (rc < 0) {
146 		perror("setaudit_addr");
147 	}
148 }
149 
150 void
151 audit_rexd_fail(msg, hostname, user, uid, gid, shell, cmd)
152 	char	*msg;		/* message containing failure information */
153 	char	*hostname;	/* hostname of machine requesting service */
154 	char	*user;		/* username of user requesting service */
155 	uid_t 	uid;		/* user id of user requesting service */
156 	gid_t	gid;		/* group of user requesting service */
157 	char	*shell;		/* login shell of user requesting service */
158 	char	**cmd;		/* argv to be executed locally */
159 {
160 	int	rd;		/* audit record descriptor */
161 	char	buf[256];	/* temporary buffer */
162 	char	*tbuf;		/* temporary buffer */
163 	int	tlen;
164 	const char *gtxt;	/* gettext return value */
165 	pid_t	pid;
166 	char	*cmdbuf;
167 	char	*audit_cmd[2] = {NULL, NULL};
168 	int	dont_free = 0;
169 	struct auditinfo_addr info;
170 
171 	dprintf(("audit_rexd_fail()\n"));
172 
173 	/*
174 	 * check if audit_rexd_fail() or audit_rexd_success()
175 	 * have been called already.
176 	 */
177 	if (audit_rexd_status == 1) {
178 		return;
179 	}
180 
181 	if (cannot_audit(0)) {
182 		return;
183 	}
184 
185 	/*
186 	 * set status to prevent multiple calls
187 	 * to audit_rexd_fail() and audit_rexd_success()
188 	 */
189 	audit_rexd_status = 1;
190 
191 	/* determine if we're preselected */
192 	if (!selected(uid, user, event, -1))
193 		return;
194 
195 	pid = getpid();
196 
197 	if (getaudit_addr(&info, sizeof (info)) < 0) {
198 		perror("getaudit_addr");
199 		exit(1);
200 	}
201 
202 	rd = au_open();
203 
204 	/* add subject token */
205 	(void) au_write(rd,
206 		au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid,
207 			&info.ai_termid));
208 	if (is_system_labeled())
209 		(void) au_write(rd, au_to_mylabel());
210 
211 	/* add reason for failure */
212 	(void) au_write(rd, au_to_text(msg));
213 
214 	/* add hostname of machine requesting service */
215 	(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
216 		"Remote execution requested by: %s"), hostname);
217 	(void) au_write(rd, au_to_text(buf));
218 
219 	/* add username of user requesting service */
220 	if (user == NULL)
221 		user = "???";
222 	(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
223 	    "Username: %s"), user);
224 	(void) au_write(rd, au_to_text(buf));
225 
226 	(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
227 	    "User id: %d"), uid);
228 	(void) au_write(rd, au_to_text(buf));
229 
230 	if (cmd == NULL) {
231 		audit_cmd[0] = shell;
232 		cmd = audit_cmd;
233 	}
234 
235 	cmdbuf = build_cmd(cmd);
236 	if (cmdbuf == NULL) {
237 		cmdbuf = UNKNOWN_CMD;
238 		dont_free = 1;
239 	}
240 
241 	gtxt = dgettext(bsm_dom, "Command line: %s");
242 	/* over estimate of size of buffer needed (%s is replaced) */
243 	tlen = strlen(cmdbuf) + strlen(gtxt) + 1;
244 
245 	if ((tbuf = malloc(tlen)) == NULL) {
246 		(void) au_close(rd, 0, 0);
247 		return;
248 	}
249 	(void) snprintf(tbuf, tlen, gtxt, cmdbuf);
250 	(void) au_write(rd, au_to_text(tbuf));
251 	(void) free(tbuf);
252 	if (!dont_free)
253 		(void) free(cmdbuf);
254 
255 	/* add return token */
256 #ifdef _LP64
257 	(void) au_write(rd, au_to_return64(-1, (int64_t)0));
258 #else
259 	(void) au_write(rd, au_to_return32(-1, (int32_t)0));
260 #endif
261 
262 	/* write audit record */
263 	if (au_close(rd, 1, event) < 0) {
264 		(void) au_close(rd, 0, 0);
265 		return;
266 	}
267 }
268 
269 void
270 audit_rexd_success(hostname, user, uid, gid, shell, cmd)
271 char	*hostname;	/* hostname of machine requesting service */
272 char	*user;		/* username of user requesting service, may be NULL */
273 uid_t 	uid;		/* user id of user requesting service */
274 gid_t	gid;		/* group of user requesting service */
275 char	*shell;		/* login shell of user requesting service */
276 char	**cmd;		/* argv to be executed locally, may be NULL */
277 {
278 	int	rd;			/* audit record descriptor */
279 	char	buf[256];	/* temporary buffer */
280 	char	*tbuf;		/* temporary buffer */
281 	int	tlen;
282 	const char *gtxt;
283 	pid_t	pid;
284 	char	*cmdbuf;
285 	char	*audit_cmd[2] = {NULL, NULL};
286 	int	dont_free = 0;
287 	struct auditinfo_addr info;
288 	char	*empty = "";
289 
290 	dprintf(("audit_rexd_success()\n"));
291 
292 	/*
293 	 * check if audit_rexd_fail() or audit_rexd_success()
294 	 * have been called already.
295 	 */
296 	if (audit_rexd_status == 1) {
297 		return;
298 	}
299 
300 	if (cannot_audit(0)) {
301 		return;
302 	}
303 
304 	/* a little bullet proofing... */
305 
306 	if (hostname == NULL)
307 		hostname = empty;
308 	if (shell == NULL)
309 		shell = empty;
310 
311 	/*
312 	 * set status to prevent multiple calls
313 	 * to audit_rexd_fail() and audit_rexd_success()
314 	 */
315 	audit_rexd_status = 1;
316 
317 	/* determine if we're preselected */
318 	if (!selected(uid, user, event, 0))
319 		goto rexd_audit_session;
320 
321 	pid = getpid();
322 
323 	if (getaudit_addr(&info, sizeof (info)) < 0) {
324 		perror("getaudit_addr");
325 		exit(1);
326 	}
327 
328 	rd = au_open();
329 
330 	/* add subject token */
331 	(void) au_write(rd,
332 		au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid,
333 			&info.ai_termid));
334 	if (is_system_labeled())
335 		(void) au_write(rd, au_to_mylabel());
336 
337 	/* add hostname of machine requesting service */
338 
339 	(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
340 		"Remote execution requested by: %s"), hostname);
341 	(void) au_write(rd, au_to_text(buf));
342 
343 	/* add username at machine requesting service */
344 	(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
345 	    "Username: %s"), user);
346 	(void) au_write(rd, au_to_text(buf));
347 
348 	if (cmd == NULL) {
349 		audit_cmd[0] = shell;
350 		cmd = audit_cmd;
351 	}
352 
353 	cmdbuf = build_cmd(cmd);
354 	if (cmdbuf == NULL) {
355 		cmdbuf = UNKNOWN_CMD;
356 		dont_free = 1;
357 	}
358 
359 	gtxt = dgettext(bsm_dom, "Command line: %s");
360 	tlen = strlen(cmdbuf) + strlen(gtxt) + 1;
361 
362 	if ((tbuf = malloc(tlen)) == NULL) {
363 		(void) au_close(rd, 0, 0);
364 		goto rexd_audit_session;
365 	}
366 
367 	(void) snprintf(tbuf, tlen, gtxt, cmdbuf);
368 	(void) au_write(rd, au_to_text(tbuf));
369 	(void) free(tbuf);
370 	if (!dont_free)
371 		(void) free(cmdbuf);
372 
373 	/* add return token */
374 #ifdef _LP64
375 	(void) au_write(rd, au_to_return64(0, (int64_t)0));
376 #else
377 	(void) au_write(rd, au_to_return32(0, (int32_t)0));
378 #endif
379 
380 	/* write audit record */
381 	if (au_close(rd, 1, event) < 0) {
382 		(void) au_close(rd, 0, 0);
383 	}
384 
385 rexd_audit_session:
386 	audit_rexd_session_setup(user, hostname, uid);
387 }
388