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 /* 222df1fe9cSrandyf * Copyright 2007 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 327c478bd9Sstevel@tonic-gate #include <fcntl.h> 337c478bd9Sstevel@tonic-gate #include <stdio.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <signal.h> 377c478bd9Sstevel@tonic-gate #include <sys/uadmin.h> 38*6a3b10dbStz204579 #include <bsm/adt.h> 39*6a3b10dbStz204579 #include <bsm/adt_event.h> 40*6a3b10dbStz204579 #include <libscf.h> 41*6a3b10dbStz204579 #include <strings.h> 427c478bd9Sstevel@tonic-gate 4358091fd8Ssetje #define SMF_RST "/etc/svc/volatile/resetting" 44*6a3b10dbStz204579 #define AUDITD_FMRI "svc:/system/auditd:default" 4558091fd8Ssetje 467c478bd9Sstevel@tonic-gate static const char *Usage = "Usage: %s cmd fcn [mdep]\n"; 477c478bd9Sstevel@tonic-gate 48*6a3b10dbStz204579 static int turnoff_auditd(); 49*6a3b10dbStz204579 static void wait_for_auqueue(); 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate int 527c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 537c478bd9Sstevel@tonic-gate { 547c478bd9Sstevel@tonic-gate int cmd, fcn; 557c478bd9Sstevel@tonic-gate uintptr_t mdep = NULL; 567c478bd9Sstevel@tonic-gate sigset_t set; 57*6a3b10dbStz204579 adt_session_data_t *ah; /* audit session handle */ 58*6a3b10dbStz204579 adt_event_data_t *event = NULL; /* event to be generated */ 59*6a3b10dbStz204579 au_event_t event_id; 60*6a3b10dbStz204579 enum adt_uadmin_fcn fcn_id; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate if (argc < 3 || argc > 4) { 637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Usage, argv[0]); 647c478bd9Sstevel@tonic-gate return (1); 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate (void) sigfillset(&set); 687c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &set, NULL); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate cmd = atoi(argv[1]); 717c478bd9Sstevel@tonic-gate fcn = atoi(argv[2]); 727c478bd9Sstevel@tonic-gate if (argc == 4) { /* mdep argument given */ 732df1fe9cSrandyf if (cmd != A_REBOOT && cmd != A_SHUTDOWN && cmd != A_DUMP && 742df1fe9cSrandyf cmd != A_FREEZE) { 757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: mdep argument not " 767c478bd9Sstevel@tonic-gate "allowed for this cmd value\n", argv[0]); 777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, Usage, argv[0]); 787c478bd9Sstevel@tonic-gate return (1); 797c478bd9Sstevel@tonic-gate } else { 807c478bd9Sstevel@tonic-gate mdep = (uintptr_t)argv[3]; 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate } 837c478bd9Sstevel@tonic-gate 84*6a3b10dbStz204579 /* set up audit session and event */ 85*6a3b10dbStz204579 if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) { 86*6a3b10dbStz204579 (void) fprintf(stderr, "%s: can't start audit session\n", 87*6a3b10dbStz204579 argv[0]); 88*6a3b10dbStz204579 } 89*6a3b10dbStz204579 switch (cmd) { 90*6a3b10dbStz204579 case A_SHUTDOWN: 91*6a3b10dbStz204579 event_id = ADT_uadmin_shutdown; 92*6a3b10dbStz204579 break; 93*6a3b10dbStz204579 case A_REBOOT: 94*6a3b10dbStz204579 event_id = ADT_uadmin_reboot; 95*6a3b10dbStz204579 break; 96*6a3b10dbStz204579 case A_DUMP: 97*6a3b10dbStz204579 event_id = ADT_uadmin_dump; 98*6a3b10dbStz204579 break; 99*6a3b10dbStz204579 case A_REMOUNT: 100*6a3b10dbStz204579 event_id = ADT_uadmin_remount; 101*6a3b10dbStz204579 break; 102*6a3b10dbStz204579 case A_FREEZE: 103*6a3b10dbStz204579 event_id = ADT_uadmin_freeze; 104*6a3b10dbStz204579 break; 105*6a3b10dbStz204579 case A_FTRACE: 106*6a3b10dbStz204579 event_id = ADT_uadmin_ftrace; 107*6a3b10dbStz204579 break; 108*6a3b10dbStz204579 case A_SWAPCTL: 109*6a3b10dbStz204579 event_id = ADT_uadmin_swapctl; 110*6a3b10dbStz204579 break; 111*6a3b10dbStz204579 default: 112*6a3b10dbStz204579 event_id = 0; 113*6a3b10dbStz204579 } 114*6a3b10dbStz204579 if ((event_id != 0) && 115*6a3b10dbStz204579 (event = adt_alloc_event(ah, event_id)) == NULL) { 116*6a3b10dbStz204579 (void) fprintf(stderr, "%s: can't allocate audit event\n", 117*6a3b10dbStz204579 argv[0]); 118*6a3b10dbStz204579 } 119*6a3b10dbStz204579 switch (fcn) { 120*6a3b10dbStz204579 case AD_HALT: 121*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_HALT; 122*6a3b10dbStz204579 break; 123*6a3b10dbStz204579 case AD_POWEROFF: 124*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_POWEROFF; 125*6a3b10dbStz204579 break; 126*6a3b10dbStz204579 case AD_BOOT: 127*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_BOOT; 128*6a3b10dbStz204579 break; 129*6a3b10dbStz204579 case AD_IBOOT: 130*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_IBOOT; 131*6a3b10dbStz204579 break; 132*6a3b10dbStz204579 case AD_SBOOT: 133*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_SBOOT; 134*6a3b10dbStz204579 break; 135*6a3b10dbStz204579 case AD_SIBOOT: 136*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_SIBOOT; 137*6a3b10dbStz204579 break; 138*6a3b10dbStz204579 case AD_NOSYNC: 139*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_NOSYNC; 140*6a3b10dbStz204579 break; 141*6a3b10dbStz204579 default: 142*6a3b10dbStz204579 fcn_id = 0; 143*6a3b10dbStz204579 } 144*6a3b10dbStz204579 if (cmd == A_FREEZE) { 145*6a3b10dbStz204579 switch (fcn) { 146*6a3b10dbStz204579 case AD_SUSPEND_TO_DISK: 147*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_DISK; 148*6a3b10dbStz204579 break; 149*6a3b10dbStz204579 case AD_CHECK_SUSPEND_TO_DISK: 150*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_DISK; 151*6a3b10dbStz204579 break; 152*6a3b10dbStz204579 case AD_FORCE: 153*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_FORCE; 154*6a3b10dbStz204579 break; 155*6a3b10dbStz204579 case AD_SUSPEND_TO_RAM: 156*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_RAM; 157*6a3b10dbStz204579 break; 158*6a3b10dbStz204579 case AD_CHECK_SUSPEND_TO_RAM: 159*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_RAM; 160*6a3b10dbStz204579 break; 161*6a3b10dbStz204579 case AD_REUSEINIT: 162*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_REUSEINIT; 163*6a3b10dbStz204579 break; 164*6a3b10dbStz204579 case AD_REUSABLE: 165*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_REUSABLE; 166*6a3b10dbStz204579 break; 167*6a3b10dbStz204579 case AD_REUSEFINI: 168*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_REUSEFINI; 169*6a3b10dbStz204579 break; 170*6a3b10dbStz204579 } 171*6a3b10dbStz204579 } else if (cmd == A_FTRACE) { 172*6a3b10dbStz204579 switch (fcn) { 173*6a3b10dbStz204579 case AD_FTRACE_START: 174*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_FTRACE_START; 175*6a3b10dbStz204579 break; 176*6a3b10dbStz204579 case AD_FTRACE_STOP: 177*6a3b10dbStz204579 fcn_id = ADT_UADMIN_FCN_AD_FTRACE_STOP; 178*6a3b10dbStz204579 break; 179*6a3b10dbStz204579 } 180*6a3b10dbStz204579 } 181*6a3b10dbStz204579 1827c478bd9Sstevel@tonic-gate if (geteuid() == 0) { 183*6a3b10dbStz204579 if (event != NULL) { 184*6a3b10dbStz204579 switch (cmd) { 185*6a3b10dbStz204579 case A_SHUTDOWN: 186*6a3b10dbStz204579 event->adt_uadmin_shutdown.fcn = fcn_id; 187*6a3b10dbStz204579 event->adt_uadmin_shutdown.mdep = (char *)mdep; 188*6a3b10dbStz204579 break; 189*6a3b10dbStz204579 case A_REBOOT: 190*6a3b10dbStz204579 event->adt_uadmin_reboot.fcn = fcn_id; 191*6a3b10dbStz204579 event->adt_uadmin_reboot.mdep = (char *)mdep; 192*6a3b10dbStz204579 break; 193*6a3b10dbStz204579 case A_DUMP: 194*6a3b10dbStz204579 event->adt_uadmin_dump.fcn = fcn_id; 195*6a3b10dbStz204579 event->adt_uadmin_dump.mdep = (char *)mdep; 196*6a3b10dbStz204579 break; 197*6a3b10dbStz204579 case A_REMOUNT: 198*6a3b10dbStz204579 /* no parameters */ 199*6a3b10dbStz204579 break; 200*6a3b10dbStz204579 case A_FREEZE: 201*6a3b10dbStz204579 event->adt_uadmin_freeze.fcn = fcn_id; 202*6a3b10dbStz204579 event->adt_uadmin_freeze.mdep = (char *)mdep; 203*6a3b10dbStz204579 break; 204*6a3b10dbStz204579 case A_FTRACE: 205*6a3b10dbStz204579 event->adt_uadmin_ftrace.fcn = fcn_id; 206*6a3b10dbStz204579 break; 207*6a3b10dbStz204579 case A_SWAPCTL: 208*6a3b10dbStz204579 event->adt_uadmin_swapctl.fcn = fcn_id; 209*6a3b10dbStz204579 break; 210*6a3b10dbStz204579 } 211*6a3b10dbStz204579 212*6a3b10dbStz204579 if (adt_put_event(event, ADT_SUCCESS, 0) != 0) { 213*6a3b10dbStz204579 (void) fprintf(stderr, 214*6a3b10dbStz204579 "%s: can't put audit event\n", argv[0]); 215*6a3b10dbStz204579 } 216*6a3b10dbStz204579 /* 217*6a3b10dbStz204579 * allow audit record to be processed in the kernel 218*6a3b10dbStz204579 * audit queue 219*6a3b10dbStz204579 */ 220*6a3b10dbStz204579 wait_for_auqueue(); 221*6a3b10dbStz204579 } 222*6a3b10dbStz204579 223*6a3b10dbStz204579 if (turnoff_auditd() == -1) 2247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: can't turn off auditd\n", 2257c478bd9Sstevel@tonic-gate argv[0]); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate if (cmd == A_SHUTDOWN || cmd == A_REBOOT) 22858091fd8Ssetje (void) creat(SMF_RST, 0777); 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 231*6a3b10dbStz204579 (void) adt_free_event(event); 232*6a3b10dbStz204579 (void) adt_end_session(ah); 233*6a3b10dbStz204579 2347c478bd9Sstevel@tonic-gate if (uadmin(cmd, fcn, mdep) < 0) { 2357c478bd9Sstevel@tonic-gate perror("uadmin"); 2367c478bd9Sstevel@tonic-gate 23758091fd8Ssetje (void) unlink(SMF_RST); 23858091fd8Ssetje 2397c478bd9Sstevel@tonic-gate return (1); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate return (0); 2437c478bd9Sstevel@tonic-gate } 244*6a3b10dbStz204579 245*6a3b10dbStz204579 static int 246*6a3b10dbStz204579 turnoff_auditd() 247*6a3b10dbStz204579 { 248*6a3b10dbStz204579 char *smf_state; 249*6a3b10dbStz204579 int rc = -1; 250*6a3b10dbStz204579 int retries = 15; 251*6a3b10dbStz204579 252*6a3b10dbStz204579 if (smf_disable_instance(AUDITD_FMRI, SMF_TEMPORARY) != 0) { 253*6a3b10dbStz204579 (void) fprintf(stderr, "error disabling auditd: %s\n", 254*6a3b10dbStz204579 scf_strerror(scf_error())); 255*6a3b10dbStz204579 return (-1); 256*6a3b10dbStz204579 } 257*6a3b10dbStz204579 258*6a3b10dbStz204579 /* wait for auditd to finish its work */ 259*6a3b10dbStz204579 do { 260*6a3b10dbStz204579 if ((smf_state = smf_get_state(AUDITD_FMRI)) == NULL) { 261*6a3b10dbStz204579 (void) fprintf(stderr, 262*6a3b10dbStz204579 "getting state of auditd failed: %s\n", 263*6a3b10dbStz204579 scf_strerror(scf_error())); 264*6a3b10dbStz204579 return (-1); 265*6a3b10dbStz204579 } 266*6a3b10dbStz204579 267*6a3b10dbStz204579 if (strcmp(smf_state, SCF_STATE_STRING_DISABLED)) { 268*6a3b10dbStz204579 retries--; 269*6a3b10dbStz204579 (void) sleep(1); 270*6a3b10dbStz204579 } else { 271*6a3b10dbStz204579 rc = 0; 272*6a3b10dbStz204579 } 273*6a3b10dbStz204579 free(smf_state); 274*6a3b10dbStz204579 } while (rc && retries); 275*6a3b10dbStz204579 276*6a3b10dbStz204579 return (rc); 277*6a3b10dbStz204579 } 278*6a3b10dbStz204579 279*6a3b10dbStz204579 static void 280*6a3b10dbStz204579 wait_for_auqueue() 281*6a3b10dbStz204579 { 282*6a3b10dbStz204579 au_stat_t au_stat; 283*6a3b10dbStz204579 int retries = 10; 284*6a3b10dbStz204579 285*6a3b10dbStz204579 while (retries-- && auditon(A_GETSTAT, (caddr_t)&au_stat, NULL) == 0) { 286*6a3b10dbStz204579 if (au_stat.as_enqueue == au_stat.as_written) { 287*6a3b10dbStz204579 break; 288*6a3b10dbStz204579 } 289*6a3b10dbStz204579 (void) sleep(1); 290*6a3b10dbStz204579 } 291*6a3b10dbStz204579 } 292