lock.c revision 99112
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1987, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Bob Toxen. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 3. All advertising materials mentioning features or use of this software 171590Srgrimes * must display the following acknowledgement: 181590Srgrimes * This product includes software developed by the University of 191590Srgrimes * California, Berkeley and its contributors. 201590Srgrimes * 4. Neither the name of the University nor the names of its contributors 211590Srgrimes * may be used to endorse or promote products derived from this software 221590Srgrimes * without specific prior written permission. 231590Srgrimes * 241590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341590Srgrimes * SUCH DAMAGE. 351590Srgrimes */ 361590Srgrimes 371590Srgrimes#ifndef lint 3827575Scharnierstatic const char copyright[] = 391590Srgrimes"@(#) Copyright (c) 1980, 1987, 1993\n\ 401590Srgrimes The Regents of the University of California. All rights reserved.\n"; 411590Srgrimes#endif /* not lint */ 421590Srgrimes 431590Srgrimes#ifndef lint 4427575Scharnier#if 0 451590Srgrimesstatic char sccsid[] = "@(#)lock.c 8.1 (Berkeley) 6/6/93"; 4627575Scharnier#endif 471590Srgrimes#endif /* not lint */ 4899112Sobrien#include <sys/cdefs.h> 4999112Sobrien__FBSDID("$FreeBSD: head/usr.bin/lock/lock.c 99112 2002-06-30 05:25:07Z obrien $"); 501590Srgrimes 511590Srgrimes/* 521590Srgrimes * Lock a terminal up until the given key is entered, until the root 531590Srgrimes * password is entered, or the given interval times out. 541590Srgrimes * 551590Srgrimes * Timeout interval is by default TIMEOUT, it can be changed with 561590Srgrimes * an argument of the form -time where time is in minutes 571590Srgrimes */ 581590Srgrimes 591590Srgrimes#include <sys/param.h> 601590Srgrimes#include <sys/stat.h> 611590Srgrimes#include <sys/time.h> 621590Srgrimes#include <sys/signal.h> 6327575Scharnier#include <err.h> 6427575Scharnier#include <ctype.h> 6527575Scharnier#include <pwd.h> 661590Srgrimes#include <sgtty.h> 671590Srgrimes#include <stdio.h> 6827575Scharnier#include <stdlib.h> 691590Srgrimes#include <string.h> 7052158Snectar#include <syslog.h> 7127575Scharnier#include <unistd.h> 7252158Snectar#include <varargs.h> 731590Srgrimes 741590Srgrimes#define TIMEOUT 15 751590Srgrimes 7692920Simpvoid quit(int); 7792920Simpvoid bye(int); 7892920Simpvoid hi(int); 7992920Simpstatic void usage(void); 801590Srgrimes 811590Srgrimesstruct timeval timeout; 821590Srgrimesstruct timeval zerotime; 831590Srgrimesstruct sgttyb tty, ntty; 841590Srgrimeslong nexttime; /* keep the timeout time */ 8518295Srobertoint no_timeout; /* lock terminal forever */ 861590Srgrimes 871590Srgrimes/*ARGSUSED*/ 8827575Scharnierint 891590Srgrimesmain(argc, argv) 901590Srgrimes int argc; 911590Srgrimes char **argv; 921590Srgrimes{ 931590Srgrimes struct passwd *pw; 941590Srgrimes struct timeval timval; 9537262Sbde time_t timval_sec; 961590Srgrimes struct itimerval ntimer, otimer; 971590Srgrimes struct tm *timp; 9852158Snectar int ch, failures, sectimeout, usemine; 991590Srgrimes char *ap, *mypw, *ttynam, *tzn; 1001590Srgrimes char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ]; 1011590Srgrimes 10252158Snectar openlog("lock", LOG_ODELAY, LOG_AUTH); 10352158Snectar 1041590Srgrimes sectimeout = TIMEOUT; 1051590Srgrimes mypw = NULL; 1061590Srgrimes usemine = 0; 10718295Sroberto no_timeout = 0; 10824360Simp while ((ch = getopt(argc, argv, "npt:")) != -1) 1091590Srgrimes switch((char)ch) { 1101590Srgrimes case 't': 11127575Scharnier if ((sectimeout = atoi(optarg)) <= 0) 11227575Scharnier errx(1, "illegal timeout value"); 1131590Srgrimes break; 1141590Srgrimes case 'p': 1151590Srgrimes usemine = 1; 11627575Scharnier if (!(pw = getpwuid(getuid()))) 11727575Scharnier errx(1, "unknown uid %d", getuid()); 1181590Srgrimes mypw = strdup(pw->pw_passwd); 1191590Srgrimes break; 12018295Sroberto case 'n': 12118295Sroberto no_timeout = 1; 12218295Sroberto break; 1231590Srgrimes case '?': 1241590Srgrimes default: 12527575Scharnier usage(); 1261590Srgrimes } 1271590Srgrimes timeout.tv_sec = sectimeout * 60; 1281590Srgrimes 1291590Srgrimes setuid(getuid()); /* discard privs */ 1301590Srgrimes 1311590Srgrimes if (ioctl(0, TIOCGETP, &tty)) /* get information for header */ 1321590Srgrimes exit(1); 1331590Srgrimes gethostname(hostname, sizeof(hostname)); 13427575Scharnier if (!(ttynam = ttyname(0))) 13527575Scharnier errx(1, "not a terminal?"); 13627575Scharnier if (gettimeofday(&timval, (struct timezone *)NULL)) 13727575Scharnier err(1, "gettimeofday"); 1381590Srgrimes nexttime = timval.tv_sec + (sectimeout * 60); 13937262Sbde timval_sec = timval.tv_sec; 14037262Sbde timp = localtime(&timval_sec); 1411590Srgrimes ap = asctime(timp); 1421590Srgrimes tzn = timp->tm_zone; 1431590Srgrimes 1441590Srgrimes (void)signal(SIGINT, quit); 1451590Srgrimes (void)signal(SIGQUIT, quit); 1461590Srgrimes ntty = tty; ntty.sg_flags &= ~ECHO; 1471590Srgrimes (void)ioctl(0, TIOCSETP, &ntty); 1481590Srgrimes 1491590Srgrimes if (!mypw) { 1501590Srgrimes /* get key and check again */ 1511590Srgrimes (void)printf("Key: "); 1521590Srgrimes if (!fgets(s, sizeof(s), stdin) || *s == '\n') 15387286Sdwmalone quit(0); 1541590Srgrimes (void)printf("\nAgain: "); 1551590Srgrimes /* 1561590Srgrimes * Don't need EOF test here, if we get EOF, then s1 != s 1571590Srgrimes * and the right things will happen. 1581590Srgrimes */ 1591590Srgrimes (void)fgets(s1, sizeof(s1), stdin); 1601590Srgrimes (void)putchar('\n'); 1611590Srgrimes if (strcmp(s1, s)) { 1621590Srgrimes (void)printf("\07lock: passwords didn't match.\n"); 1631590Srgrimes ioctl(0, TIOCSETP, &tty); 1641590Srgrimes exit(1); 1651590Srgrimes } 16627575Scharnier s[0] = '\0'; 1671590Srgrimes mypw = s1; 1681590Srgrimes } 1691590Srgrimes 1701590Srgrimes /* set signal handlers */ 1711590Srgrimes (void)signal(SIGINT, hi); 1721590Srgrimes (void)signal(SIGQUIT, hi); 1731590Srgrimes (void)signal(SIGTSTP, hi); 1741590Srgrimes (void)signal(SIGALRM, bye); 1751590Srgrimes 1761590Srgrimes ntimer.it_interval = zerotime; 1771590Srgrimes ntimer.it_value = timeout; 17818295Sroberto if (!no_timeout) 17918295Sroberto setitimer(ITIMER_REAL, &ntimer, &otimer); 1801590Srgrimes 1811590Srgrimes /* header info */ 18218295Sroberto if (no_timeout) { 18318295Sroberto(void)printf("lock: %s on %s. no timeout\ntime now is %.20s%s%s", 18418295Sroberto ttynam, hostname, ap, tzn, ap + 19); 18518295Sroberto } else { 1861590Srgrimes(void)printf("lock: %s on %s. timeout in %d minutes\ntime now is %.20s%s%s", 1871590Srgrimes ttynam, hostname, sectimeout, ap, tzn, ap + 19); 18818295Sroberto } 18952158Snectar failures = 0; 1901590Srgrimes 1911590Srgrimes for (;;) { 1921590Srgrimes (void)printf("Key: "); 1931590Srgrimes if (!fgets(s, sizeof(s), stdin)) { 1941590Srgrimes clearerr(stdin); 19587286Sdwmalone hi(0); 1961590Srgrimes continue; 1971590Srgrimes } 1981590Srgrimes if (usemine) { 1991590Srgrimes s[strlen(s) - 1] = '\0'; 2001590Srgrimes if (!strcmp(mypw, crypt(s, mypw))) 2011590Srgrimes break; 2021590Srgrimes } 2031590Srgrimes else if (!strcmp(s, s1)) 2041590Srgrimes break; 2051590Srgrimes (void)printf("\07\n"); 20652158Snectar failures++; 20752158Snectar if (getuid() == 0) 20852158Snectar syslog(LOG_NOTICE, "%d ROOT UNLOCK FAILURE%s (%s on %s)", 20952158Snectar failures, failures > 1 ? "S": "", ttynam, hostname); 2101590Srgrimes if (ioctl(0, TIOCGETP, &ntty)) 2111590Srgrimes exit(1); 21252158Snectar sleep(1); /* to discourage guessing */ 2131590Srgrimes } 21452158Snectar if (getuid() == 0) 21552158Snectar syslog(LOG_NOTICE, "ROOT UNLOCK ON hostname %s port %s", 21652158Snectar hostname, ttynam); 21787286Sdwmalone quit(0); 21827575Scharnier return(0); /* not reached */ 2191590Srgrimes} 2201590Srgrimes 22127575Scharnier 22227575Scharnierstatic void 22327575Scharnierusage() 22427575Scharnier{ 22527575Scharnier (void)fprintf(stderr, "usage: lock [-n] [-p] [-t timeout]\n"); 22627575Scharnier exit(1); 22727575Scharnier} 22827575Scharnier 2291590Srgrimesvoid 23087286Sdwmalonehi(int signo __unused) 2311590Srgrimes{ 2321590Srgrimes struct timeval timval; 2331590Srgrimes 23418295Sroberto if (!gettimeofday(&timval, (struct timezone *)NULL)) { 23518295Sroberto (void)printf("lock: type in the unlock key. "); 23618295Sroberto if (no_timeout) { 23718295Sroberto (void)putchar('\n'); 23818295Sroberto } else { 23918295Sroberto (void)printf("timeout in %ld:%ld minutes\n", 24018295Sroberto (nexttime - timval.tv_sec) / 60, 24118295Sroberto (nexttime - timval.tv_sec) % 60); 24218295Sroberto } 24318295Sroberto } 2441590Srgrimes} 2451590Srgrimes 2461590Srgrimesvoid 24787286Sdwmalonequit(int signo __unused) 2481590Srgrimes{ 2491590Srgrimes (void)putchar('\n'); 2501590Srgrimes (void)ioctl(0, TIOCSETP, &tty); 2511590Srgrimes exit(0); 2521590Srgrimes} 2531590Srgrimes 2541590Srgrimesvoid 25587286Sdwmalonebye(int signo __unused) 2561590Srgrimes{ 25718295Sroberto if (!no_timeout) { 25818295Sroberto (void)ioctl(0, TIOCSETP, &tty); 25918295Sroberto (void)printf("lock: timeout\n"); 26018295Sroberto exit(1); 26118295Sroberto } 2621590Srgrimes} 263