audit_rexecd.c revision 2
2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 1992, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <sys/types.h>
2N/A#include <stdio.h>
2N/A#include <unistd.h>
2N/A#include <sys/fcntl.h>
2N/A#include <bsm/audit.h>
2N/A#include <bsm/audit_record.h>
2N/A#include <bsm/audit_uevents.h>
2N/A#include <bsm/libbsm.h>
2N/A#include <bsm/audit_private.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A#include <syslog.h>
2N/A#include <pwd.h>
2N/A#include <netinet/in.h>
2N/A#include <tsol/label.h>
2N/A#include <locale.h>
2N/A#include "generic.h"
2N/A
2N/A#ifdef C2_DEBUG
2N/A#define dprintf(x) { (void) printf x; }
2N/A#else
2N/A#define dprintf(x)
2N/A#endif
2N/A
2N/Astatic au_event_t event;
2N/Astatic int audit_rexecd_status = 0;
2N/A
2N/Astatic int
2N/Aselected(uid, user, event, sf)
2N/Auid_t uid;
2N/Achar *user;
2N/Aau_event_t event;
2N/Aint sf;
2N/A{
2N/A int sorf;
2N/A struct au_mask mask;
2N/A
2N/A mask.am_success = mask.am_failure = AU_MASK_NONE;
2N/A if (uid > MAXEPHUID) {
2N/A /* get non-attrib flags */
2N/A (void) auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask));
2N/A } else {
2N/A (void) au_user_mask(user, &mask);
2N/A }
2N/A
2N/A if (sf == 0) {
2N/A sorf = AU_PRS_SUCCESS;
2N/A } else if (sf == -1) {
2N/A sorf = AU_PRS_FAILURE;
2N/A } else {
2N/A sorf = AU_PRS_BOTH;
2N/A }
2N/A
2N/A return (au_preselect(event, &mask, sorf, AU_PRS_REREAD));
2N/A}
2N/A
2N/Avoid
2N/Aaudit_rexecd_setup()
2N/A{
2N/A dprintf(("audit_rexecd_setup()\n"));
2N/A
2N/A event = AUE_rexecd;
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Aaudit_rexecd_session_setup(char *name, char *mach, uid_t uid)
2N/A{
2N/A int rc;
2N/A au_mask_t mask;
2N/A struct auditinfo_addr info;
2N/A uint32_t addr[4], type;
2N/A
2N/A info.ai_auid = uid;
2N/A info.ai_asid = getpid();
2N/A
2N/A mask.am_success = AU_MASK_NONE;
2N/A mask.am_failure = AU_MASK_NONE;
2N/A
2N/A (void) au_user_mask(name, &mask);
2N/A
2N/A info.ai_mask.am_success = mask.am_success;
2N/A info.ai_mask.am_failure = mask.am_failure;
2N/A
2N/A rc = aug_get_machine(mach, addr, &type);
2N/A if (rc < 0) {
2N/A perror("get address");
2N/A }
2N/A info.ai_termid.at_port = aug_get_port();
2N/A info.ai_termid.at_type = type;
2N/A info.ai_termid.at_addr[0] = addr[0];
2N/A info.ai_termid.at_addr[1] = addr[1];
2N/A info.ai_termid.at_addr[2] = addr[2];
2N/A info.ai_termid.at_addr[3] = addr[3];
2N/A
2N/A rc = setaudit_addr(&info, sizeof (info));
2N/A if (rc < 0) {
2N/A perror("setaudit");
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Aaudit_rexecd_fail(msg, hostname, user, cmdbuf)
2N/Achar *msg; /* message containing failure information */
2N/Achar *hostname; /* hostname of machine requesting service */
2N/Achar *user; /* username of user requesting service */
2N/Achar *cmdbuf; /* command line to be executed locally */
2N/A{
2N/A int rd; /* audit record descriptor */
2N/A char buf[256]; /* temporary buffer */
2N/A char *tbuf; /* temporary buffer */
2N/A int tlen;
2N/A const char *gtxt;
2N/A uid_t uid;
2N/A gid_t gid;
2N/A pid_t pid;
2N/A au_tid_addr_t tid;
2N/A struct passwd *pwd;
2N/A uint32_t addr[4], type;
2N/A int rc;
2N/A
2N/A dprintf(("audit_rexecd_fail()\n"));
2N/A
2N/A /*
2N/A * check if audit_rexecd_fail() or audit_rexecd_success()
2N/A * have been called already.
2N/A */
2N/A if (audit_rexecd_status == 1) {
2N/A return;
2N/A }
2N/A
2N/A if (cannot_audit(0)) {
2N/A return;
2N/A }
2N/A
2N/A /*
2N/A * set status to prevent multiple calls
2N/A * to audit_rexecd_fail() and audit_rexecd_success()
2N/A */
2N/A audit_rexecd_status = 1;
2N/A
2N/A pwd = getpwnam(user);
2N/A if (pwd == NULL) {
2N/A uid = (uid_t)-1;
2N/A gid = (gid_t)-1;
2N/A } else {
2N/A uid = pwd->pw_uid;
2N/A gid = pwd->pw_gid;
2N/A }
2N/A
2N/A /* determine if we're preselected */
2N/A if (!selected(uid, user, event, -1))
2N/A return;
2N/A
2N/A pid = getpid();
2N/A rc = aug_get_machine(hostname, addr, &type);
2N/A if (rc < 0) {
2N/A perror("get address");
2N/A }
2N/A
2N/A tid.at_port = aug_get_port();
2N/A tid.at_addr[0] = addr[0];
2N/A tid.at_addr[1] = addr[1];
2N/A tid.at_addr[2] = addr[2];
2N/A tid.at_addr[3] = addr[3];
2N/A tid.at_type = type;
2N/A
2N/A rd = au_open();
2N/A
2N/A /* add subject token */
2N/A (void) au_write(rd,
2N/A au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, &tid));
2N/A if (is_system_labeled())
2N/A (void) au_write(rd, au_to_mylabel());
2N/A
2N/A /* add reason for failure */
2N/A (void) au_write(rd, au_to_text(msg));
2N/A
2N/A /* add hostname of machine requesting service */
2N/A (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
2N/A "Remote execution requested by: %s"), hostname);
2N/A (void) au_write(rd, au_to_text(buf));
2N/A
2N/A /* add username of user requesting service */
2N/A (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
2N/A "Username: %s"), user);
2N/A (void) au_write(rd, au_to_text(buf));
2N/A
2N/A /* add command line to be executed locally */
2N/A gtxt = dgettext(bsm_dom, "Command line: %s");
2N/A tlen = strlen(gtxt) + strlen(cmdbuf) + 1;
2N/A if ((tbuf = malloc(tlen)) == NULL) {
2N/A (void) au_close(rd, AU_TO_NO_WRITE, 0, 0);
2N/A return;
2N/A }
2N/A (void) snprintf(tbuf, tlen, gtxt, cmdbuf);
2N/A (void) au_write(rd, au_to_text(tbuf));
2N/A (void) free(tbuf);
2N/A
2N/A /* add return token */
2N/A#ifdef _LP64
2N/A (void) au_write(rd, au_to_return64(-1, (int64_t)0));
2N/A#else
2N/A (void) au_write(rd, au_to_return32(-1, (int32_t)0));
2N/A#endif
2N/A
2N/A /* write audit record */
2N/A if (au_close(rd, AU_TO_WRITE, event, PAD_FAILURE) < 0) {
2N/A (void) au_close(rd, AU_TO_NO_WRITE, 0, 0);
2N/A return;
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Aaudit_rexecd_success(hostname, user, cmdbuf)
2N/Achar *hostname; /* hostname of machine requesting service */
2N/Achar *user; /* username of user requesting service */
2N/Achar *cmdbuf; /* command line to be executed locally */
2N/A{
2N/A int rd; /* audit record descriptor */
2N/A char buf[256]; /* temporary buffer */
2N/A char *tbuf; /* temporary buffer */
2N/A int tlen;
2N/A const char *gtxt;
2N/A uid_t uid;
2N/A gid_t gid;
2N/A pid_t pid;
2N/A au_tid_addr_t tid;
2N/A struct passwd *pwd;
2N/A uint32_t addr[4], type;
2N/A int rc;
2N/A
2N/A dprintf(("audit_rexecd_success()\n"));
2N/A
2N/A /*
2N/A * check if audit_rexecd_fail() or audit_rexecd_success()
2N/A * have been called already.
2N/A */
2N/A if (audit_rexecd_status == 1) {
2N/A return;
2N/A }
2N/A
2N/A if (cannot_audit(0)) {
2N/A return;
2N/A }
2N/A
2N/A /*
2N/A * set status to prevent multiple calls
2N/A * to audit_rexecd_fail() and audit_rexecd_success()
2N/A */
2N/A audit_rexecd_status = 1;
2N/A
2N/A pwd = getpwnam(user);
2N/A if (pwd == NULL) {
2N/A uid = (uid_t)-1;
2N/A gid = (gid_t)-1;
2N/A } else {
2N/A uid = pwd->pw_uid;
2N/A gid = pwd->pw_gid;
2N/A }
2N/A
2N/A /* determine if we're preselected */
2N/A if (!selected(uid, user, event, 0))
2N/A goto rexecd_audit_session;
2N/A
2N/A pid = getpid();
2N/A rc = aug_get_machine(hostname, addr, &type);
2N/A if (rc < 0) {
2N/A perror("get address");
2N/A }
2N/A
2N/A tid.at_port = aug_get_port();
2N/A tid.at_addr[0] = addr[0];
2N/A tid.at_addr[1] = addr[1];
2N/A tid.at_addr[2] = addr[2];
2N/A tid.at_addr[3] = addr[3];
2N/A tid.at_type = type;
2N/A
2N/A rd = au_open();
2N/A
2N/A /* add subject token */
2N/A (void) au_write(rd,
2N/A au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, &tid));
2N/A if (is_system_labeled())
2N/A (void) au_write(rd, au_to_mylabel());
2N/A
2N/A /* add hostname of machine requesting service */
2N/A (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
2N/A "Remote execution requested by: %s"), hostname);
2N/A (void) au_write(rd, au_to_text(buf));
2N/A
2N/A /* add username at machine requesting service */
2N/A (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom,
2N/A "Username: %s"), user);
2N/A (void) au_write(rd, au_to_text(buf));
2N/A
2N/A /* add command line to be executed locally */
2N/A gtxt = dgettext(bsm_dom, "Command line: %s");
2N/A tlen = strlen(gtxt) + strlen(cmdbuf) + 1;
2N/A if ((tbuf = malloc(tlen)) == NULL) {
2N/A (void) au_close(rd, AU_TO_NO_WRITE, 0, 0);
2N/A } else {
2N/A (void) snprintf(tbuf, tlen, gtxt, cmdbuf);
2N/A (void) au_write(rd, au_to_text(tbuf));
2N/A (void) free(tbuf);
2N/A
2N/A /* add return token */
2N/A#ifdef _LP64
2N/A (void) au_write(rd, au_to_return64(0, (int64_t)0));
2N/A#else
2N/A (void) au_write(rd, au_to_return32(0, (int32_t)0));
2N/A#endif
2N/A
2N/A /* write audit record */
2N/A if (au_close(rd, AU_TO_WRITE, event, 0) < 0) {
2N/A (void) au_close(rd, AU_TO_NO_WRITE, 0, 0);
2N/A }
2N/A }
2N/A
2N/Arexecd_audit_session:
2N/A audit_rexecd_session_setup(user, hostname, uid);
2N/A}