limiting singleuser access

Jim Knutson knutson%marconi.sw.MCC.COM at mcc.com
Sat Jul 22 01:09:27 AEST 1989


This has been discussed before, but we use root's .profile and a special
program to limit singleuser access.  The special program prompts for a
root password, but also gives the user the capability to type halt or
reboot and get the machine going again.  Note that root's default shell
cannot be /bin/sh for this to work.

Jim Knutson
knutson at mcc.com
cs.utexas.edu!milano!knutson

---- /.profile ----

trap "" 3
trap "" 8
trap "" 18

PATH=/etc:/usr/etc:/usr/ucb:/bin:/usr/bin:.
PATH=$PATH:/usr/hosts:/usr/local/bin:/usr/local/etc
TZ=CST6CDT
export PATH TERM TZ
stty dec

###### Use a locking program to prompt for password when single-user ######
SULOCK=/etc/.singleuserlock

echo "Entering single-user mode."
if [ -x $SULOCK ]; then
	$SULOCK
fi

trap 3
trap 8
trap 18

TERM=sun
USER=root
HOME=/
export TERM USER HOME

---- singleuserlock.c ----

/* example written by Bruce G. Barnett <barnett at ge-crd.arpa> */
#include	<stdio.h>
#include	<signal.h>
#include	<pwd.h>
#include	<sys/reboot.h>
#include	<sys/time.h>
#include	<errno.h>

#define	ROOT_UID	0
#define	MAXTRIES	4	/* number of tries for password */
#define	ALARM		60	/* seconds for alarm */
#define	INIT_PID	1	/* PID of init */

struct	passwd *pwd;
struct	passwd *getpwuid();
char	*strcpy();
char	*crypt();
char	*getpass();
char	*pw;
char	pwbuf[32];
int	numtries;
int	timeout();

main()
{
	(void) signal(SIGINT, SIG_IGN);
	(void) signal(SIGQUIT, SIG_IGN);
	(void) signal(SIGTSTP, SIG_IGN);
	(void) signal(SIGALRM, timeout);

/* get the password entry for root */

/* use 0 if you want to hard-wire the passwd for root */
/* else use getuid() */

	if(geteuid() != ROOT_UID) {
		(void) fprintf(stderr, "Permission denied.\n");
		exit(1);
		}
	pwd=getpwuid(ROOT_UID);
	if (pwd == NULL ) {
		(void) fprintf(stderr,"Cannot get password entry for root.\n");
		doreboot(RB_HALT);
		}

	(void) alarm(ALARM);
	while (numtries<MAXTRIES) {
		(void) fprintf(stderr,
			"Enter: root password, \"halt\", or \"reboot\".\n");
		(void) strcpy(pwbuf, getpass("Password:"));
		pw = crypt(pwbuf, pwd->pw_passwd);
		if (strcmp(pw, pwd->pw_passwd) == 0 )
			exit(0);
		if(strcmp(pwbuf, "halt") == 0) {
			(void) fprintf(stderr, "System halting...\n");
			doreboot(RB_HALT);
			}
		if(strcmp(pwbuf, "reboot") == 0) {
			(void) fprintf(stderr, "System rebooting...\n");
			doreboot(RB_AUTOBOOT);
			}
		(void) fprintf(stderr, "Incorrect password.\n");
		numtries++;
	}
	(void) alarm(0);
	(void) fprintf(stderr, "Root login failed.  System halting....\n");
	doreboot(RB_HALT);
}

timeout()
{
	(void) alarm(0);
	(void) fprintf(stderr, "\nTime out after %d seconds.\n", ALARM);
	(void) fprintf(stderr, "System halting...\n");
	doreboot(RB_HALT);
}

doreboot(howto)
int	howto;
{
	int	i;
	extern	int	errno;

	(void) alarm(0);
	sync();
	if(kill(INIT_PID, SIGTSTP) == -1)
		(void) fprintf(stderr, "Can't idle init.\n");
	sleep(1);
	(void) kill(-1, SIGTERM);
	sleep(5);
	sync();
	for(i=0; ; i++) {
		if(kill(-1, SIGKILL) == -1) {
			if(errno == ESRCH)
				break;
			}
		if(i>5) {
			(void) fprintf(stderr,
				"CAUTION: some process(es) wouldn't die.\n");
			break;
			}
		}

	sync();

	reboot(howto);

	/* If the reboot() fails, make sure that the system does nothing */
	pause();
}



More information about the Comp.sys.sun mailing list