xref: /titanic_51/usr/src/cmd/uadmin/uadmin.c (revision e333042d319d2ba8ccbbd914d8b6ee5b8b990931)
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 /*
22*e333042dSgww  * 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 
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>
386a3b10dbStz204579 #include <bsm/adt.h>
396a3b10dbStz204579 #include <bsm/adt_event.h>
406a3b10dbStz204579 #include <libscf.h>
416a3b10dbStz204579 #include <strings.h>
427c478bd9Sstevel@tonic-gate 
4358091fd8Ssetje #define	SMF_RST	"/etc/svc/volatile/resetting"
446a3b10dbStz204579 #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*e333042dSgww static int turnoff_auditd(int, int);
496a3b10dbStz204579 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;
576a3b10dbStz204579 	adt_session_data_t *ah;  /* audit session handle */
586a3b10dbStz204579 	adt_event_data_t *event = NULL; /* event to be generated */
596a3b10dbStz204579 	au_event_t event_id;
606a3b10dbStz204579 	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 
846a3b10dbStz204579 	/* set up audit session and event */
856a3b10dbStz204579 	if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
866a3b10dbStz204579 		(void) fprintf(stderr, "%s: can't start audit session\n",
876a3b10dbStz204579 		    argv[0]);
886a3b10dbStz204579 	}
896a3b10dbStz204579 	switch (cmd) {
906a3b10dbStz204579 	case A_SHUTDOWN:
916a3b10dbStz204579 		event_id = ADT_uadmin_shutdown;
926a3b10dbStz204579 		break;
936a3b10dbStz204579 	case A_REBOOT:
946a3b10dbStz204579 		event_id = ADT_uadmin_reboot;
956a3b10dbStz204579 		break;
966a3b10dbStz204579 	case A_DUMP:
976a3b10dbStz204579 		event_id = ADT_uadmin_dump;
986a3b10dbStz204579 		break;
996a3b10dbStz204579 	case A_REMOUNT:
1006a3b10dbStz204579 		event_id = ADT_uadmin_remount;
1016a3b10dbStz204579 		break;
1026a3b10dbStz204579 	case A_FREEZE:
1036a3b10dbStz204579 		event_id = ADT_uadmin_freeze;
1046a3b10dbStz204579 		break;
1056a3b10dbStz204579 	case A_FTRACE:
1066a3b10dbStz204579 		event_id = ADT_uadmin_ftrace;
1076a3b10dbStz204579 		break;
1086a3b10dbStz204579 	case A_SWAPCTL:
1096a3b10dbStz204579 		event_id = ADT_uadmin_swapctl;
1106a3b10dbStz204579 		break;
1116a3b10dbStz204579 	default:
1126a3b10dbStz204579 		event_id = 0;
1136a3b10dbStz204579 	}
1146a3b10dbStz204579 	if ((event_id != 0) &&
1156a3b10dbStz204579 	    (event = adt_alloc_event(ah, event_id)) == NULL) {
1166a3b10dbStz204579 		(void) fprintf(stderr, "%s: can't allocate audit event\n",
1176a3b10dbStz204579 		    argv[0]);
1186a3b10dbStz204579 	}
1196a3b10dbStz204579 	switch (fcn) {
1206a3b10dbStz204579 	case AD_HALT:
1216a3b10dbStz204579 		fcn_id = ADT_UADMIN_FCN_AD_HALT;
1226a3b10dbStz204579 		break;
1236a3b10dbStz204579 	case AD_POWEROFF:
1246a3b10dbStz204579 		fcn_id = ADT_UADMIN_FCN_AD_POWEROFF;
1256a3b10dbStz204579 		break;
1266a3b10dbStz204579 	case AD_BOOT:
1276a3b10dbStz204579 		fcn_id = ADT_UADMIN_FCN_AD_BOOT;
1286a3b10dbStz204579 		break;
1296a3b10dbStz204579 	case AD_IBOOT:
1306a3b10dbStz204579 		fcn_id = ADT_UADMIN_FCN_AD_IBOOT;
1316a3b10dbStz204579 		break;
1326a3b10dbStz204579 	case AD_SBOOT:
1336a3b10dbStz204579 		fcn_id = ADT_UADMIN_FCN_AD_SBOOT;
1346a3b10dbStz204579 		break;
1356a3b10dbStz204579 	case AD_SIBOOT:
1366a3b10dbStz204579 		fcn_id = ADT_UADMIN_FCN_AD_SIBOOT;
1376a3b10dbStz204579 		break;
1386a3b10dbStz204579 	case AD_NOSYNC:
1396a3b10dbStz204579 		fcn_id = ADT_UADMIN_FCN_AD_NOSYNC;
1406a3b10dbStz204579 		break;
1416a3b10dbStz204579 	default:
1426a3b10dbStz204579 		fcn_id = 0;
1436a3b10dbStz204579 	}
1446a3b10dbStz204579 	if (cmd == A_FREEZE) {
1456a3b10dbStz204579 		switch (fcn) {
1466a3b10dbStz204579 		case AD_SUSPEND_TO_DISK:
1476a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_DISK;
1486a3b10dbStz204579 			break;
1496a3b10dbStz204579 		case AD_CHECK_SUSPEND_TO_DISK:
1506a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_DISK;
1516a3b10dbStz204579 			break;
1526a3b10dbStz204579 		case AD_FORCE:
1536a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_FORCE;
1546a3b10dbStz204579 			break;
1556a3b10dbStz204579 		case AD_SUSPEND_TO_RAM:
1566a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_RAM;
1576a3b10dbStz204579 			break;
1586a3b10dbStz204579 		case AD_CHECK_SUSPEND_TO_RAM:
1596a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_RAM;
1606a3b10dbStz204579 			break;
1616a3b10dbStz204579 		case AD_REUSEINIT:
1626a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_REUSEINIT;
1636a3b10dbStz204579 			break;
1646a3b10dbStz204579 		case AD_REUSABLE:
1656a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_REUSABLE;
1666a3b10dbStz204579 			break;
1676a3b10dbStz204579 		case AD_REUSEFINI:
1686a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_REUSEFINI;
1696a3b10dbStz204579 			break;
1706a3b10dbStz204579 		}
1716a3b10dbStz204579 	} else if (cmd == A_FTRACE) {
1726a3b10dbStz204579 		switch (fcn) {
1736a3b10dbStz204579 		case AD_FTRACE_START:
1746a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_FTRACE_START;
1756a3b10dbStz204579 			break;
1766a3b10dbStz204579 		case AD_FTRACE_STOP:
1776a3b10dbStz204579 			fcn_id = ADT_UADMIN_FCN_AD_FTRACE_STOP;
1786a3b10dbStz204579 			break;
1796a3b10dbStz204579 		}
1806a3b10dbStz204579 	}
1816a3b10dbStz204579 
1827c478bd9Sstevel@tonic-gate 	if (geteuid() == 0) {
1836a3b10dbStz204579 		if (event != NULL) {
1846a3b10dbStz204579 			switch (cmd) {
1856a3b10dbStz204579 			case A_SHUTDOWN:
1866a3b10dbStz204579 				event->adt_uadmin_shutdown.fcn = fcn_id;
1876a3b10dbStz204579 				event->adt_uadmin_shutdown.mdep = (char *)mdep;
1886a3b10dbStz204579 				break;
1896a3b10dbStz204579 			case A_REBOOT:
1906a3b10dbStz204579 				event->adt_uadmin_reboot.fcn = fcn_id;
1916a3b10dbStz204579 				event->adt_uadmin_reboot.mdep = (char *)mdep;
1926a3b10dbStz204579 				break;
1936a3b10dbStz204579 			case A_DUMP:
1946a3b10dbStz204579 				event->adt_uadmin_dump.fcn = fcn_id;
1956a3b10dbStz204579 				event->adt_uadmin_dump.mdep = (char *)mdep;
1966a3b10dbStz204579 				break;
1976a3b10dbStz204579 			case A_REMOUNT:
1986a3b10dbStz204579 				/* no parameters */
1996a3b10dbStz204579 				break;
2006a3b10dbStz204579 			case A_FREEZE:
2016a3b10dbStz204579 				event->adt_uadmin_freeze.fcn = fcn_id;
2026a3b10dbStz204579 				event->adt_uadmin_freeze.mdep = (char *)mdep;
2036a3b10dbStz204579 				break;
2046a3b10dbStz204579 			case A_FTRACE:
2056a3b10dbStz204579 				event->adt_uadmin_ftrace.fcn = fcn_id;
2066a3b10dbStz204579 				break;
2076a3b10dbStz204579 			case A_SWAPCTL:
2086a3b10dbStz204579 				event->adt_uadmin_swapctl.fcn = fcn_id;
2096a3b10dbStz204579 				break;
2106a3b10dbStz204579 			}
2116a3b10dbStz204579 
2126a3b10dbStz204579 			if (adt_put_event(event, ADT_SUCCESS, 0) != 0) {
2136a3b10dbStz204579 				(void) fprintf(stderr,
2146a3b10dbStz204579 				    "%s: can't put audit event\n", argv[0]);
2156a3b10dbStz204579 			}
2166a3b10dbStz204579 			/*
2176a3b10dbStz204579 			 * allow audit record to be processed in the kernel
2186a3b10dbStz204579 			 * audit queue
2196a3b10dbStz204579 			 */
2206a3b10dbStz204579 			wait_for_auqueue();
2216a3b10dbStz204579 		}
2226a3b10dbStz204579 
223*e333042dSgww 		if (turnoff_auditd(cmd, fcn) == -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 
2316a3b10dbStz204579 	(void) adt_free_event(event);
2326a3b10dbStz204579 	(void) adt_end_session(ah);
2336a3b10dbStz204579 
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 }
2446a3b10dbStz204579 
2456a3b10dbStz204579 static int
246*e333042dSgww turnoff_auditd(int cmd, int fcn)
2476a3b10dbStz204579 {
2486a3b10dbStz204579 	char	*smf_state;
2496a3b10dbStz204579 	int	rc = -1;
2506a3b10dbStz204579 	int	retries = 15;
2516a3b10dbStz204579 
252*e333042dSgww 	switch (cmd) {
253*e333042dSgww 	case A_SHUTDOWN:
254*e333042dSgww 	case A_REBOOT:
255*e333042dSgww 	case A_DUMP:
256*e333042dSgww 		/* system shutting down, turn off auditd */
257*e333042dSgww 		break;
258*e333042dSgww 	case A_REMOUNT:
259*e333042dSgww 	case A_SWAPCTL:
260*e333042dSgww 	case A_FTRACE:
261*e333042dSgww 		/* No system discontinuity, don't turn off auditd */
262*e333042dSgww 		return (0);
263*e333042dSgww 	case A_FREEZE:
264*e333042dSgww 		switch (fcn) {
265*e333042dSgww 		case AD_CHECK_SUSPEND_TO_DISK:	/* AD_CHECK */
266*e333042dSgww 		case AD_CHECK_SUSPEND_TO_RAM:
267*e333042dSgww 		case AD_REUSEINIT:
268*e333042dSgww 		case AD_REUSEFINI:
269*e333042dSgww 			/* No system discontinuity, don't turn off auditd */
270*e333042dSgww 			return (0);
271*e333042dSgww 		case AD_REUSABLE:
272*e333042dSgww 		case AD_SUSPEND_TO_DISK:	/* AD_COMPRESS */
273*e333042dSgww 		case AD_SUSPEND_TO_RAM:
274*e333042dSgww 		case AD_FORCE:
275*e333042dSgww 			/* suspend the system, change audit files */
276*e333042dSgww 			/* XXX not implemented for now */
277*e333042dSgww 		default:
278*e333042dSgww 			return (-1);
279*e333042dSgww 		}
280*e333042dSgww 	default:
281*e333042dSgww 		return (-1);
282*e333042dSgww 	}
283*e333042dSgww 
2846a3b10dbStz204579 	if (smf_disable_instance(AUDITD_FMRI, SMF_TEMPORARY) != 0) {
2856a3b10dbStz204579 		(void) fprintf(stderr, "error disabling auditd: %s\n",
2866a3b10dbStz204579 		    scf_strerror(scf_error()));
2876a3b10dbStz204579 		return (-1);
2886a3b10dbStz204579 	}
2896a3b10dbStz204579 
2906a3b10dbStz204579 	/* wait for auditd to finish its work */
2916a3b10dbStz204579 	do {
2926a3b10dbStz204579 		if ((smf_state = smf_get_state(AUDITD_FMRI)) == NULL) {
2936a3b10dbStz204579 			(void) fprintf(stderr,
2946a3b10dbStz204579 			    "getting state of auditd failed: %s\n",
2956a3b10dbStz204579 			    scf_strerror(scf_error()));
2966a3b10dbStz204579 			return (-1);
2976a3b10dbStz204579 		}
2986a3b10dbStz204579 
2996a3b10dbStz204579 		if (strcmp(smf_state, SCF_STATE_STRING_DISABLED)) {
3006a3b10dbStz204579 			retries--;
3016a3b10dbStz204579 			(void) sleep(1);
3026a3b10dbStz204579 		} else {
3036a3b10dbStz204579 			rc = 0;
3046a3b10dbStz204579 		}
3056a3b10dbStz204579 		free(smf_state);
3066a3b10dbStz204579 	} while (rc && retries);
3076a3b10dbStz204579 
3086a3b10dbStz204579 	return (rc);
3096a3b10dbStz204579 }
3106a3b10dbStz204579 
3116a3b10dbStz204579 static void
3126a3b10dbStz204579 wait_for_auqueue()
3136a3b10dbStz204579 {
3146a3b10dbStz204579 	au_stat_t	au_stat;
3156a3b10dbStz204579 	int		retries = 10;
3166a3b10dbStz204579 
3176a3b10dbStz204579 	while (retries-- && auditon(A_GETSTAT, (caddr_t)&au_stat, NULL) == 0) {
3186a3b10dbStz204579 		if (au_stat.as_enqueue == au_stat.as_written) {
3196a3b10dbStz204579 			break;
3206a3b10dbStz204579 		}
3216a3b10dbStz204579 		(void) sleep(1);
3226a3b10dbStz204579 	}
3236a3b10dbStz204579 }
324