xref: /illumos-gate/usr/src/lib/libbsm/common/audit_rexecd.c (revision 8fc99e42676a23421c75e76660640f9765d693b1)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <sys/fcntl.h>
30 #include <bsm/audit.h>
31 #include <bsm/audit_record.h>
32 #include <bsm/audit_uevents.h>
33 #include <bsm/libbsm.h>
34 #include <bsm/audit_private.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <syslog.h>
38 #include <pwd.h>
39 #include <netinet/in.h>
40 #include <tsol/label.h>
41 #include <locale.h>
42 #include "generic.h"
43 
44 #ifdef C2_DEBUG
45 #define	dprintf(x) { (void) printf x; }
46 #else
47 #define	dprintf(x)
48 #endif
49 
50 static au_event_t	event;
51 static int		audit_rexecd_status = 0;
52 
53 static int
54 selected(uid, user, event, sf)
55 uid_t uid;
56 char	*user;
57 au_event_t	event;
58 int	sf;
59 {
60 	int	rc, sorf;
61 	char	naflags[512];
62 	struct au_mask mask;
63 
64 	mask.am_success = mask.am_failure = 0;
65 	if (uid > MAXEPHUID) {
66 		rc = getacna(naflags, 256); /* get non-attrib flags */
67 		if (rc == 0)
68 			(void) getauditflagsbin(naflags, &mask);
69 	} else {
70 		rc = au_user_mask(user, &mask);
71 	}
72 
73 	if (sf == 0)
74 		sorf = AU_PRS_SUCCESS;
75 	else if (sf == -1)
76 		sorf = AU_PRS_FAILURE;
77 	else
78 		sorf = AU_PRS_BOTH;
79 	rc = au_preselect(event, &mask, sorf, AU_PRS_REREAD);
80 	return (rc);
81 }
82 
83 void
84 audit_rexecd_setup()
85 {
86 	dprintf(("audit_rexecd_setup()\n"));
87 
88 	event = AUE_rexecd;
89 }
90 
91 
92 static void
93 audit_rexecd_session_setup(char *name, char *mach, uid_t uid)
94 {
95 	int			rc;
96 	au_mask_t		mask;
97 	struct auditinfo_addr	info;
98 	uint32_t addr[4], type;
99 
100 	info.ai_auid = uid;
101 	info.ai_asid = getpid();
102 
103 	mask.am_success = 0;
104 	mask.am_failure = 0;
105 
106 	(void) au_user_mask(name, &mask);
107 
108 	info.ai_mask.am_success  = mask.am_success;
109 	info.ai_mask.am_failure  = mask.am_failure;
110 
111 	rc = aug_get_machine(mach, addr, &type);
112 	if (rc < 0) {
113 		perror("get address");
114 	}
115 	info.ai_termid.at_port = aug_get_port();
116 	info.ai_termid.at_type    = type;
117 	info.ai_termid.at_addr[0] = addr[0];
118 	info.ai_termid.at_addr[1] = addr[1];
119 	info.ai_termid.at_addr[2] = addr[2];
120 	info.ai_termid.at_addr[3] = addr[3];
121 
122 	rc = setaudit_addr(&info, sizeof (info));
123 	if (rc < 0) {
124 		perror("setaudit");
125 	}
126 }
127 
128 void
129 audit_rexecd_fail(msg, hostname, user, cmdbuf)
130 char	*msg;		/* message containing failure information */
131 char	*hostname;	/* hostname of machine requesting service */
132 char	*user;		/* username of user requesting service */
133 char	*cmdbuf;	/* command line to be executed locally */
134 {
135 	int	rd;		/* audit record descriptor */
136 	char	buf[256];	/* temporary buffer */
137 	char	*tbuf;		/* temporary buffer */
138 	int	tlen;
139 	const char *gtxt;
140 	uid_t 	uid;
141 	gid_t	gid;
142 	pid_t	pid;
143 	au_tid_addr_t	tid;
144 	struct passwd	*pwd;
145 	uint32_t addr[4], type;
146 	int rc;
147 
148 	dprintf(("audit_rexecd_fail()\n"));
149 
150 	/*
151 	 * check if audit_rexecd_fail() or audit_rexecd_success()
152 	 * have been called already.
153 	 */
154 	if (audit_rexecd_status == 1) {
155 		return;
156 	}
157 
158 	if (cannot_audit(0)) {
159 		return;
160 	}
161 
162 	/*
163 	 * set status to prevent multiple calls
164 	 * to audit_rexecd_fail() and audit_rexecd_success()
165 	 */
166 	audit_rexecd_status = 1;
167 
168 	pwd = getpwnam(user);
169 	if (pwd == NULL) {
170 		uid = (uid_t)-1;
171 		gid = (gid_t)-1;
172 	} else {
173 		uid = pwd->pw_uid;
174 		gid = pwd->pw_gid;
175 	}
176 
177 	/* determine if we're preselected */
178 	if (!selected(uid, user, event, -1))
179 		return;
180 
181 	pid = getpid();
182 	rc = aug_get_machine(hostname, addr, &type);
183 	if (rc < 0) {
184 		perror("get address");
185 	}
186 
187 	tid.at_port    = aug_get_port();
188 	tid.at_addr[0] = addr[0];
189 	tid.at_addr[1] = addr[1];
190 	tid.at_addr[2] = addr[2];
191 	tid.at_addr[3] = addr[3];
192 	tid.at_type    = type;
193 
194 	rd = au_open();
195 
196 	/* add subject token */
197 	(void) au_write(rd,
198 		au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, &tid));
199 	if (is_system_labeled())
200 		(void) au_write(rd, au_to_mylabel());
201 
202 	/* add reason for failure */
203 	(void) au_write(rd, au_to_text(msg));
204 
205 	/* add hostname of machine requesting service */
206 	(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
207 		"Remote execution requested by: %s"), hostname);
208 	(void) au_write(rd, au_to_text(buf));
209 
210 	/* add username of user requesting service */
211 	(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
212 		"Username: %s"), user);
213 	(void) au_write(rd, au_to_text(buf));
214 
215 	/* add command line to be executed locally */
216 	gtxt = dgettext(bsm_dom, "Command line: %s");
217 	tlen = strlen(gtxt) + strlen(cmdbuf) + 1;
218 	if ((tbuf = malloc(tlen)) == NULL) {
219 		(void) au_close(rd, 0, 0);
220 		return;
221 	}
222 	(void) snprintf(tbuf, tlen, gtxt, cmdbuf);
223 	(void) au_write(rd, au_to_text(tbuf));
224 	(void) free(tbuf);
225 
226 	/* add return token */
227 #ifdef _LP64
228 	(void) au_write(rd, au_to_return64(-1, (int64_t)0));
229 #else
230 	(void) au_write(rd, au_to_return32(-1, (int32_t)0));
231 #endif
232 
233 	/* write audit record */
234 	if (au_close(rd, 1, event) < 0) {
235 		(void) au_close(rd, 0, 0);
236 		return;
237 	}
238 }
239 
240 void
241 audit_rexecd_success(hostname, user, cmdbuf)
242 char	*hostname;	/* hostname of machine requesting service */
243 char	*user;		/* username of user requesting service */
244 char	*cmdbuf;	/* command line to be executed locally */
245 {
246 	int	rd;		/* audit record descriptor */
247 	char	buf[256];	/* temporary buffer */
248 	char	*tbuf;		/* temporary buffer */
249 	int	tlen;
250 	const char *gtxt;
251 	uid_t 	uid;
252 	gid_t	gid;
253 	pid_t	pid;
254 	au_tid_addr_t	tid;
255 	struct passwd	*pwd;
256 	uint32_t addr[4], type;
257 	int rc;
258 
259 	dprintf(("audit_rexecd_success()\n"));
260 
261 	/*
262 	 * check if audit_rexecd_fail() or audit_rexecd_success()
263 	 * have been called already.
264 	 */
265 	if (audit_rexecd_status == 1) {
266 		return;
267 	}
268 
269 	if (cannot_audit(0)) {
270 		return;
271 	}
272 
273 	/*
274 	 * set status to prevent multiple calls
275 	 * to audit_rexecd_fail() and audit_rexecd_success()
276 	 */
277 	audit_rexecd_status = 1;
278 
279 	pwd = getpwnam(user);
280 	if (pwd == NULL) {
281 		uid = (uid_t)-1;
282 		gid = (gid_t)-1;
283 	} else {
284 		uid = pwd->pw_uid;
285 		gid = pwd->pw_gid;
286 	}
287 
288 	/* determine if we're preselected */
289 	if (!selected(uid, user, event, 0))
290 		goto rexecd_audit_session;
291 
292 	pid = getpid();
293 	rc = aug_get_machine(hostname, addr, &type);
294 	if (rc < 0) {
295 		perror("get address");
296 	}
297 
298 	tid.at_port    = aug_get_port();
299 	tid.at_addr[0] = addr[0];
300 	tid.at_addr[1] = addr[1];
301 	tid.at_addr[2] = addr[2];
302 	tid.at_addr[3] = addr[3];
303 	tid.at_type    = type;
304 
305 	rd = au_open();
306 
307 	/* add subject token */
308 	(void) au_write(rd,
309 		au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, &tid));
310 	if (is_system_labeled())
311 		(void) au_write(rd, au_to_mylabel());
312 
313 	/* add hostname of machine requesting service */
314 	(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
315 		"Remote execution requested by: %s"), hostname);
316 	(void) au_write(rd, au_to_text(buf));
317 
318 	/* add username at machine requesting service */
319 	(void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
320 	    "Username: %s"), user);
321 	(void) au_write(rd, au_to_text(buf));
322 
323 	/* add command line to be executed locally */
324 	gtxt = dgettext(bsm_dom, "Command line: %s");
325 	tlen = strlen(gtxt) + strlen(cmdbuf) + 1;
326 	if ((tbuf = malloc(tlen)) == NULL) {
327 		(void) au_close(rd, 0, 0);
328 	} else {
329 		(void) snprintf(tbuf, tlen, gtxt, cmdbuf);
330 		(void) au_write(rd, au_to_text(tbuf));
331 		(void) free(tbuf);
332 
333 		/* add return token */
334 #ifdef _LP64
335 		(void) au_write(rd, au_to_return64(0, (int64_t)0));
336 #else
337 		(void) au_write(rd, au_to_return32(0, (int32_t)0));
338 #endif
339 
340 		/* write audit record */
341 		if (au_close(rd, 1, event) < 0) {
342 			(void) au_close(rd, 0, 0);
343 		}
344 	}
345 
346 rexecd_audit_session:
347 	audit_rexecd_session_setup(user, hostname, uid);
348 }
349