Home | History | Annotate | Download | only in common
      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