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 558091fd8Ssetje * Common Development and Distribution License (the "License"). 658091fd8Ssetje * 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 /* 22e333042dSgww * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 317c478bd9Sstevel@tonic-gate 32*6dcd8691Sgww #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <fcntl.h> 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 36*6dcd8691Sgww #include <string.h> 37*6dcd8691Sgww #include <strings.h> 387c478bd9Sstevel@tonic-gate #include <signal.h> 39*6dcd8691Sgww #include <unistd.h> 40*6dcd8691Sgww 416a3b10dbStz204579 #include <bsm/adt.h> 426a3b10dbStz204579 #include <bsm/adt_event.h> 43*6dcd8691Sgww 44*6dcd8691Sgww #include <sys/uadmin.h> 457c478bd9Sstevel@tonic-gate 4658091fd8Ssetje #define SMF_RST "/etc/svc/volatile/resetting" 4758091fd8Ssetje 487c478bd9Sstevel@tonic-gate static const char *Usage = "Usage: %s cmd fcn [mdep]\n"; 497c478bd9Sstevel@tonic-gate 50e333042dSgww static int turnoff_auditd(int, int); 516a3b10dbStz204579 static void wait_for_auqueue(); 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate int 547c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 557c478bd9Sstevel@tonic-gate { 567c478bd9Sstevel@tonic-gate int cmd, fcn; 577c478bd9Sstevel@tonic-gate uintptr_t mdep = NULL; 587c478bd9Sstevel@tonic-gate sigset_t set; 596a3b10dbStz204579 adt_session_data_t *ah; /* audit session handle */ 606a3b10dbStz204579 adt_event_data_t *event = NULL; /* event to be generated */ 616a3b10dbStz204579 au_event_t event_id; 626a3b10dbStz204579 enum adt_uadmin_fcn fcn_id; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate if (argc < 3 || argc > 4) { 657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Usage, argv[0]); 667c478bd9Sstevel@tonic-gate return (1); 677c478bd9Sstevel@tonic-gate } 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate (void) sigfillset(&set); 707c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &set, NULL); 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate cmd = atoi(argv[1]); 737c478bd9Sstevel@tonic-gate fcn = atoi(argv[2]); 747c478bd9Sstevel@tonic-gate if (argc == 4) { /* mdep argument given */ 752df1fe9cSrandyf if (cmd != A_REBOOT && cmd != A_SHUTDOWN && cmd != A_DUMP && 762df1fe9cSrandyf cmd != A_FREEZE) { 777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: mdep argument not " 787c478bd9Sstevel@tonic-gate "allowed for this cmd value\n", argv[0]); 797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Usage, argv[0]); 807c478bd9Sstevel@tonic-gate return (1); 817c478bd9Sstevel@tonic-gate } else { 827c478bd9Sstevel@tonic-gate mdep = (uintptr_t)argv[3]; 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 866a3b10dbStz204579 /* set up audit session and event */ 876a3b10dbStz204579 if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) { 886a3b10dbStz204579 (void) fprintf(stderr, "%s: can't start audit session\n", 896a3b10dbStz204579 argv[0]); 906a3b10dbStz204579 } 916a3b10dbStz204579 switch (cmd) { 926a3b10dbStz204579 case A_SHUTDOWN: 936a3b10dbStz204579 event_id = ADT_uadmin_shutdown; 946a3b10dbStz204579 break; 956a3b10dbStz204579 case A_REBOOT: 966a3b10dbStz204579 event_id = ADT_uadmin_reboot; 976a3b10dbStz204579 break; 986a3b10dbStz204579 case A_DUMP: 996a3b10dbStz204579 event_id = ADT_uadmin_dump; 1006a3b10dbStz204579 break; 1016a3b10dbStz204579 case A_REMOUNT: 1026a3b10dbStz204579 event_id = ADT_uadmin_remount; 1036a3b10dbStz204579 break; 1046a3b10dbStz204579 case A_FREEZE: 1056a3b10dbStz204579 event_id = ADT_uadmin_freeze; 1066a3b10dbStz204579 break; 1076a3b10dbStz204579 case A_FTRACE: 1086a3b10dbStz204579 event_id = ADT_uadmin_ftrace; 1096a3b10dbStz204579 break; 1106a3b10dbStz204579 case A_SWAPCTL: 1116a3b10dbStz204579 event_id = ADT_uadmin_swapctl; 1126a3b10dbStz204579 break; 1136a3b10dbStz204579 default: 1146a3b10dbStz204579 event_id = 0; 1156a3b10dbStz204579 } 1166a3b10dbStz204579 if ((event_id != 0) && 1176a3b10dbStz204579 (event = adt_alloc_event(ah, event_id)) == NULL) { 1186a3b10dbStz204579 (void) fprintf(stderr, "%s: can't allocate audit event\n", 1196a3b10dbStz204579 argv[0]); 1206a3b10dbStz204579 } 1216a3b10dbStz204579 switch (fcn) { 1226a3b10dbStz204579 case AD_HALT: 1236a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_HALT; 1246a3b10dbStz204579 break; 1256a3b10dbStz204579 case AD_POWEROFF: 1266a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_POWEROFF; 1276a3b10dbStz204579 break; 1286a3b10dbStz204579 case AD_BOOT: 1296a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_BOOT; 1306a3b10dbStz204579 break; 1316a3b10dbStz204579 case AD_IBOOT: 1326a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_IBOOT; 1336a3b10dbStz204579 break; 1346a3b10dbStz204579 case AD_SBOOT: 1356a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_SBOOT; 1366a3b10dbStz204579 break; 1376a3b10dbStz204579 case AD_SIBOOT: 1386a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_SIBOOT; 1396a3b10dbStz204579 break; 1406a3b10dbStz204579 case AD_NOSYNC: 1416a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_NOSYNC; 1426a3b10dbStz204579 break; 1436a3b10dbStz204579 default: 1446a3b10dbStz204579 fcn_id = 0; 1456a3b10dbStz204579 } 1466a3b10dbStz204579 if (cmd == A_FREEZE) { 1476a3b10dbStz204579 switch (fcn) { 1486a3b10dbStz204579 case AD_SUSPEND_TO_DISK: 1496a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_DISK; 1506a3b10dbStz204579 break; 1516a3b10dbStz204579 case AD_CHECK_SUSPEND_TO_DISK: 1526a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_DISK; 1536a3b10dbStz204579 break; 1546a3b10dbStz204579 case AD_FORCE: 1556a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_FORCE; 1566a3b10dbStz204579 break; 1576a3b10dbStz204579 case AD_SUSPEND_TO_RAM: 1586a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_RAM; 1596a3b10dbStz204579 break; 1606a3b10dbStz204579 case AD_CHECK_SUSPEND_TO_RAM: 1616a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_RAM; 1626a3b10dbStz204579 break; 1636a3b10dbStz204579 case AD_REUSEINIT: 1646a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_REUSEINIT; 1656a3b10dbStz204579 break; 1666a3b10dbStz204579 case AD_REUSABLE: 1676a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_REUSABLE; 1686a3b10dbStz204579 break; 1696a3b10dbStz204579 case AD_REUSEFINI: 1706a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_REUSEFINI; 1716a3b10dbStz204579 break; 1726a3b10dbStz204579 } 1736a3b10dbStz204579 } else if (cmd == A_FTRACE) { 1746a3b10dbStz204579 switch (fcn) { 1756a3b10dbStz204579 case AD_FTRACE_START: 1766a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_FTRACE_START; 1776a3b10dbStz204579 break; 1786a3b10dbStz204579 case AD_FTRACE_STOP: 1796a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_FTRACE_STOP; 1806a3b10dbStz204579 break; 1816a3b10dbStz204579 } 1826a3b10dbStz204579 } 1836a3b10dbStz204579 1847c478bd9Sstevel@tonic-gate if (geteuid() == 0) { 1856a3b10dbStz204579 if (event != NULL) { 1866a3b10dbStz204579 switch (cmd) { 1876a3b10dbStz204579 case A_SHUTDOWN: 1886a3b10dbStz204579 event->adt_uadmin_shutdown.fcn = fcn_id; 1896a3b10dbStz204579 event->adt_uadmin_shutdown.mdep = (char *)mdep; 1906a3b10dbStz204579 break; 1916a3b10dbStz204579 case A_REBOOT: 1926a3b10dbStz204579 event->adt_uadmin_reboot.fcn = fcn_id; 1936a3b10dbStz204579 event->adt_uadmin_reboot.mdep = (char *)mdep; 1946a3b10dbStz204579 break; 1956a3b10dbStz204579 case A_DUMP: 1966a3b10dbStz204579 event->adt_uadmin_dump.fcn = fcn_id; 1976a3b10dbStz204579 event->adt_uadmin_dump.mdep = (char *)mdep; 1986a3b10dbStz204579 break; 1996a3b10dbStz204579 case A_REMOUNT: 2006a3b10dbStz204579 /* no parameters */ 2016a3b10dbStz204579 break; 2026a3b10dbStz204579 case A_FREEZE: 2036a3b10dbStz204579 event->adt_uadmin_freeze.fcn = fcn_id; 2046a3b10dbStz204579 event->adt_uadmin_freeze.mdep = (char *)mdep; 2056a3b10dbStz204579 break; 2066a3b10dbStz204579 case A_FTRACE: 2076a3b10dbStz204579 event->adt_uadmin_ftrace.fcn = fcn_id; 2086a3b10dbStz204579 break; 2096a3b10dbStz204579 case A_SWAPCTL: 2106a3b10dbStz204579 event->adt_uadmin_swapctl.fcn = fcn_id; 2116a3b10dbStz204579 break; 2126a3b10dbStz204579 } 2136a3b10dbStz204579 2146a3b10dbStz204579 if (adt_put_event(event, ADT_SUCCESS, 0) != 0) { 2156a3b10dbStz204579 (void) fprintf(stderr, 2166a3b10dbStz204579 "%s: can't put audit event\n", argv[0]); 2176a3b10dbStz204579 } 2186a3b10dbStz204579 /* 2196a3b10dbStz204579 * allow audit record to be processed in the kernel 2206a3b10dbStz204579 * audit queue 2216a3b10dbStz204579 */ 2226a3b10dbStz204579 wait_for_auqueue(); 2236a3b10dbStz204579 } 2246a3b10dbStz204579 225e333042dSgww if (turnoff_auditd(cmd, fcn) == -1) 2267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: can't turn off auditd\n", 2277c478bd9Sstevel@tonic-gate argv[0]); 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate if (cmd == A_SHUTDOWN || cmd == A_REBOOT) 23058091fd8Ssetje (void) creat(SMF_RST, 0777); 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate 2336a3b10dbStz204579 (void) adt_free_event(event); 2346a3b10dbStz204579 (void) adt_end_session(ah); 2356a3b10dbStz204579 2367c478bd9Sstevel@tonic-gate if (uadmin(cmd, fcn, mdep) < 0) { 2377c478bd9Sstevel@tonic-gate perror("uadmin"); 2387c478bd9Sstevel@tonic-gate 23958091fd8Ssetje (void) unlink(SMF_RST); 24058091fd8Ssetje 2417c478bd9Sstevel@tonic-gate return (1); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate return (0); 2457c478bd9Sstevel@tonic-gate } 2466a3b10dbStz204579 2476a3b10dbStz204579 static int 248e333042dSgww turnoff_auditd(int cmd, int fcn) 2496a3b10dbStz204579 { 250*6dcd8691Sgww int rc; 2516a3b10dbStz204579 int retries = 15; 2526a3b10dbStz204579 253e333042dSgww switch (cmd) { 254e333042dSgww case A_SHUTDOWN: 255e333042dSgww case A_REBOOT: 256e333042dSgww case A_DUMP: 257e333042dSgww /* system shutting down, turn off auditd */ 258e333042dSgww break; 259e333042dSgww case A_REMOUNT: 260e333042dSgww case A_SWAPCTL: 261e333042dSgww case A_FTRACE: 262e333042dSgww /* No system discontinuity, don't turn off auditd */ 263e333042dSgww return (0); 264e333042dSgww case A_FREEZE: 265e333042dSgww switch (fcn) { 266e333042dSgww case AD_CHECK_SUSPEND_TO_DISK: /* AD_CHECK */ 267e333042dSgww case AD_CHECK_SUSPEND_TO_RAM: 268e333042dSgww case AD_REUSEINIT: 269e333042dSgww case AD_REUSEFINI: 270e333042dSgww /* No system discontinuity, don't turn off auditd */ 271e333042dSgww return (0); 272e333042dSgww case AD_REUSABLE: 273e333042dSgww case AD_SUSPEND_TO_DISK: /* AD_COMPRESS */ 274e333042dSgww case AD_SUSPEND_TO_RAM: 275e333042dSgww case AD_FORCE: 276e333042dSgww /* suspend the system, change audit files */ 277e333042dSgww /* XXX not implemented for now */ 278e333042dSgww default: 279e333042dSgww return (-1); 280e333042dSgww } 281e333042dSgww default: 282e333042dSgww return (-1); 283e333042dSgww } 284e333042dSgww 285*6dcd8691Sgww if (adt_audit_enabled()) { 286*6dcd8691Sgww if ((rc = fork()) == 0) { 287*6dcd8691Sgww (void) execl("/usr/sbin/audit", "audit", "-t", NULL); 2886a3b10dbStz204579 (void) fprintf(stderr, "error disabling auditd: %s\n", 289*6dcd8691Sgww strerror(errno)); 290*6dcd8691Sgww _exit(-1); 291*6dcd8691Sgww } else if (rc == -1) { 292*6dcd8691Sgww (void) fprintf(stderr, "error disabling auditd: %s\n", 293*6dcd8691Sgww strerror(errno)); 2946a3b10dbStz204579 return (-1); 2956a3b10dbStz204579 } 296*6dcd8691Sgww } else { 297*6dcd8691Sgww return (0); 298*6dcd8691Sgww } 2996a3b10dbStz204579 300*6dcd8691Sgww /* 301*6dcd8691Sgww * wait for auditd to finish its work. auditd will change the 302*6dcd8691Sgww * auditstart from AUC_AUDITING (auditd up and running) to 303*6dcd8691Sgww * AUC_NOAUDIT. Other states are errors, so we're done as well. 304*6dcd8691Sgww */ 3056a3b10dbStz204579 do { 306*6dcd8691Sgww int auditstate; 3076a3b10dbStz204579 308*6dcd8691Sgww rc = -1; 309*6dcd8691Sgww if ((auditon(A_GETCOND, (caddr_t)&auditstate, 310*6dcd8691Sgww sizeof (auditstate)) == 0) && 311*6dcd8691Sgww (auditstate == AUC_AUDITING)) { 3126a3b10dbStz204579 retries--; 3136a3b10dbStz204579 (void) sleep(1); 3146a3b10dbStz204579 } else { 3156a3b10dbStz204579 rc = 0; 3166a3b10dbStz204579 } 317*6dcd8691Sgww } while ((rc != 0) && (retries != 0)); 3186a3b10dbStz204579 3196a3b10dbStz204579 return (rc); 3206a3b10dbStz204579 } 3216a3b10dbStz204579 3226a3b10dbStz204579 static void 3236a3b10dbStz204579 wait_for_auqueue() 3246a3b10dbStz204579 { 3256a3b10dbStz204579 au_stat_t au_stat; 3266a3b10dbStz204579 int retries = 10; 3276a3b10dbStz204579 3286a3b10dbStz204579 while (retries-- && auditon(A_GETSTAT, (caddr_t)&au_stat, NULL) == 0) { 3296a3b10dbStz204579 if (au_stat.as_enqueue == au_stat.as_written) { 3306a3b10dbStz204579 break; 3316a3b10dbStz204579 } 3326a3b10dbStz204579 (void) sleep(1); 3336a3b10dbStz204579 } 3346a3b10dbStz204579 } 335