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 51a578a15Spaulson * Common Development and Distribution License (the "License"). 61a578a15Spaulson * 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) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate * 247c478bd9Sstevel@tonic-gate * write binary audit records directly to a file. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #define DEBUG 0 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #if DEBUG 30dfc7be02SJan Friedel #define DPRINT(x) { (void) fprintf x; } 317c478bd9Sstevel@tonic-gate #else 327c478bd9Sstevel@tonic-gate #define DPRINT(x) 337c478bd9Sstevel@tonic-gate #endif 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate /* 367c478bd9Sstevel@tonic-gate * auditd_plugin_open(), auditd_plugin() and auditd_plugin_close() 377c478bd9Sstevel@tonic-gate * implement a replacable library for use by auditd; they are a 387c478bd9Sstevel@tonic-gate * project private interface and may change without notice. 397c478bd9Sstevel@tonic-gate * 407c478bd9Sstevel@tonic-gate */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include <assert.h> 437c478bd9Sstevel@tonic-gate #include <bsm/audit.h> 447c478bd9Sstevel@tonic-gate #include <bsm/audit_record.h> 457c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h> 467c478bd9Sstevel@tonic-gate #include <errno.h> 477c478bd9Sstevel@tonic-gate #include <fcntl.h> 487c478bd9Sstevel@tonic-gate #include <libintl.h> 497c478bd9Sstevel@tonic-gate #include <netdb.h> 507c478bd9Sstevel@tonic-gate #include <pthread.h> 517c478bd9Sstevel@tonic-gate #include <secdb.h> 527c478bd9Sstevel@tonic-gate #include <signal.h> 537c478bd9Sstevel@tonic-gate #include <stdio.h> 547c478bd9Sstevel@tonic-gate #include <stdlib.h> 557c478bd9Sstevel@tonic-gate #include <string.h> 567c478bd9Sstevel@tonic-gate #include <sys/param.h> 577c478bd9Sstevel@tonic-gate #include <sys/types.h> 587c478bd9Sstevel@tonic-gate #include <time.h> 597c478bd9Sstevel@tonic-gate #include <tzfile.h> 607c478bd9Sstevel@tonic-gate #include <unistd.h> 617c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 62f7092930Spr131582 #include <limits.h> 63f7092930Spr131582 #include <syslog.h> 647c478bd9Sstevel@tonic-gate #include <security/auditd.h> 657c478bd9Sstevel@tonic-gate #include <audit_plugin.h> 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #define AUDIT_DATE_SZ 14 687c478bd9Sstevel@tonic-gate #define AUDIT_FNAME_SZ 2 * AUDIT_DATE_SZ + 2 + MAXHOSTNAMELEN 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* per-directory status */ 717c478bd9Sstevel@tonic-gate #define SOFT_SPACE 0 /* minfree or less space available */ 727c478bd9Sstevel@tonic-gate #define PLENTY_SPACE 1 /* more than minfree available */ 737c478bd9Sstevel@tonic-gate #define SPACE_FULL 2 /* out of space */ 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate #define AVAIL_MIN 50 /* If there are less that this number */ 767c478bd9Sstevel@tonic-gate /* of blocks avail, the filesystem is */ 777c478bd9Sstevel@tonic-gate /* presumed full. */ 787c478bd9Sstevel@tonic-gate 791a578a15Spaulson #define ALLHARD_DELAY 20 /* Call audit_warn(allhard) every 20 seconds */ 801a578a15Spaulson 81f7092930Spr131582 /* minimum reasonable size in bytes to roll over an audit file */ 82f7092930Spr131582 #define FSIZE_MIN 512000 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * The directory list is a circular linked list. It is pointed into by 867c478bd9Sstevel@tonic-gate * activeDir. Each element contains the pointer to the next 877c478bd9Sstevel@tonic-gate * element, the directory pathname, a flag for how much space there is 887c478bd9Sstevel@tonic-gate * in the directory's filesystem, and a file handle. Since a new 897c478bd9Sstevel@tonic-gate * directory list can be created from auditd_plugin_open() while the 907c478bd9Sstevel@tonic-gate * current list is in use, activeDir is protected by log_mutex. 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate typedef struct dirlist_s dirlist_t; 937c478bd9Sstevel@tonic-gate struct dirlist_s { 947c478bd9Sstevel@tonic-gate dirlist_t *dl_next; 957c478bd9Sstevel@tonic-gate int dl_space; 967c478bd9Sstevel@tonic-gate int dl_flags; 977c478bd9Sstevel@tonic-gate char *dl_dirname; 987c478bd9Sstevel@tonic-gate char *dl_filename; /* file name (not path) if open */ 997c478bd9Sstevel@tonic-gate int dl_fd; /* file handle, -1 unless open */ 1007c478bd9Sstevel@tonic-gate }; 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * Defines for dl_flags 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate #define SOFT_WARNED 0x0001 /* already did soft warning for this dir */ 1057c478bd9Sstevel@tonic-gate #define HARD_WARNED 0x0002 /* already did hard warning for this dir */ 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate #if DEBUG 1087c478bd9Sstevel@tonic-gate static FILE *dbfp; /* debug file */ 1097c478bd9Sstevel@tonic-gate #endif 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate static pthread_mutex_t log_mutex; 1127c478bd9Sstevel@tonic-gate static int binfile_is_open = 0; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static int minfree = -1; 1157c478bd9Sstevel@tonic-gate static int minfreeblocks; /* minfree in blocks */ 1167c478bd9Sstevel@tonic-gate 117*f8994074SJan Friedel static dirlist_t *lastOpenDir = NULL; /* last activeDir */ 118*f8994074SJan Friedel static dirlist_t *activeDir = NULL; /* to be current directory */ 1191a578a15Spaulson static dirlist_t *startdir; /* first dir in the ring */ 1207c478bd9Sstevel@tonic-gate static int activeCount = 0; /* number of dirs in the ring */ 1217c478bd9Sstevel@tonic-gate 1221a578a15Spaulson static int openNewFile = 0; /* need to open a new file */ 1237c478bd9Sstevel@tonic-gate static int hung_count = 0; /* count of audit_warn hard */ 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* flag from audit_plugin_open to audit_plugin_close */ 1267c478bd9Sstevel@tonic-gate static int am_open = 0; 1277c478bd9Sstevel@tonic-gate /* preferred dir state */ 1287c478bd9Sstevel@tonic-gate static int fullness_state = PLENTY_SPACE; 1297c478bd9Sstevel@tonic-gate 130f7092930Spr131582 /* 131f7092930Spr131582 * These are used to implement a maximum size for the auditing 132f7092930Spr131582 * file. binfile_maxsize is set via the 'p_fsize' parameter to the 133f7092930Spr131582 * audit_binfile plugin. 134f7092930Spr131582 */ 135f7092930Spr131582 static uint_t binfile_cursize = 0; 136f7092930Spr131582 static uint_t binfile_maxsize = 0; 137f7092930Spr131582 1387c478bd9Sstevel@tonic-gate static int open_log(dirlist_t *); 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate static void 1417c478bd9Sstevel@tonic-gate freedirlist(dirlist_t *head) 1427c478bd9Sstevel@tonic-gate { 1437c478bd9Sstevel@tonic-gate dirlist_t *n1, *n2; 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * Free up the old directory list if any 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate if (head != NULL) { 1487c478bd9Sstevel@tonic-gate n1 = head; 1497c478bd9Sstevel@tonic-gate do { 1507c478bd9Sstevel@tonic-gate n2 = n1->dl_next; 1517c478bd9Sstevel@tonic-gate free(n1->dl_dirname); 1527c478bd9Sstevel@tonic-gate free(n1->dl_filename); 1537c478bd9Sstevel@tonic-gate free(n1); 1547c478bd9Sstevel@tonic-gate n1 = n2; 1557c478bd9Sstevel@tonic-gate } while (n1 != head); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 159*f8994074SJan Friedel dirlist_t * 160*f8994074SJan Friedel dupdirnode(dirlist_t *node_orig) 161*f8994074SJan Friedel { 162*f8994074SJan Friedel dirlist_t *node_new; 163*f8994074SJan Friedel 164*f8994074SJan Friedel if ((node_new = calloc(1, sizeof (dirlist_t))) == NULL) { 165*f8994074SJan Friedel return (NULL); 166*f8994074SJan Friedel } 167*f8994074SJan Friedel 168*f8994074SJan Friedel if (node_orig->dl_dirname != NULL && 169*f8994074SJan Friedel (node_new->dl_dirname = strdup(node_orig->dl_dirname)) == NULL || 170*f8994074SJan Friedel node_orig->dl_filename != NULL && 171*f8994074SJan Friedel (node_new->dl_filename = strdup(node_orig->dl_filename)) == NULL) { 172*f8994074SJan Friedel freedirlist(node_new); 173*f8994074SJan Friedel return (NULL); 174*f8994074SJan Friedel } 175*f8994074SJan Friedel 176*f8994074SJan Friedel node_new->dl_next = node_new; 177*f8994074SJan Friedel node_new->dl_space = node_orig->dl_space; 178*f8994074SJan Friedel node_new->dl_flags = node_orig->dl_flags; 179*f8994074SJan Friedel node_new->dl_fd = node_orig->dl_fd; 180*f8994074SJan Friedel 181*f8994074SJan Friedel return (node_new); 182*f8994074SJan Friedel } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * add to a linked list of directories available for writing 1867c478bd9Sstevel@tonic-gate * 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate static int 1897c478bd9Sstevel@tonic-gate growauditlist(dirlist_t **listhead, char *dirlist, 1907c478bd9Sstevel@tonic-gate dirlist_t *endnode, int *count) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate dirlist_t *node; 1937c478bd9Sstevel@tonic-gate char *bs, *be; 1947c478bd9Sstevel@tonic-gate dirlist_t **node_p; 1957c478bd9Sstevel@tonic-gate char *dirname; 1967c478bd9Sstevel@tonic-gate char *remainder; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: dirlist=%s\n", dirlist)); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate if (*listhead == NULL) 2017c478bd9Sstevel@tonic-gate node_p = listhead; 2027c478bd9Sstevel@tonic-gate else 2037c478bd9Sstevel@tonic-gate node_p = &(endnode->dl_next); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate node = NULL; 2067c478bd9Sstevel@tonic-gate while ((dirname = strtok_r(dirlist, ",", &remainder)) != NULL) { 2077c478bd9Sstevel@tonic-gate dirlist = NULL; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: p_dir = %s\n", dirname)); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate (*count)++; 2127c478bd9Sstevel@tonic-gate node = malloc(sizeof (dirlist_t)); 2137c478bd9Sstevel@tonic-gate if (node == NULL) 2147c478bd9Sstevel@tonic-gate return (AUDITD_NO_MEMORY); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate node->dl_flags = 0; 2177c478bd9Sstevel@tonic-gate node->dl_filename = NULL; 2187c478bd9Sstevel@tonic-gate node->dl_fd = -1; 2197c478bd9Sstevel@tonic-gate node->dl_space = PLENTY_SPACE; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate node->dl_dirname = malloc((unsigned)strlen(dirname) + 1); 2227c478bd9Sstevel@tonic-gate if (node->dl_dirname == NULL) 2237c478bd9Sstevel@tonic-gate return (AUDITD_NO_MEMORY); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate bs = dirname; 2267c478bd9Sstevel@tonic-gate while ((*bs == ' ') || (*bs == '\t')) /* trim blanks */ 2277c478bd9Sstevel@tonic-gate bs++; 2287c478bd9Sstevel@tonic-gate be = bs + strlen(bs) - 1; 2297c478bd9Sstevel@tonic-gate while (be > bs) { /* trim trailing blanks */ 2307c478bd9Sstevel@tonic-gate if ((*bs != ' ') && (*bs != '\t')) 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate be--; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate *(be + 1) = '\0'; 2357c478bd9Sstevel@tonic-gate (void) strlcpy(node->dl_dirname, bs, AUDIT_FNAME_SZ); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate if (*listhead != NULL) 2387c478bd9Sstevel@tonic-gate node->dl_next = *listhead; 2397c478bd9Sstevel@tonic-gate else 2407c478bd9Sstevel@tonic-gate node->dl_next = node; 2417c478bd9Sstevel@tonic-gate *node_p = node; 2427c478bd9Sstevel@tonic-gate node_p = &(node->dl_next); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate return (0); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * create a linked list of directories available for writing 2507c478bd9Sstevel@tonic-gate * 2517c478bd9Sstevel@tonic-gate * if a list already exists, the two are compared and the new one is 2527c478bd9Sstevel@tonic-gate * used only if it is different than the old. 2537c478bd9Sstevel@tonic-gate * 2547c478bd9Sstevel@tonic-gate * returns -2 for new or changed list, 0 for unchanged list and -1 for 2557c478bd9Sstevel@tonic-gate * error. (Positive returns are for AUDITD_<error code> values) 2567c478bd9Sstevel@tonic-gate * 2577c478bd9Sstevel@tonic-gate */ 2587c478bd9Sstevel@tonic-gate static int 2597c478bd9Sstevel@tonic-gate loadauditlist(char *dirstr, char *minfreestr) 2607c478bd9Sstevel@tonic-gate { 261*f8994074SJan Friedel dirlist_t *n1, *n2; 2627c478bd9Sstevel@tonic-gate dirlist_t *listhead = NULL; 2637c478bd9Sstevel@tonic-gate dirlist_t *thisdir; 2647c478bd9Sstevel@tonic-gate int node_count = 0; 2657c478bd9Sstevel@tonic-gate int rc; 2667c478bd9Sstevel@tonic-gate int temp_minfree; 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate static dirlist_t *activeList = NULL; /* directory list */ 2697c478bd9Sstevel@tonic-gate 270*f8994074SJan Friedel DPRINT((dbfp, "binfile: Loading audit list from audit service " 271*f8994074SJan Friedel "(audit_binfile)\n")); 2727c478bd9Sstevel@tonic-gate 273*f8994074SJan Friedel if (dirstr == NULL || minfreestr == NULL) { 274*f8994074SJan Friedel DPRINT((dbfp, "binfile: internal error")); 2757c478bd9Sstevel@tonic-gate return (-1); 2767c478bd9Sstevel@tonic-gate } 277*f8994074SJan Friedel if ((rc = growauditlist(&listhead, dirstr, NULL, &node_count)) != 0) { 2787c478bd9Sstevel@tonic-gate return (rc); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate if (node_count == 0) { 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * there was a problem getting the directory 283*f8994074SJan Friedel * list or remote host info from the audit_binfile 284*f8994074SJan Friedel * configuration even though auditd thought there was 285*f8994074SJan Friedel * at least 1 good entry 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: " 2887c478bd9Sstevel@tonic-gate "problem getting directory / libpath list " 289*f8994074SJan Friedel "from audit_binfile configuration.\n")); 2907c478bd9Sstevel@tonic-gate return (-1); 2917c478bd9Sstevel@tonic-gate } 292*f8994074SJan Friedel 2937c478bd9Sstevel@tonic-gate #if DEBUG 2947c478bd9Sstevel@tonic-gate /* print out directory list */ 2957c478bd9Sstevel@tonic-gate if (listhead != NULL) { 296dfc7be02SJan Friedel (void) fprintf(dbfp, "Directory list:\n\t%s\n", 297dfc7be02SJan Friedel listhead->dl_dirname); 2987c478bd9Sstevel@tonic-gate thisdir = listhead->dl_next; 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate while (thisdir != listhead) { 301dfc7be02SJan Friedel (void) fprintf(dbfp, "\t%s\n", thisdir->dl_dirname); 3027c478bd9Sstevel@tonic-gate thisdir = thisdir->dl_next; 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 3067c478bd9Sstevel@tonic-gate 307*f8994074SJan Friedel thisdir = listhead; 308*f8994074SJan Friedel 309*f8994074SJan Friedel /* See if the list has changed (rc = 0 if no change, else 1) */ 310*f8994074SJan Friedel rc = 0; 3117c478bd9Sstevel@tonic-gate if (node_count == activeCount) { 3127c478bd9Sstevel@tonic-gate n1 = listhead; 3137c478bd9Sstevel@tonic-gate n2 = activeList; 3147c478bd9Sstevel@tonic-gate do { 3157c478bd9Sstevel@tonic-gate if (strcmp(n1->dl_dirname, n2->dl_dirname) != 0) { 3167c478bd9Sstevel@tonic-gate DPRINT((dbfp, 3177c478bd9Sstevel@tonic-gate "binfile: new dirname = %s\n" 3187c478bd9Sstevel@tonic-gate "binfile: old dirname = %s\n", 3197c478bd9Sstevel@tonic-gate n1->dl_dirname, 3207c478bd9Sstevel@tonic-gate n2->dl_dirname)); 3217c478bd9Sstevel@tonic-gate rc = -2; 3227c478bd9Sstevel@tonic-gate break; 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate n1 = n1->dl_next; 3257c478bd9Sstevel@tonic-gate n2 = n2->dl_next; 3267c478bd9Sstevel@tonic-gate } while ((n1 != listhead) && (n2 != activeList)); 3277c478bd9Sstevel@tonic-gate } else { 328*f8994074SJan Friedel DPRINT((dbfp, "binfile: dir counts differs\n" 329*f8994074SJan Friedel "binfile: old dir count = %d\n" 3307c478bd9Sstevel@tonic-gate "binfile: new dir count = %d\n", 3317c478bd9Sstevel@tonic-gate activeCount, node_count)); 3327c478bd9Sstevel@tonic-gate rc = -2; 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate if (rc == -2) { 3357c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&log_mutex); 336*f8994074SJan Friedel DPRINT((dbfp, "loadauditlist: close / open audit.log(4)\n")); 3371a578a15Spaulson if (open_log(listhead) == 0) { 3387c478bd9Sstevel@tonic-gate openNewFile = 1; /* try again later */ 3391a578a15Spaulson } else { 3401a578a15Spaulson openNewFile = 0; 3411a578a15Spaulson } 3427c478bd9Sstevel@tonic-gate freedirlist(activeList); /* old list */ 3437c478bd9Sstevel@tonic-gate activeList = listhead; /* new list */ 3441a578a15Spaulson activeDir = startdir = thisdir; 3457c478bd9Sstevel@tonic-gate activeCount = node_count; 3467c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&log_mutex); 347*f8994074SJan Friedel } else { 3487c478bd9Sstevel@tonic-gate freedirlist(listhead); 349*f8994074SJan Friedel } 350*f8994074SJan Friedel 351*f8994074SJan Friedel /* Get the minfree value. */ 3527c478bd9Sstevel@tonic-gate if (minfreestr != NULL) 3537c478bd9Sstevel@tonic-gate temp_minfree = atoi(minfreestr); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate if ((temp_minfree < 0) || (temp_minfree > 100)) 3567c478bd9Sstevel@tonic-gate temp_minfree = 0; 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate if (minfree != temp_minfree) { 3597c478bd9Sstevel@tonic-gate DPRINT((dbfp, "minfree: old = %d, new = %d\n", 3607c478bd9Sstevel@tonic-gate minfree, temp_minfree)); 3617c478bd9Sstevel@tonic-gate rc = -2; /* data change */ 3627c478bd9Sstevel@tonic-gate minfree = temp_minfree; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate return (rc); 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate /* 3697c478bd9Sstevel@tonic-gate * getauditdate - get the current time (GMT) and put it in the form 3707c478bd9Sstevel@tonic-gate * yyyymmddHHMMSS . 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate static void 3737c478bd9Sstevel@tonic-gate getauditdate(char *date) 3747c478bd9Sstevel@tonic-gate { 3757c478bd9Sstevel@tonic-gate struct timeval tp; 3767c478bd9Sstevel@tonic-gate struct timezone tzp; 3777c478bd9Sstevel@tonic-gate struct tm tm; 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate (void) gettimeofday(&tp, &tzp); 3807c478bd9Sstevel@tonic-gate tm = *gmtime(&tp.tv_sec); 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * NOTE: if we want to use gmtime, we have to be aware that the 3837c478bd9Sstevel@tonic-gate * structure only keeps the year as an offset from TM_YEAR_BASE. 3847c478bd9Sstevel@tonic-gate * I have used TM_YEAR_BASE in this code so that if they change 3857c478bd9Sstevel@tonic-gate * this base from 1900 to 2000, it will hopefully mean that this 3867c478bd9Sstevel@tonic-gate * code does not have to change. TM_YEAR_BASE is defined in 3877c478bd9Sstevel@tonic-gate * tzfile.h . 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate (void) sprintf(date, "%.4d%.2d%.2d%.2d%.2d%.2d", 3907c478bd9Sstevel@tonic-gate tm.tm_year + TM_YEAR_BASE, tm.tm_mon + 1, tm.tm_mday, 3917c478bd9Sstevel@tonic-gate tm.tm_hour, tm.tm_min, tm.tm_sec); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate /* 3977c478bd9Sstevel@tonic-gate * write_file_token - put the file token into the audit log 3987c478bd9Sstevel@tonic-gate */ 3997c478bd9Sstevel@tonic-gate static int 4007c478bd9Sstevel@tonic-gate write_file_token(int fd, char *name) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate adr_t adr; /* xdr ptr */ 4037c478bd9Sstevel@tonic-gate struct timeval tv; /* time now */ 4047c478bd9Sstevel@tonic-gate char for_adr[AUDIT_FNAME_SZ + AUDIT_FNAME_SZ]; /* plenty of room */ 4057c478bd9Sstevel@tonic-gate char token_id; 4067c478bd9Sstevel@tonic-gate short i; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)0); 4097c478bd9Sstevel@tonic-gate i = strlen(name) + 1; 4107c478bd9Sstevel@tonic-gate adr_start(&adr, for_adr); 4117c478bd9Sstevel@tonic-gate #ifdef _LP64 4127c478bd9Sstevel@tonic-gate token_id = AUT_OTHER_FILE64; 4137c478bd9Sstevel@tonic-gate adr_char(&adr, &token_id, 1); 4147c478bd9Sstevel@tonic-gate adr_int64(&adr, (int64_t *)& tv, 2); 4157c478bd9Sstevel@tonic-gate #else 4167c478bd9Sstevel@tonic-gate token_id = AUT_OTHER_FILE32; 4177c478bd9Sstevel@tonic-gate adr_char(&adr, &token_id, 1); 4187c478bd9Sstevel@tonic-gate adr_int32(&adr, (int32_t *)& tv, 2); 4197c478bd9Sstevel@tonic-gate #endif 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate adr_short(&adr, &i, 1); 4227c478bd9Sstevel@tonic-gate adr_char(&adr, name, i); 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate if (write(fd, for_adr, adr_count(&adr)) < 0) { 4257c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: Bad write\n")); 4267c478bd9Sstevel@tonic-gate return (errno); 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate return (0); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate /* 4327c478bd9Sstevel@tonic-gate * close_log - close the file if open. Also put the name of the 4337c478bd9Sstevel@tonic-gate * new log file in the trailer, and rename the old file 4347c478bd9Sstevel@tonic-gate * to oldname. The caller must hold log_mutext while calling 4357c478bd9Sstevel@tonic-gate * close_log since any change to activeDir is a complete redo 4367c478bd9Sstevel@tonic-gate * of all it points to. 4377c478bd9Sstevel@tonic-gate * arguments - 4387c478bd9Sstevel@tonic-gate * oldname - the new name for the file to be closed 4397c478bd9Sstevel@tonic-gate * newname - the name of the new log file (for the trailer) 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate static void 442*f8994074SJan Friedel close_log(dirlist_t **lastOpenDir_ptr, char *oname, char *newname) 4437c478bd9Sstevel@tonic-gate { 4447c478bd9Sstevel@tonic-gate char auditdate[AUDIT_DATE_SZ+1]; 4457c478bd9Sstevel@tonic-gate char *name; 4467c478bd9Sstevel@tonic-gate char oldname[AUDIT_FNAME_SZ+1]; 447*f8994074SJan Friedel dirlist_t *currentdir = *lastOpenDir_ptr; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate if ((currentdir == NULL) || (currentdir->dl_fd == -1)) 4507c478bd9Sstevel@tonic-gate return; 4517c478bd9Sstevel@tonic-gate /* 4527c478bd9Sstevel@tonic-gate * If oldname is blank, we were called by auditd_plugin_close() 4537c478bd9Sstevel@tonic-gate * instead of by open_log, so we need to update our name. 4547c478bd9Sstevel@tonic-gate */ 4557c478bd9Sstevel@tonic-gate (void) strlcpy(oldname, oname, AUDIT_FNAME_SZ); 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if (strcmp(oldname, "") == 0) { 4587c478bd9Sstevel@tonic-gate getauditdate(auditdate); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate assert(currentdir->dl_filename != NULL); 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate (void) strlcpy(oldname, currentdir->dl_filename, 4637c478bd9Sstevel@tonic-gate AUDIT_FNAME_SZ); 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate name = strrchr(oldname, '/') + 1; 4667c478bd9Sstevel@tonic-gate (void) memcpy(name + AUDIT_DATE_SZ + 1, auditdate, 4677c478bd9Sstevel@tonic-gate AUDIT_DATE_SZ); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * Write the trailer record and rename and close the file. 4717c478bd9Sstevel@tonic-gate * If any of the write, rename, or close fail, ignore it 4727c478bd9Sstevel@tonic-gate * since there is not much else we can do and the next open() 4737c478bd9Sstevel@tonic-gate * will trigger the necessary full directory logic. 4747c478bd9Sstevel@tonic-gate * 4757c478bd9Sstevel@tonic-gate * newname is "" if binfile is being closed down. 4767c478bd9Sstevel@tonic-gate */ 4777c478bd9Sstevel@tonic-gate (void) write_file_token(currentdir->dl_fd, newname); 4786a3b10dbStz204579 if (currentdir->dl_fd >= 0) { 4796a3b10dbStz204579 (void) fsync(currentdir->dl_fd); 4807c478bd9Sstevel@tonic-gate (void) close(currentdir->dl_fd); 4816a3b10dbStz204579 } 4827c478bd9Sstevel@tonic-gate currentdir->dl_fd = -1; 4837c478bd9Sstevel@tonic-gate (void) rename(currentdir->dl_filename, oldname); 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: Log closed %s\n", oldname)); 4867c478bd9Sstevel@tonic-gate 487*f8994074SJan Friedel freedirlist(currentdir); 488*f8994074SJan Friedel *lastOpenDir_ptr = NULL; 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate /* 4937c478bd9Sstevel@tonic-gate * open_log - open a new file in the current directory. If a 4947c478bd9Sstevel@tonic-gate * file is already open, close it. 4957c478bd9Sstevel@tonic-gate * 4967c478bd9Sstevel@tonic-gate * return 1 if ok, 0 if all directories are full. 4977c478bd9Sstevel@tonic-gate * 4987c478bd9Sstevel@tonic-gate * lastOpenDir - used to get the oldfile name (and change it), 4997c478bd9Sstevel@tonic-gate * to close the oldfile. 5007c478bd9Sstevel@tonic-gate * 5017c478bd9Sstevel@tonic-gate * The caller must hold log_mutex while calling open_log. 5027c478bd9Sstevel@tonic-gate * 5037c478bd9Sstevel@tonic-gate */ 5047c478bd9Sstevel@tonic-gate static int 5057c478bd9Sstevel@tonic-gate open_log(dirlist_t *current_dir) 5067c478bd9Sstevel@tonic-gate { 5077c478bd9Sstevel@tonic-gate char auditdate[AUDIT_DATE_SZ + 1]; 5087c478bd9Sstevel@tonic-gate char oldname[AUDIT_FNAME_SZ + 1] = ""; 5097c478bd9Sstevel@tonic-gate char newname[AUDIT_FNAME_SZ + 1]; 5107c478bd9Sstevel@tonic-gate char *name; /* pointer into oldname */ 511*f8994074SJan Friedel int opened = 0; 5127c478bd9Sstevel@tonic-gate int error = 0; 5137c478bd9Sstevel@tonic-gate int newfd = 0; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate static char host[MAXHOSTNAMELEN + 1] = ""; 5167c478bd9Sstevel@tonic-gate /* previous directory with open log file */ 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate if (host[0] == '\0') 5197c478bd9Sstevel@tonic-gate (void) gethostname(host, MAXHOSTNAMELEN); 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* Get a filename which does not already exist */ 5227c478bd9Sstevel@tonic-gate while (!opened) { 5237c478bd9Sstevel@tonic-gate getauditdate(auditdate); 5247c478bd9Sstevel@tonic-gate (void) snprintf(newname, AUDIT_FNAME_SZ, 5257c478bd9Sstevel@tonic-gate "%s/%s.not_terminated.%s", 5267c478bd9Sstevel@tonic-gate current_dir->dl_dirname, auditdate, host); 5277c478bd9Sstevel@tonic-gate newfd = open(newname, 528172c0d20Sme23304 O_RDWR | O_APPEND | O_CREAT | O_EXCL, 0640); 5297c478bd9Sstevel@tonic-gate if (newfd < 0) { 5307c478bd9Sstevel@tonic-gate switch (errno) { 5317c478bd9Sstevel@tonic-gate case EEXIST: 5327c478bd9Sstevel@tonic-gate DPRINT((dbfp, 5337c478bd9Sstevel@tonic-gate "open_log says duplicate for %s " 5347c478bd9Sstevel@tonic-gate "(will try another)\n", newname)); 5357c478bd9Sstevel@tonic-gate (void) sleep(1); 5367c478bd9Sstevel@tonic-gate break; 537*f8994074SJan Friedel case ENOENT: { 538*f8994074SJan Friedel /* invalid path */ 539*f8994074SJan Friedel char *msg; 540*f8994074SJan Friedel (void) asprintf(&msg, 541*f8994074SJan Friedel gettext("No such p_dir: %s\n"), 542*f8994074SJan Friedel current_dir->dl_dirname); 543*f8994074SJan Friedel DPRINT((dbfp, 544*f8994074SJan Friedel "open_log says about %s: %s\n", 545*f8994074SJan Friedel newname, strerror(errno))); 546*f8994074SJan Friedel __audit_syslog("audit_binfile.so", 547*f8994074SJan Friedel LOG_CONS | LOG_NDELAY, 548*f8994074SJan Friedel LOG_DAEMON, LOG_ERR, msg); 549*f8994074SJan Friedel free(msg); 550*f8994074SJan Friedel current_dir = current_dir->dl_next; 551*f8994074SJan Friedel return (0); 552*f8994074SJan Friedel } 5537c478bd9Sstevel@tonic-gate default: 5547c478bd9Sstevel@tonic-gate /* open failed */ 5557c478bd9Sstevel@tonic-gate DPRINT((dbfp, 5567c478bd9Sstevel@tonic-gate "open_log says full for %s: %s\n", 5577c478bd9Sstevel@tonic-gate newname, strerror(errno))); 5587c478bd9Sstevel@tonic-gate current_dir->dl_space = SPACE_FULL; 5597c478bd9Sstevel@tonic-gate current_dir = current_dir->dl_next; 5607c478bd9Sstevel@tonic-gate return (0); 5617c478bd9Sstevel@tonic-gate } /* switch */ 5627c478bd9Sstevel@tonic-gate } else 5637c478bd9Sstevel@tonic-gate opened = 1; 5647c478bd9Sstevel@tonic-gate } /* while */ 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate /* 5677c478bd9Sstevel@tonic-gate * When we get here, we have opened our new log file. 5687c478bd9Sstevel@tonic-gate * Now we need to update the name of the old file to 5697c478bd9Sstevel@tonic-gate * store in this file's header. lastOpenDir may point 5707c478bd9Sstevel@tonic-gate * to current_dir if the list is only one entry long and 5717c478bd9Sstevel@tonic-gate * there is only one list. 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate if ((lastOpenDir != NULL) && (lastOpenDir->dl_filename != NULL)) { 5747c478bd9Sstevel@tonic-gate (void) strlcpy(oldname, lastOpenDir->dl_filename, 5757c478bd9Sstevel@tonic-gate AUDIT_FNAME_SZ); 5767c478bd9Sstevel@tonic-gate name = (char *)strrchr(oldname, '/') + 1; 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate (void) memcpy(name + AUDIT_DATE_SZ + 1, auditdate, 5797c478bd9Sstevel@tonic-gate AUDIT_DATE_SZ); 5807c478bd9Sstevel@tonic-gate 581*f8994074SJan Friedel close_log(&lastOpenDir, oldname, newname); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate error = write_file_token(newfd, oldname); 5847c478bd9Sstevel@tonic-gate if (error) { 5857c478bd9Sstevel@tonic-gate /* write token failed */ 5867c478bd9Sstevel@tonic-gate (void) close(newfd); 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate current_dir->dl_space = SPACE_FULL; 5897c478bd9Sstevel@tonic-gate current_dir->dl_fd = -1; 5907c478bd9Sstevel@tonic-gate free(current_dir->dl_filename); 5917c478bd9Sstevel@tonic-gate current_dir->dl_filename = NULL; 5927c478bd9Sstevel@tonic-gate current_dir = current_dir->dl_next; 5937c478bd9Sstevel@tonic-gate return (0); 5947c478bd9Sstevel@tonic-gate } else { 595*f8994074SJan Friedel if (current_dir->dl_filename != NULL) { 596*f8994074SJan Friedel free(current_dir->dl_filename); 597*f8994074SJan Friedel } 5987c478bd9Sstevel@tonic-gate current_dir->dl_filename = strdup(newname); 599*f8994074SJan Friedel current_dir->dl_fd = newfd; 600*f8994074SJan Friedel 601*f8994074SJan Friedel if (lastOpenDir == NULL) { 602*f8994074SJan Friedel freedirlist(lastOpenDir); 603*f8994074SJan Friedel if ((lastOpenDir = dupdirnode(current_dir)) == NULL) { 604*f8994074SJan Friedel __audit_syslog("audit_binfile.so", 605*f8994074SJan Friedel LOG_CONS | LOG_NDELAY, 606*f8994074SJan Friedel LOG_DAEMON, LOG_ERR, gettext("no memory")); 607*f8994074SJan Friedel return (0); 608*f8994074SJan Friedel } 609*f8994074SJan Friedel DPRINT((dbfp, "open_log created new lastOpenDir " 610*f8994074SJan Friedel "(%s, %s [fd: %d])\n", 611*f8994074SJan Friedel lastOpenDir->dl_dirname == NULL ? "" : 612*f8994074SJan Friedel lastOpenDir->dl_dirname, 613*f8994074SJan Friedel lastOpenDir->dl_filename == NULL ? "" : 614*f8994074SJan Friedel lastOpenDir->dl_filename, lastOpenDir->dl_fd)); 615*f8994074SJan Friedel } 6167c478bd9Sstevel@tonic-gate 617f7092930Spr131582 /* 618f7092930Spr131582 * New file opened, so reset file size statistic (used 619f7092930Spr131582 * to ensure audit log does not grow above size limit 620f7092930Spr131582 * set by p_fsize). 621f7092930Spr131582 */ 622f7092930Spr131582 binfile_cursize = 0; 623f7092930Spr131582 6245ad42b1bSSurya Prakki (void) __logpost(newname); 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: Log opened: %s\n", newname)); 6277c478bd9Sstevel@tonic-gate return (1); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate #define IGNORE_SIZE 8192 6327c478bd9Sstevel@tonic-gate /* 6337c478bd9Sstevel@tonic-gate * spacecheck - determine whether the given directory's filesystem 6347c478bd9Sstevel@tonic-gate * has the at least the space requested. Also set the space 6357c478bd9Sstevel@tonic-gate * value in the directory list structure. If the caller 6367c478bd9Sstevel@tonic-gate * passes other than PLENTY_SPACE or SOFT_SPACE, the caller should 6377c478bd9Sstevel@tonic-gate * ignore the return value. Otherwise, 0 = less than the 6387c478bd9Sstevel@tonic-gate * requested space is available, 1 = at least the requested space 6397c478bd9Sstevel@tonic-gate * is available. 6407c478bd9Sstevel@tonic-gate * 6417c478bd9Sstevel@tonic-gate * log_mutex must be held by the caller 6427c478bd9Sstevel@tonic-gate * 6437c478bd9Sstevel@tonic-gate * -1 is returned if stat fails 6447c478bd9Sstevel@tonic-gate * 6457c478bd9Sstevel@tonic-gate * IGNORE_SIZE is one page (Sol 9 / 10 timeframe) and is the default 6467c478bd9Sstevel@tonic-gate * buffer size written for Sol 9 and earlier. To keep the same accuracy 6477c478bd9Sstevel@tonic-gate * for the soft limit check as before, spacecheck checks for space 6487c478bd9Sstevel@tonic-gate * remaining IGNORE_SIZE bytes. This reduces the number of statvfs() 6497c478bd9Sstevel@tonic-gate * calls and related math. 6507c478bd9Sstevel@tonic-gate * 6517c478bd9Sstevel@tonic-gate * globals - 6527c478bd9Sstevel@tonic-gate * minfree - the soft limit, i.e., the % of filesystem to reserve 6537c478bd9Sstevel@tonic-gate */ 6547c478bd9Sstevel@tonic-gate static int 6557c478bd9Sstevel@tonic-gate spacecheck(dirlist_t *thisdir, int test_limit, size_t next_buf_size) 6567c478bd9Sstevel@tonic-gate { 6577c478bd9Sstevel@tonic-gate struct statvfs sb; 6587c478bd9Sstevel@tonic-gate static int ignore_size = 0; 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate ignore_size += next_buf_size; 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate if ((test_limit == PLENTY_SPACE) && (ignore_size < IGNORE_SIZE)) 6637c478bd9Sstevel@tonic-gate return (1); 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate assert(thisdir != NULL); 6667c478bd9Sstevel@tonic-gate 6671a578a15Spaulson if (statvfs(thisdir->dl_dirname, &sb) < 0) { 6687c478bd9Sstevel@tonic-gate thisdir->dl_space = SPACE_FULL; 6697c478bd9Sstevel@tonic-gate minfreeblocks = AVAIL_MIN; 6707c478bd9Sstevel@tonic-gate return (-1); 6717c478bd9Sstevel@tonic-gate } else { 6727c478bd9Sstevel@tonic-gate minfreeblocks = ((minfree * sb.f_blocks) / 100) + AVAIL_MIN; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate if (sb.f_bavail < AVAIL_MIN) 6757c478bd9Sstevel@tonic-gate thisdir->dl_space = SPACE_FULL; 6761a578a15Spaulson else if (sb.f_bavail > minfreeblocks) { 6771a578a15Spaulson thisdir->dl_space = fullness_state = PLENTY_SPACE; 6781a578a15Spaulson ignore_size = 0; 6791a578a15Spaulson } else 6807c478bd9Sstevel@tonic-gate thisdir->dl_space = SOFT_SPACE; 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate if (thisdir->dl_space == PLENTY_SPACE) 6837c478bd9Sstevel@tonic-gate return (1); 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate return (thisdir->dl_space == test_limit); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* 689f7092930Spr131582 * Parses p_fsize value and contains it within the range FSIZE_MIN and 690f7092930Spr131582 * INT_MAX so using uints won't cause an undetected overflow of 691f7092930Spr131582 * INT_MAX. Defaults to 0 if the value is invalid or is missing. 692f7092930Spr131582 */ 693f7092930Spr131582 static void 694f7092930Spr131582 save_maxsize(char *maxsize) { 695f7092930Spr131582 /* 696f7092930Spr131582 * strtol() returns a long which could be larger than int so 697f7092930Spr131582 * store here for sanity checking first 698f7092930Spr131582 */ 699f7092930Spr131582 long proposed_maxsize; 700f7092930Spr131582 701f7092930Spr131582 if (maxsize != NULL) { 702f7092930Spr131582 /* 703f7092930Spr131582 * There is no explicit error return from strtol() so 704f7092930Spr131582 * we may need to depend on the value of errno. 705f7092930Spr131582 */ 706f7092930Spr131582 errno = 0; 707f7092930Spr131582 proposed_maxsize = strtol(maxsize, (char **)NULL, 10); 708f7092930Spr131582 709f7092930Spr131582 /* 710f7092930Spr131582 * If sizeof(long) is greater than sizeof(int) on this 711f7092930Spr131582 * platform, proposed_maxsize might be greater than 712f7092930Spr131582 * INT_MAX without it being reported as ERANGE. 713f7092930Spr131582 */ 714f7092930Spr131582 if ((errno == ERANGE) || 715f7092930Spr131582 ((proposed_maxsize != 0) && 716f7092930Spr131582 (proposed_maxsize < FSIZE_MIN)) || 717f7092930Spr131582 (proposed_maxsize > INT_MAX)) { 718f7092930Spr131582 binfile_maxsize = 0; 719f7092930Spr131582 DPRINT((dbfp, "binfile: p_fsize parameter out of " 720f7092930Spr131582 "range: %s\n", maxsize)); 721f7092930Spr131582 /* 722f7092930Spr131582 * Inform administrator of the error via 723f7092930Spr131582 * syslog 724f7092930Spr131582 */ 725f7092930Spr131582 __audit_syslog("audit_binfile.so", 726f7092930Spr131582 LOG_CONS | LOG_NDELAY, 727f7092930Spr131582 LOG_DAEMON, LOG_ERR, 728f7092930Spr131582 gettext("p_fsize parameter out of range\n")); 729f7092930Spr131582 } else { 730f7092930Spr131582 binfile_maxsize = proposed_maxsize; 731f7092930Spr131582 } 732f7092930Spr131582 } else { /* p_fsize string was not present */ 733f7092930Spr131582 binfile_maxsize = 0; 734f7092930Spr131582 } 735f7092930Spr131582 736f7092930Spr131582 DPRINT((dbfp, "binfile: set maxsize to %d\n", binfile_maxsize)); 737f7092930Spr131582 } 738f7092930Spr131582 739f7092930Spr131582 /* 7401a578a15Spaulson * auditd_plugin() writes a buffer to the currently open file. The 741f7092930Spr131582 * global "openNewFile" is used to force a new log file for cases such 742f7092930Spr131582 * as the initial open, when minfree is reached, the p_fsize value is 743f7092930Spr131582 * exceeded or the current file system fills up, and "audit -s" with 744f7092930Spr131582 * changed parameters. For "audit -n" a new log file is opened 745f7092930Spr131582 * immediately in auditd_plugin_open(). 7467c478bd9Sstevel@tonic-gate * 7477c478bd9Sstevel@tonic-gate * This function manages one or more audit directories as follows: 7487c478bd9Sstevel@tonic-gate * 7497c478bd9Sstevel@tonic-gate * If the current open file is in a directory that has not 7507c478bd9Sstevel@tonic-gate * reached the soft limit, write the input data and return. 7517c478bd9Sstevel@tonic-gate * 7527c478bd9Sstevel@tonic-gate * Scan the list of directories for one which has not reached 7537c478bd9Sstevel@tonic-gate * the soft limit; if one is found, write and return. Such 7547c478bd9Sstevel@tonic-gate * a writable directory is in "PLENTY_SPACE" state. 7557c478bd9Sstevel@tonic-gate * 7567c478bd9Sstevel@tonic-gate * Scan the list of directories for one which has not reached 7577c478bd9Sstevel@tonic-gate * the hard limit; if one is found, write and return. This 7587c478bd9Sstevel@tonic-gate * directory in in "SOFT_SPACE" state. 7597c478bd9Sstevel@tonic-gate * 7607c478bd9Sstevel@tonic-gate * Oh, and if a write fails, handle it like a hard space limit. 7617c478bd9Sstevel@tonic-gate * 7627c478bd9Sstevel@tonic-gate * audit_warn (via __audit_dowarn()) is used to alert an operator 7637c478bd9Sstevel@tonic-gate * at various levels of fullness. 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate /* ARGSUSED */ 7667c478bd9Sstevel@tonic-gate auditd_rc_t 7678f775e0aSJan Friedel auditd_plugin(const char *input, size_t in_len, uint64_t sequence, char **error) 7687c478bd9Sstevel@tonic-gate { 7697c478bd9Sstevel@tonic-gate auditd_rc_t rc = AUDITD_FAIL; 7707c478bd9Sstevel@tonic-gate int open_status; 7717c478bd9Sstevel@tonic-gate size_t out_len; 7727c478bd9Sstevel@tonic-gate /* avoid excess audit_warnage */ 7737c478bd9Sstevel@tonic-gate static int allsoftfull_warning = 0; 7741a578a15Spaulson static int allhard_pause = 0; 7751a578a15Spaulson static struct timeval next_allhard; 7761a578a15Spaulson struct timeval now; 7777c478bd9Sstevel@tonic-gate #if DEBUG 778dfc7be02SJan Friedel int statrc; 7797c478bd9Sstevel@tonic-gate static char *last_file_written_to = NULL; 7808f775e0aSJan Friedel static uint64_t last_sequence = 0; 7818f775e0aSJan Friedel static uint64_t write_count = 0; 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate if ((last_sequence > 0) && (sequence != last_sequence + 1)) 784dfc7be02SJan Friedel (void) fprintf(dbfp, 785dfc7be02SJan Friedel "binfile: buffer sequence=%llu but prev=%llu=n", 7867c478bd9Sstevel@tonic-gate sequence, last_sequence); 7877c478bd9Sstevel@tonic-gate last_sequence = sequence; 7887c478bd9Sstevel@tonic-gate 789dfc7be02SJan Friedel (void) fprintf(dbfp, "binfile: input seq=%llu, len=%d\n", 790dfc7be02SJan Friedel sequence, in_len); 7917c478bd9Sstevel@tonic-gate #endif 7927c478bd9Sstevel@tonic-gate *error = NULL; 7937c478bd9Sstevel@tonic-gate /* 7947c478bd9Sstevel@tonic-gate * lock is for activeDir, referenced by open_log() and close_log() 7957c478bd9Sstevel@tonic-gate */ 7967c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&log_mutex); 797f7092930Spr131582 798f7092930Spr131582 /* 799f7092930Spr131582 * If this would take us over the maximum size, open a new 800f7092930Spr131582 * file, unless maxsize is 0, in which case growth of the 801f7092930Spr131582 * audit log is unrestricted. 802f7092930Spr131582 */ 803f7092930Spr131582 if ((binfile_maxsize != 0) && 804f7092930Spr131582 ((binfile_cursize + in_len) > binfile_maxsize)) { 805f7092930Spr131582 DPRINT((dbfp, "binfile: maxsize exceeded, opening new audit " 806f7092930Spr131582 "file.\n")); 807f7092930Spr131582 openNewFile = 1; 808f7092930Spr131582 } 809f7092930Spr131582 8107c478bd9Sstevel@tonic-gate while (rc == AUDITD_FAIL) { 8117c478bd9Sstevel@tonic-gate open_status = 1; 8127c478bd9Sstevel@tonic-gate if (openNewFile) { 8137c478bd9Sstevel@tonic-gate open_status = open_log(activeDir); 8147c478bd9Sstevel@tonic-gate if (open_status == 1) /* ok */ 8157c478bd9Sstevel@tonic-gate openNewFile = 0; 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate /* 8187c478bd9Sstevel@tonic-gate * consider "space ok" return and error return the same; 8197c478bd9Sstevel@tonic-gate * a -1 means spacecheck couldn't check for space. 8207c478bd9Sstevel@tonic-gate */ 821dfc7be02SJan Friedel #if !DEBUG 822dfc7be02SJan Friedel if ((open_status == 1) && 823dfc7be02SJan Friedel (spacecheck(activeDir, fullness_state, in_len) != 0)) { 824dfc7be02SJan Friedel #else 8257c478bd9Sstevel@tonic-gate if ((open_status == 1) && 8267c478bd9Sstevel@tonic-gate (statrc = spacecheck(activeDir, fullness_state, 827dfc7be02SJan Friedel in_len) != 0)) { 8287c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: returned from spacecheck\n")); 8297c478bd9Sstevel@tonic-gate /* 8307c478bd9Sstevel@tonic-gate * The last copy of last_file_written_to is 8317c478bd9Sstevel@tonic-gate * never free'd, so there will be one open 8327c478bd9Sstevel@tonic-gate * memory reference on exit. It's debug only. 8337c478bd9Sstevel@tonic-gate */ 8347c478bd9Sstevel@tonic-gate if ((last_file_written_to != NULL) && 8357c478bd9Sstevel@tonic-gate (strcmp(last_file_written_to, 8367c478bd9Sstevel@tonic-gate activeDir->dl_filename) != 0)) { 8377c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: now writing to %s\n", 8387c478bd9Sstevel@tonic-gate activeDir->dl_filename)); 8397c478bd9Sstevel@tonic-gate free(last_file_written_to); 8407c478bd9Sstevel@tonic-gate } 8417c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: finished some debug stuff\n")); 8427c478bd9Sstevel@tonic-gate last_file_written_to = 8437c478bd9Sstevel@tonic-gate strdup(activeDir->dl_filename); 8447c478bd9Sstevel@tonic-gate #endif 8457c478bd9Sstevel@tonic-gate out_len = write(activeDir->dl_fd, input, in_len); 8467c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: finished the write\n")); 8477c478bd9Sstevel@tonic-gate 848f7092930Spr131582 binfile_cursize += out_len; 849f7092930Spr131582 8507c478bd9Sstevel@tonic-gate if (out_len == in_len) { 8517c478bd9Sstevel@tonic-gate DPRINT((dbfp, 8528f775e0aSJan Friedel "binfile: write_count=%llu, sequence=%llu," 8537c478bd9Sstevel@tonic-gate " l=%u\n", 8547c478bd9Sstevel@tonic-gate ++write_count, sequence, out_len)); 8557c478bd9Sstevel@tonic-gate allsoftfull_warning = 0; 8561a578a15Spaulson activeDir->dl_flags = 0; 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate rc = AUDITD_SUCCESS; 8597c478bd9Sstevel@tonic-gate break; 8601a578a15Spaulson } else if (!(activeDir->dl_flags & HARD_WARNED)) { 8617c478bd9Sstevel@tonic-gate DPRINT((dbfp, 8628f775e0aSJan Friedel "binfile: write failed, sequence=%llu, " 8637c478bd9Sstevel@tonic-gate "l=%u\n", sequence, out_len)); 8647c478bd9Sstevel@tonic-gate DPRINT((dbfp, "hard warning sent.\n")); 8657c478bd9Sstevel@tonic-gate __audit_dowarn("hard", activeDir->dl_dirname, 8667c478bd9Sstevel@tonic-gate 0); 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate activeDir->dl_flags |= HARD_WARNED; 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate } else { 8717c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: statrc=%d, fullness_state=%d\n", 8727c478bd9Sstevel@tonic-gate statrc, fullness_state)); 8731a578a15Spaulson if (!(activeDir->dl_flags & SOFT_WARNED) && 8741a578a15Spaulson (activeDir->dl_space == SOFT_SPACE)) { 8757c478bd9Sstevel@tonic-gate DPRINT((dbfp, "soft warning sent\n")); 8767c478bd9Sstevel@tonic-gate __audit_dowarn("soft", 8777c478bd9Sstevel@tonic-gate activeDir->dl_dirname, 0); 8787c478bd9Sstevel@tonic-gate activeDir->dl_flags |= SOFT_WARNED; 8797c478bd9Sstevel@tonic-gate } 8801a578a15Spaulson if (!(activeDir->dl_flags & HARD_WARNED) && 8811a578a15Spaulson (activeDir->dl_space == SPACE_FULL)) { 8827c478bd9Sstevel@tonic-gate DPRINT((dbfp, "hard warning sent.\n")); 8837c478bd9Sstevel@tonic-gate __audit_dowarn("hard", 8847c478bd9Sstevel@tonic-gate activeDir->dl_dirname, 0); 8857c478bd9Sstevel@tonic-gate activeDir->dl_flags |= HARD_WARNED; 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: activeDir=%s, next=%s\n", 8897c478bd9Sstevel@tonic-gate activeDir->dl_dirname, activeDir->dl_next->dl_dirname)); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate activeDir = activeDir->dl_next; 8921a578a15Spaulson openNewFile = 1; 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate if (activeDir == startdir) { /* full circle */ 8957c478bd9Sstevel@tonic-gate if (fullness_state == PLENTY_SPACE) { /* once */ 8967c478bd9Sstevel@tonic-gate fullness_state = SOFT_SPACE; 8977c478bd9Sstevel@tonic-gate if (allsoftfull_warning == 0) { 8987c478bd9Sstevel@tonic-gate allsoftfull_warning++; 8997c478bd9Sstevel@tonic-gate __audit_dowarn("allsoft", "", 0); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate } else { /* full circle twice */ 9021a578a15Spaulson if ((hung_count > 0) && !allhard_pause) { 9031a578a15Spaulson allhard_pause = 1; 9041a578a15Spaulson (void) gettimeofday(&next_allhard, 9051a578a15Spaulson NULL); 9061a578a15Spaulson next_allhard.tv_sec += ALLHARD_DELAY; 9071a578a15Spaulson } 9081a578a15Spaulson 9091a578a15Spaulson if (allhard_pause) { 9101a578a15Spaulson (void) gettimeofday(&now, NULL); 9111a578a15Spaulson if (now.tv_sec >= next_allhard.tv_sec) { 9121a578a15Spaulson allhard_pause = 0; 9131a578a15Spaulson __audit_dowarn("allhard", "", 9141a578a15Spaulson ++hung_count); 9151a578a15Spaulson } 9161a578a15Spaulson } else { 9171a578a15Spaulson __audit_dowarn("allhard", "", 9181a578a15Spaulson ++hung_count); 9191a578a15Spaulson } 9207c478bd9Sstevel@tonic-gate minfreeblocks = AVAIL_MIN; 9217c478bd9Sstevel@tonic-gate rc = AUDITD_RETRY; 9227c478bd9Sstevel@tonic-gate *error = strdup(gettext( 9237c478bd9Sstevel@tonic-gate "all partitions full\n")); 9245ad42b1bSSurya Prakki (void) __logpost(""); 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate } 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&log_mutex); 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate return (rc); 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate /* 9357c478bd9Sstevel@tonic-gate * It may be called multiple times as auditd handles SIGHUP and SIGUSR1 9367c478bd9Sstevel@tonic-gate * corresponding to the audit(1M) flags -s and -n 9377c478bd9Sstevel@tonic-gate * 938*f8994074SJan Friedel * kvlist is NULL only if auditd caught a SIGUSR1 (audit -n), so after the first 939*f8994074SJan Friedel * time open is called; the reason is -s if kvlist != NULL and -n otherwise. 9407c478bd9Sstevel@tonic-gate * 9417c478bd9Sstevel@tonic-gate */ 9427c478bd9Sstevel@tonic-gate auditd_rc_t 9437c478bd9Sstevel@tonic-gate auditd_plugin_open(const kva_t *kvlist, char **ret_list, char **error) 9447c478bd9Sstevel@tonic-gate { 9457c478bd9Sstevel@tonic-gate int rc = 0; 9467c478bd9Sstevel@tonic-gate int status; 9477c478bd9Sstevel@tonic-gate int reason; 9487c478bd9Sstevel@tonic-gate char *dirlist; 9497c478bd9Sstevel@tonic-gate char *minfree; 950f7092930Spr131582 char *maxsize; 9517c478bd9Sstevel@tonic-gate kva_t *kv; 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate *error = NULL; 9547c478bd9Sstevel@tonic-gate *ret_list = NULL; 9557c478bd9Sstevel@tonic-gate kv = (kva_t *)kvlist; 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate if (am_open) { 9587c478bd9Sstevel@tonic-gate if (kvlist == NULL) 9597c478bd9Sstevel@tonic-gate reason = 1; /* audit -n */ 9607c478bd9Sstevel@tonic-gate else 9617c478bd9Sstevel@tonic-gate reason = 2; /* audit -s */ 9627c478bd9Sstevel@tonic-gate } else { 9637c478bd9Sstevel@tonic-gate reason = 0; /* initial open */ 9647c478bd9Sstevel@tonic-gate #if DEBUG 9657c478bd9Sstevel@tonic-gate dbfp = __auditd_debug_file_open(); 9667c478bd9Sstevel@tonic-gate #endif 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: am_open=%d, reason=%d\n", am_open, reason)); 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate am_open = 1; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate if (kvlist == NULL) { 9737c478bd9Sstevel@tonic-gate dirlist = NULL; 9747c478bd9Sstevel@tonic-gate minfree = NULL; 975f7092930Spr131582 maxsize = NULL; 9767c478bd9Sstevel@tonic-gate } else { 9777c478bd9Sstevel@tonic-gate dirlist = kva_match(kv, "p_dir"); 9787c478bd9Sstevel@tonic-gate minfree = kva_match(kv, "p_minfree"); 979f7092930Spr131582 maxsize = kva_match(kv, "p_fsize"); 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate switch (reason) { 9827c478bd9Sstevel@tonic-gate case 0: /* initial open */ 9837c478bd9Sstevel@tonic-gate if (!binfile_is_open) 9847c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&log_mutex, NULL); 9857c478bd9Sstevel@tonic-gate binfile_is_open = 1; 9867c478bd9Sstevel@tonic-gate openNewFile = 1; 9877c478bd9Sstevel@tonic-gate /* FALLTHRU */ 9887c478bd9Sstevel@tonic-gate case 2: /* audit -s */ 989f7092930Spr131582 /* handle p_fsize parameter */ 990f7092930Spr131582 save_maxsize(maxsize); 991f7092930Spr131582 9927c478bd9Sstevel@tonic-gate fullness_state = PLENTY_SPACE; 9937c478bd9Sstevel@tonic-gate status = loadauditlist(dirlist, minfree); 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate if (status == -1) { 9965ad42b1bSSurya Prakki (void) __logpost(""); 9977c478bd9Sstevel@tonic-gate *error = strdup(gettext("no directories configured")); 9987c478bd9Sstevel@tonic-gate return (AUDITD_RETRY); 9997c478bd9Sstevel@tonic-gate } else if (status == AUDITD_NO_MEMORY) { 10005ad42b1bSSurya Prakki (void) __logpost(""); 10017c478bd9Sstevel@tonic-gate *error = strdup(gettext("no memory")); 10027c478bd9Sstevel@tonic-gate return (status); 10037c478bd9Sstevel@tonic-gate } else { /* status is 0 or -2 (no change or changed) */ 10047c478bd9Sstevel@tonic-gate hung_count = 0; 10057c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: loadauditlist returned %d\n", 10067c478bd9Sstevel@tonic-gate status)); 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate break; 10097c478bd9Sstevel@tonic-gate case 1: /* audit -n */ 10107c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&log_mutex); 10117c478bd9Sstevel@tonic-gate if (open_log(activeDir) == 1) /* ok */ 10127c478bd9Sstevel@tonic-gate openNewFile = 0; 10137c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&log_mutex); 10147c478bd9Sstevel@tonic-gate break; 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate rc = AUDITD_SUCCESS; 10187c478bd9Sstevel@tonic-gate *ret_list = NULL; 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate return (rc); 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate auditd_rc_t 10247c478bd9Sstevel@tonic-gate auditd_plugin_close(char **error) 10257c478bd9Sstevel@tonic-gate { 10267c478bd9Sstevel@tonic-gate *error = NULL; 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&log_mutex); 1029*f8994074SJan Friedel close_log(&lastOpenDir, "", ""); 10307c478bd9Sstevel@tonic-gate freedirlist(activeDir); 10317c478bd9Sstevel@tonic-gate activeDir = NULL; 10327c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&log_mutex); 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate DPRINT((dbfp, "binfile: closed\n")); 10357c478bd9Sstevel@tonic-gate 1036c900e163Sgww (void) __logpost(""); 1037c900e163Sgww 10387c478bd9Sstevel@tonic-gate if (binfile_is_open) { 10397c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&log_mutex); 10407c478bd9Sstevel@tonic-gate binfile_is_open = 0; 1041dfc7be02SJan Friedel #if DEBUG 10427c478bd9Sstevel@tonic-gate } else { 1043dfc7be02SJan Friedel (void) fprintf(dbfp, 1044dfc7be02SJan Friedel "auditd_plugin_close() called when already closed."); 1045dfc7be02SJan Friedel #endif 10467c478bd9Sstevel@tonic-gate } 10477c478bd9Sstevel@tonic-gate am_open = 0; 10487c478bd9Sstevel@tonic-gate return (AUDITD_SUCCESS); 10497c478bd9Sstevel@tonic-gate } 1050