xref: /titanic_51/usr/src/cmd/uadmin/uadmin.c (revision 6a3b10db10504576d94f22ea0d7aaf12b96b0bbe)
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