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