knutson%marconi.sw.MCC.COM@mcc.com (Jim Knutson) (07/21/89)
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@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@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(); }