10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51914Scasper * Common Development and Distribution License (the "License").
61914Scasper * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12918SJan.Friedel@Sun.COM * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate *
240Sstevel@tonic-gate * private interfaces for auditd plugins and auditd.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <bsm/audit.h>
280Sstevel@tonic-gate #include <bsm/audit_record.h>
290Sstevel@tonic-gate #include <bsm/audit_uevents.h>
300Sstevel@tonic-gate #include <bsm/libbsm.h>
310Sstevel@tonic-gate #include <errno.h>
320Sstevel@tonic-gate #include <fcntl.h>
330Sstevel@tonic-gate #include <libintl.h>
340Sstevel@tonic-gate #include <pthread.h>
350Sstevel@tonic-gate #include <stdio.h>
360Sstevel@tonic-gate #include <stdlib.h>
370Sstevel@tonic-gate #include <string.h>
380Sstevel@tonic-gate #include <sys/file.h>
390Sstevel@tonic-gate #include <sys/stat.h>
400Sstevel@tonic-gate #include <sys/types.h>
410Sstevel@tonic-gate #include <syslog.h>
420Sstevel@tonic-gate #include <unistd.h>
430Sstevel@tonic-gate #include <wait.h>
440Sstevel@tonic-gate #include "audit_plugin.h"
450Sstevel@tonic-gate
460Sstevel@tonic-gate static char auditwarn[] = "/etc/security/audit_warn";
470Sstevel@tonic-gate static pthread_mutex_t syslog_lock;
480Sstevel@tonic-gate
490Sstevel@tonic-gate static void
init_syslog_mutex()500Sstevel@tonic-gate init_syslog_mutex()
510Sstevel@tonic-gate {
520Sstevel@tonic-gate (void) pthread_mutex_init(&syslog_lock, NULL);
530Sstevel@tonic-gate }
540Sstevel@tonic-gate
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate * audit_syslog() -- generate syslog messages from threads that use
570Sstevel@tonic-gate * different severity, facility code, and application names.
580Sstevel@tonic-gate *
590Sstevel@tonic-gate * syslog(3C) is thread safe, but the set openlog() / syslog() /
600Sstevel@tonic-gate * closelog() is not.
610Sstevel@tonic-gate *
620Sstevel@tonic-gate * Assumption: the app_name and facility code are paired, i.e.,
630Sstevel@tonic-gate * if the facility code for this call is the same as for the
640Sstevel@tonic-gate * the previous, the app_name hasn't changed.
650Sstevel@tonic-gate */
660Sstevel@tonic-gate void
__audit_syslog(const char * app_name,int flags,int facility,int severity,const char * message)6711700Sgww@eng.sun.com __audit_syslog(const char *app_name, int flags, int facility, int severity,
6811700Sgww@eng.sun.com const char *message)
690Sstevel@tonic-gate {
707427SJan.Friedel@Sun.COM static pthread_once_t once_control = PTHREAD_ONCE_INIT;
710Sstevel@tonic-gate static int logopen = 0;
720Sstevel@tonic-gate static int prev_facility = -1;
730Sstevel@tonic-gate
740Sstevel@tonic-gate (void) pthread_once(&once_control, init_syslog_mutex);
750Sstevel@tonic-gate
760Sstevel@tonic-gate (void) pthread_mutex_lock(&syslog_lock);
770Sstevel@tonic-gate if (prev_facility != facility) {
780Sstevel@tonic-gate if (logopen)
790Sstevel@tonic-gate closelog();
800Sstevel@tonic-gate openlog(app_name, flags, facility);
812540Spaulson syslog(severity, "%s", message);
820Sstevel@tonic-gate (void) pthread_mutex_unlock(&syslog_lock);
830Sstevel@tonic-gate } else {
842540Spaulson syslog(severity, "%s", message);
850Sstevel@tonic-gate (void) pthread_mutex_unlock(&syslog_lock);
860Sstevel@tonic-gate }
870Sstevel@tonic-gate }
880Sstevel@tonic-gate
890Sstevel@tonic-gate /*
900Sstevel@tonic-gate * __audit_dowarn - invoke the shell script auditwarn to notify the
910Sstevel@tonic-gate * adminstrator about a given problem.
920Sstevel@tonic-gate * parameters -
930Sstevel@tonic-gate * option - what the problem is
940Sstevel@tonic-gate * text - when used with options soft and hard: which file was being
950Sstevel@tonic-gate * used when the filesystem filled up
960Sstevel@tonic-gate * when used with the plugin option: error detail
970Sstevel@tonic-gate * count - used with various options: how many times auditwarn has
980Sstevel@tonic-gate * been called for this problem since it was last cleared.
990Sstevel@tonic-gate */
1000Sstevel@tonic-gate void
__audit_dowarn(char * option,char * text,int count)1010Sstevel@tonic-gate __audit_dowarn(char *option, char *text, int count)
1020Sstevel@tonic-gate {
1030Sstevel@tonic-gate pid_t pid;
1040Sstevel@tonic-gate int st;
1050Sstevel@tonic-gate char countstr[5];
1060Sstevel@tonic-gate char warnstring[80];
1070Sstevel@tonic-gate char empty[1] = "";
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate if ((pid = fork1()) == -1) {
1100Sstevel@tonic-gate __audit_syslog("auditd", LOG_PID | LOG_ODELAY | LOG_CONS,
1110Sstevel@tonic-gate LOG_DAEMON, LOG_ALERT, gettext("audit_warn fork failed\n"));
1120Sstevel@tonic-gate return;
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate if (pid != 0) {
1150Sstevel@tonic-gate (void) waitpid(pid, &st, 0);
1160Sstevel@tonic-gate return;
1170Sstevel@tonic-gate }
118*12918SJan.Friedel@Sun.COM (void) snprintf(countstr, 5, "%d", count);
1190Sstevel@tonic-gate if (text == NULL)
1200Sstevel@tonic-gate text = empty;
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate if (strcmp(option, "soft") == 0 || strcmp(option, "hard") == 0)
1230Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, text, 0);
1240Sstevel@tonic-gate
125*12918SJan.Friedel@Sun.COM else if (strcmp(option, "allhard") == 0)
1260Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, countstr, 0);
1270Sstevel@tonic-gate else if (strcmp(option, "plugin") == 0)
1280Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, text, countstr, 0);
1290Sstevel@tonic-gate else
1300Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, 0);
1310Sstevel@tonic-gate /*
1320Sstevel@tonic-gate * (execl failed)
1330Sstevel@tonic-gate */
1340Sstevel@tonic-gate if (strcmp(option, "soft") == 0)
135*12918SJan.Friedel@Sun.COM (void) snprintf(warnstring, 80,
1360Sstevel@tonic-gate gettext("soft limit in %s.\n"), text);
1370Sstevel@tonic-gate else if (strcmp(option, "hard") == 0)
138*12918SJan.Friedel@Sun.COM (void) snprintf(warnstring, 80,
1390Sstevel@tonic-gate gettext("hard limit in %s.\n"), text);
1400Sstevel@tonic-gate else if (strcmp(option, "allhard") == 0)
1410Sstevel@tonic-gate (void) sprintf(warnstring,
1420Sstevel@tonic-gate gettext("All audit filesystems are full.\n"));
1430Sstevel@tonic-gate else
144*12918SJan.Friedel@Sun.COM (void) snprintf(warnstring, 80,
1450Sstevel@tonic-gate gettext("error %s.\n"), option);
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate __audit_syslog("auditd", LOG_PID | LOG_ODELAY | LOG_CONS, LOG_AUTH,
1480Sstevel@tonic-gate LOG_ALERT, (const char *)warnstring);
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate exit(1);
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate /*
1540Sstevel@tonic-gate * __audit_dowarn2 - invoke the shell script auditwarn to notify the
1550Sstevel@tonic-gate * adminstrator about a given problem.
1560Sstevel@tonic-gate * parameters -
1570Sstevel@tonic-gate * option - what the problem is
1580Sstevel@tonic-gate * name - entity reporting the problem (ie, plugin name)
1590Sstevel@tonic-gate * error - error string
1600Sstevel@tonic-gate * text - when used with options soft and hard: which file was being
1610Sstevel@tonic-gate * used when the filesystem filled up
1620Sstevel@tonic-gate * when used with the plugin option: error detail
1630Sstevel@tonic-gate * count - used with various options: how many times auditwarn has
1640Sstevel@tonic-gate * been called for this problem since it was last cleared.
1650Sstevel@tonic-gate */
1660Sstevel@tonic-gate void
__audit_dowarn2(char * option,char * name,char * error,char * text,int count)1670Sstevel@tonic-gate __audit_dowarn2(char *option, char *name, char *error, char *text, int count)
1680Sstevel@tonic-gate {
1690Sstevel@tonic-gate pid_t pid;
1700Sstevel@tonic-gate int st;
1710Sstevel@tonic-gate char countstr[5];
1720Sstevel@tonic-gate char warnstring[80];
1730Sstevel@tonic-gate char empty[4] = "...";
1740Sstevel@tonic-gate char none[3] = "--";
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate if ((pid = fork()) == -1) {
1770Sstevel@tonic-gate __audit_syslog("auditd", LOG_PID | LOG_ODELAY | LOG_CONS,
1780Sstevel@tonic-gate LOG_DAEMON, LOG_ALERT, gettext("audit_warn fork failed\n"));
1790Sstevel@tonic-gate return;
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate if (pid != 0) {
1820Sstevel@tonic-gate (void) waitpid(pid, &st, 0);
1830Sstevel@tonic-gate return;
1840Sstevel@tonic-gate }
185*12918SJan.Friedel@Sun.COM (void) snprintf(countstr, 5, "%d", count);
1860Sstevel@tonic-gate if ((text == NULL) || (*text == '\0'))
1870Sstevel@tonic-gate text = empty;
1880Sstevel@tonic-gate if ((name == NULL) || (*name == '\0'))
1890Sstevel@tonic-gate name = none;
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, name, error, text,
1920Sstevel@tonic-gate countstr, 0);
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate /*
1950Sstevel@tonic-gate * (execl failed)
1960Sstevel@tonic-gate */
197*12918SJan.Friedel@Sun.COM (void) snprintf(warnstring, 80,
198*12918SJan.Friedel@Sun.COM gettext("%s plugin error: %s\n"), name, text);
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate __audit_syslog("auditd", LOG_PID | LOG_ODELAY | LOG_CONS, LOG_AUTH,
2010Sstevel@tonic-gate LOG_ALERT, (const char *)warnstring);
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate exit(1);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate /*
20711700Sgww@eng.sun.com * logpost - post the new audit log file name.
2080Sstevel@tonic-gate *
20911700Sgww@eng.sun.com * Entry name = active audit.log file name
21011700Sgww@eng.sun.com * NULL, if checking writability (auditd),
21111700Sgww@eng.sun.com * changing audit log files, error, or exiting (binfile).
21211700Sgww@eng.sun.com *
21311700Sgww@eng.sun.com * Exit 0 = success
21411700Sgww@eng.sun.com * 1 = system error -- errno
21511700Sgww@eng.sun.com * audit_warn called with the specific error
21611700Sgww@eng.sun.com *
2170Sstevel@tonic-gate */
2180Sstevel@tonic-gate int
__logpost(char * name)2190Sstevel@tonic-gate __logpost(char *name)
2200Sstevel@tonic-gate {
22111700Sgww@eng.sun.com int lerrno;
2220Sstevel@tonic-gate
22311700Sgww@eng.sun.com if (unlink(BINFILE_FILE) != 0 &&
22411700Sgww@eng.sun.com errno != ENOENT) {
2250Sstevel@tonic-gate
22611700Sgww@eng.sun.com lerrno = errno;
22711700Sgww@eng.sun.com __audit_dowarn("tmpfile", strerror(errno), 0);
22811700Sgww@eng.sun.com errno = lerrno;
22911700Sgww@eng.sun.com return (1);
2300Sstevel@tonic-gate }
23111700Sgww@eng.sun.com if (name == NULL || *name == '\0') {
23211700Sgww@eng.sun.com /* audit_binfile not active, no file pointer */
23311700Sgww@eng.sun.com return (0);
23411700Sgww@eng.sun.com }
23511700Sgww@eng.sun.com if (symlink(name, BINFILE_FILE) != 0) {
2360Sstevel@tonic-gate
23711700Sgww@eng.sun.com lerrno = errno;
23811700Sgww@eng.sun.com __audit_dowarn("tmpfile", strerror(errno), 0);
23911700Sgww@eng.sun.com errno = lerrno;
24011700Sgww@eng.sun.com return (1);
24111700Sgww@eng.sun.com }
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate return (0);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * debug use - open a file for auditd and its plugins for debug
2480Sstevel@tonic-gate */
2490Sstevel@tonic-gate FILE *
__auditd_debug_file_open()2500Sstevel@tonic-gate __auditd_debug_file_open() {
2510Sstevel@tonic-gate static FILE *fp = NULL;
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate if (fp != NULL)
2540Sstevel@tonic-gate return (fp);
2551914Scasper if ((fp = fopen("/var/audit/dump", "aF")) == NULL)
2560Sstevel@tonic-gate (void) fprintf(stderr, "failed to open debug file: %s\n",
2570Sstevel@tonic-gate strerror(errno));
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate return (fp);
2600Sstevel@tonic-gate }
261