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