17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*f8994074SJan Friedel * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate * 247c478bd9Sstevel@tonic-gate * private interfaces for auditd plugins and auditd. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <bsm/audit.h> 287c478bd9Sstevel@tonic-gate #include <bsm/audit_record.h> 297c478bd9Sstevel@tonic-gate #include <bsm/audit_uevents.h> 307c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h> 317c478bd9Sstevel@tonic-gate #include <errno.h> 327c478bd9Sstevel@tonic-gate #include <fcntl.h> 337c478bd9Sstevel@tonic-gate #include <libintl.h> 347c478bd9Sstevel@tonic-gate #include <pthread.h> 357c478bd9Sstevel@tonic-gate #include <stdio.h> 367c478bd9Sstevel@tonic-gate #include <stdlib.h> 377c478bd9Sstevel@tonic-gate #include <string.h> 387c478bd9Sstevel@tonic-gate #include <sys/file.h> 397c478bd9Sstevel@tonic-gate #include <sys/stat.h> 407c478bd9Sstevel@tonic-gate #include <sys/types.h> 417c478bd9Sstevel@tonic-gate #include <syslog.h> 427c478bd9Sstevel@tonic-gate #include <unistd.h> 437c478bd9Sstevel@tonic-gate #include <wait.h> 447c478bd9Sstevel@tonic-gate #include "audit_plugin.h" 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate static char auditwarn[] = "/etc/security/audit_warn"; 477c478bd9Sstevel@tonic-gate static pthread_mutex_t syslog_lock; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate static void 507c478bd9Sstevel@tonic-gate init_syslog_mutex() 517c478bd9Sstevel@tonic-gate { 527c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&syslog_lock, NULL); 537c478bd9Sstevel@tonic-gate } 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* 567c478bd9Sstevel@tonic-gate * audit_syslog() -- generate syslog messages from threads that use 577c478bd9Sstevel@tonic-gate * different severity, facility code, and application names. 587c478bd9Sstevel@tonic-gate * 597c478bd9Sstevel@tonic-gate * syslog(3C) is thread safe, but the set openlog() / syslog() / 607c478bd9Sstevel@tonic-gate * closelog() is not. 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * Assumption: the app_name and facility code are paired, i.e., 637c478bd9Sstevel@tonic-gate * if the facility code for this call is the same as for the 647c478bd9Sstevel@tonic-gate * the previous, the app_name hasn't changed. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate void 67c900e163Sgww __audit_syslog(const char *app_name, int flags, int facility, int severity, 687c478bd9Sstevel@tonic-gate const char *message) 697c478bd9Sstevel@tonic-gate { 703cccda98SJan Friedel static pthread_once_t once_control = PTHREAD_ONCE_INIT; 717c478bd9Sstevel@tonic-gate static int logopen = 0; 727c478bd9Sstevel@tonic-gate static int prev_facility = -1; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate (void) pthread_once(&once_control, init_syslog_mutex); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&syslog_lock); 777c478bd9Sstevel@tonic-gate if (prev_facility != facility) { 787c478bd9Sstevel@tonic-gate if (logopen) 797c478bd9Sstevel@tonic-gate closelog(); 807c478bd9Sstevel@tonic-gate openlog(app_name, flags, facility); 81e4163c9bSpaulson syslog(severity, "%s", message); 827c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&syslog_lock); 837c478bd9Sstevel@tonic-gate } else { 84e4163c9bSpaulson syslog(severity, "%s", message); 857c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&syslog_lock); 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * __audit_dowarn - invoke the shell script auditwarn to notify the 917c478bd9Sstevel@tonic-gate * adminstrator about a given problem. 927c478bd9Sstevel@tonic-gate * parameters - 937c478bd9Sstevel@tonic-gate * option - what the problem is 947c478bd9Sstevel@tonic-gate * text - when used with options soft and hard: which file was being 957c478bd9Sstevel@tonic-gate * used when the filesystem filled up 967c478bd9Sstevel@tonic-gate * when used with the plugin option: error detail 977c478bd9Sstevel@tonic-gate * count - used with various options: how many times auditwarn has 987c478bd9Sstevel@tonic-gate * been called for this problem since it was last cleared. 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate void 1017c478bd9Sstevel@tonic-gate __audit_dowarn(char *option, char *text, int count) 1027c478bd9Sstevel@tonic-gate { 1037c478bd9Sstevel@tonic-gate pid_t pid; 1047c478bd9Sstevel@tonic-gate int st; 1057c478bd9Sstevel@tonic-gate char countstr[5]; 1067c478bd9Sstevel@tonic-gate char warnstring[80]; 1077c478bd9Sstevel@tonic-gate char empty[1] = ""; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate if ((pid = fork1()) == -1) { 1107c478bd9Sstevel@tonic-gate __audit_syslog("auditd", LOG_PID | LOG_ODELAY | LOG_CONS, 1117c478bd9Sstevel@tonic-gate LOG_DAEMON, LOG_ALERT, gettext("audit_warn fork failed\n")); 1127c478bd9Sstevel@tonic-gate return; 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate if (pid != 0) { 1157c478bd9Sstevel@tonic-gate (void) waitpid(pid, &st, 0); 1167c478bd9Sstevel@tonic-gate return; 1177c478bd9Sstevel@tonic-gate } 118*f8994074SJan Friedel (void) snprintf(countstr, 5, "%d", count); 1197c478bd9Sstevel@tonic-gate if (text == NULL) 1207c478bd9Sstevel@tonic-gate text = empty; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate if (strcmp(option, "soft") == 0 || strcmp(option, "hard") == 0) 1237c478bd9Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, text, 0); 1247c478bd9Sstevel@tonic-gate 125*f8994074SJan Friedel else if (strcmp(option, "allhard") == 0) 1267c478bd9Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, countstr, 0); 1277c478bd9Sstevel@tonic-gate else if (strcmp(option, "plugin") == 0) 1287c478bd9Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, text, countstr, 0); 1297c478bd9Sstevel@tonic-gate else 1307c478bd9Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, 0); 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * (execl failed) 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate if (strcmp(option, "soft") == 0) 135*f8994074SJan Friedel (void) snprintf(warnstring, 80, 1367c478bd9Sstevel@tonic-gate gettext("soft limit in %s.\n"), text); 1377c478bd9Sstevel@tonic-gate else if (strcmp(option, "hard") == 0) 138*f8994074SJan Friedel (void) snprintf(warnstring, 80, 1397c478bd9Sstevel@tonic-gate gettext("hard limit in %s.\n"), text); 1407c478bd9Sstevel@tonic-gate else if (strcmp(option, "allhard") == 0) 1417c478bd9Sstevel@tonic-gate (void) sprintf(warnstring, 1427c478bd9Sstevel@tonic-gate gettext("All audit filesystems are full.\n")); 1437c478bd9Sstevel@tonic-gate else 144*f8994074SJan Friedel (void) snprintf(warnstring, 80, 1457c478bd9Sstevel@tonic-gate gettext("error %s.\n"), option); 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate __audit_syslog("auditd", LOG_PID | LOG_ODELAY | LOG_CONS, LOG_AUTH, 1487c478bd9Sstevel@tonic-gate LOG_ALERT, (const char *)warnstring); 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate exit(1); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * __audit_dowarn2 - invoke the shell script auditwarn to notify the 1557c478bd9Sstevel@tonic-gate * adminstrator about a given problem. 1567c478bd9Sstevel@tonic-gate * parameters - 1577c478bd9Sstevel@tonic-gate * option - what the problem is 1587c478bd9Sstevel@tonic-gate * name - entity reporting the problem (ie, plugin name) 1597c478bd9Sstevel@tonic-gate * error - error string 1607c478bd9Sstevel@tonic-gate * text - when used with options soft and hard: which file was being 1617c478bd9Sstevel@tonic-gate * used when the filesystem filled up 1627c478bd9Sstevel@tonic-gate * when used with the plugin option: error detail 1637c478bd9Sstevel@tonic-gate * count - used with various options: how many times auditwarn has 1647c478bd9Sstevel@tonic-gate * been called for this problem since it was last cleared. 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate void 1677c478bd9Sstevel@tonic-gate __audit_dowarn2(char *option, char *name, char *error, char *text, int count) 1687c478bd9Sstevel@tonic-gate { 1697c478bd9Sstevel@tonic-gate pid_t pid; 1707c478bd9Sstevel@tonic-gate int st; 1717c478bd9Sstevel@tonic-gate char countstr[5]; 1727c478bd9Sstevel@tonic-gate char warnstring[80]; 1737c478bd9Sstevel@tonic-gate char empty[4] = "..."; 1747c478bd9Sstevel@tonic-gate char none[3] = "--"; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate if ((pid = fork()) == -1) { 1777c478bd9Sstevel@tonic-gate __audit_syslog("auditd", LOG_PID | LOG_ODELAY | LOG_CONS, 1787c478bd9Sstevel@tonic-gate LOG_DAEMON, LOG_ALERT, gettext("audit_warn fork failed\n")); 1797c478bd9Sstevel@tonic-gate return; 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate if (pid != 0) { 1827c478bd9Sstevel@tonic-gate (void) waitpid(pid, &st, 0); 1837c478bd9Sstevel@tonic-gate return; 1847c478bd9Sstevel@tonic-gate } 185*f8994074SJan Friedel (void) snprintf(countstr, 5, "%d", count); 1867c478bd9Sstevel@tonic-gate if ((text == NULL) || (*text == '\0')) 1877c478bd9Sstevel@tonic-gate text = empty; 1887c478bd9Sstevel@tonic-gate if ((name == NULL) || (*name == '\0')) 1897c478bd9Sstevel@tonic-gate name = none; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate (void) execl(auditwarn, auditwarn, option, name, error, text, 1927c478bd9Sstevel@tonic-gate countstr, 0); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * (execl failed) 1967c478bd9Sstevel@tonic-gate */ 197*f8994074SJan Friedel (void) snprintf(warnstring, 80, 198*f8994074SJan Friedel gettext("%s plugin error: %s\n"), name, text); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate __audit_syslog("auditd", LOG_PID | LOG_ODELAY | LOG_CONS, LOG_AUTH, 2017c478bd9Sstevel@tonic-gate LOG_ALERT, (const char *)warnstring); 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate exit(1); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* 207c900e163Sgww * logpost - post the new audit log file name. 2087c478bd9Sstevel@tonic-gate * 209c900e163Sgww * Entry name = active audit.log file name 210c900e163Sgww * NULL, if checking writability (auditd), 211c900e163Sgww * changing audit log files, error, or exiting (binfile). 212c900e163Sgww * 213c900e163Sgww * Exit 0 = success 214c900e163Sgww * 1 = system error -- errno 215c900e163Sgww * audit_warn called with the specific error 216c900e163Sgww * 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate int 2197c478bd9Sstevel@tonic-gate __logpost(char *name) 2207c478bd9Sstevel@tonic-gate { 221c900e163Sgww int lerrno; 2227c478bd9Sstevel@tonic-gate 223c900e163Sgww if (unlink(BINFILE_FILE) != 0 && 224c900e163Sgww errno != ENOENT) { 2257c478bd9Sstevel@tonic-gate 226c900e163Sgww lerrno = errno; 227c900e163Sgww __audit_dowarn("tmpfile", strerror(errno), 0); 228c900e163Sgww errno = lerrno; 2297c478bd9Sstevel@tonic-gate return (1); 2307c478bd9Sstevel@tonic-gate } 231c900e163Sgww if (name == NULL || *name == '\0') { 232c900e163Sgww /* audit_binfile not active, no file pointer */ 233c900e163Sgww return (0); 2347c478bd9Sstevel@tonic-gate } 235c900e163Sgww if (symlink(name, BINFILE_FILE) != 0) { 2367c478bd9Sstevel@tonic-gate 237c900e163Sgww lerrno = errno; 238c900e163Sgww __audit_dowarn("tmpfile", strerror(errno), 0); 239c900e163Sgww errno = lerrno; 240c900e163Sgww return (1); 241c900e163Sgww } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate return (0); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * debug use - open a file for auditd and its plugins for debug 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate FILE * 2507c478bd9Sstevel@tonic-gate __auditd_debug_file_open() { 2517c478bd9Sstevel@tonic-gate static FILE *fp = NULL; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate if (fp != NULL) 2547c478bd9Sstevel@tonic-gate return (fp); 255004388ebScasper if ((fp = fopen("/var/audit/dump", "aF")) == NULL) 2567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "failed to open debug file: %s\n", 2577c478bd9Sstevel@tonic-gate strerror(errno)); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate return (fp); 2607c478bd9Sstevel@tonic-gate } 261