lock.c revision 110609
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 110609 2003-02-10 02:08:49Z tjr $"); 501590Srgrimes 511590Srgrimes/* 5299709Sdd * Lock a terminal up until the given key is entered or the given 5399709Sdd * 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> 63100806Sdd#include <sys/consio.h> 6427575Scharnier#include <err.h> 6527575Scharnier#include <ctype.h> 6627575Scharnier#include <pwd.h> 671590Srgrimes#include <stdio.h> 6827575Scharnier#include <stdlib.h> 691590Srgrimes#include <string.h> 7052158Snectar#include <syslog.h> 71110609Stjr#include <termios.h> 7227575Scharnier#include <unistd.h> 7352158Snectar#include <varargs.h> 741590Srgrimes 751590Srgrimes#define TIMEOUT 15 761590Srgrimes 7792920Simpvoid quit(int); 7892920Simpvoid bye(int); 7992920Simpvoid hi(int); 8092920Simpstatic void usage(void); 811590Srgrimes 821590Srgrimesstruct timeval timeout; 831590Srgrimesstruct timeval zerotime; 84110609Stjrstruct termios tty, ntty; 851590Srgrimeslong nexttime; /* keep the timeout time */ 8618295Srobertoint no_timeout; /* lock terminal forever */ 87100806Sddint vtyunlock; /* Unlock flag and code. */ 881590Srgrimes 891590Srgrimes/*ARGSUSED*/ 9027575Scharnierint 91102944Sdwmalonemain(int argc, 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; 98100806Sdd int ch, failures, sectimeout, usemine, vtylock; 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; 10799708Sdd no_timeout = 0; 108100806Sdd vtylock = 0; 109100806Sdd while ((ch = getopt(argc, argv, "npt:v")) != -1) 1101590Srgrimes switch((char)ch) { 1111590Srgrimes case 't': 11227575Scharnier if ((sectimeout = atoi(optarg)) <= 0) 11327575Scharnier errx(1, "illegal timeout value"); 1141590Srgrimes break; 1151590Srgrimes case 'p': 1161590Srgrimes usemine = 1; 11727575Scharnier if (!(pw = getpwuid(getuid()))) 11827575Scharnier errx(1, "unknown uid %d", getuid()); 1191590Srgrimes mypw = strdup(pw->pw_passwd); 1201590Srgrimes break; 12199708Sdd case 'n': 12299708Sdd no_timeout = 1; 12399708Sdd break; 124100806Sdd case 'v': 125100806Sdd vtylock = 1; 126100806Sdd break; 1271590Srgrimes case '?': 1281590Srgrimes default: 12927575Scharnier usage(); 13099708Sdd } 1311590Srgrimes timeout.tv_sec = sectimeout * 60; 1321590Srgrimes 1331590Srgrimes setuid(getuid()); /* discard privs */ 1341590Srgrimes 135110609Stjr if (tcgetattr(0, &tty)) /* get information for header */ 1361590Srgrimes exit(1); 1371590Srgrimes gethostname(hostname, sizeof(hostname)); 13827575Scharnier if (!(ttynam = ttyname(0))) 13927575Scharnier errx(1, "not a terminal?"); 14027575Scharnier if (gettimeofday(&timval, (struct timezone *)NULL)) 14127575Scharnier err(1, "gettimeofday"); 1421590Srgrimes nexttime = timval.tv_sec + (sectimeout * 60); 14337262Sbde timval_sec = timval.tv_sec; 14437262Sbde timp = localtime(&timval_sec); 1451590Srgrimes ap = asctime(timp); 1461590Srgrimes tzn = timp->tm_zone; 1471590Srgrimes 1481590Srgrimes (void)signal(SIGINT, quit); 1491590Srgrimes (void)signal(SIGQUIT, quit); 150110609Stjr ntty = tty; ntty.c_lflag &= ~ECHO; 151110609Stjr (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &ntty); 1521590Srgrimes 1531590Srgrimes if (!mypw) { 1541590Srgrimes /* get key and check again */ 1551590Srgrimes (void)printf("Key: "); 1561590Srgrimes if (!fgets(s, sizeof(s), stdin) || *s == '\n') 15787286Sdwmalone quit(0); 1581590Srgrimes (void)printf("\nAgain: "); 1591590Srgrimes /* 1601590Srgrimes * Don't need EOF test here, if we get EOF, then s1 != s 1611590Srgrimes * and the right things will happen. 1621590Srgrimes */ 1631590Srgrimes (void)fgets(s1, sizeof(s1), stdin); 1641590Srgrimes (void)putchar('\n'); 1651590Srgrimes if (strcmp(s1, s)) { 1661590Srgrimes (void)printf("\07lock: passwords didn't match.\n"); 167110609Stjr (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &tty); 1681590Srgrimes exit(1); 1691590Srgrimes } 17027575Scharnier s[0] = '\0'; 1711590Srgrimes mypw = s1; 1721590Srgrimes } 1731590Srgrimes 1741590Srgrimes /* set signal handlers */ 1751590Srgrimes (void)signal(SIGINT, hi); 1761590Srgrimes (void)signal(SIGQUIT, hi); 1771590Srgrimes (void)signal(SIGTSTP, hi); 1781590Srgrimes (void)signal(SIGALRM, bye); 1791590Srgrimes 1801590Srgrimes ntimer.it_interval = zerotime; 1811590Srgrimes ntimer.it_value = timeout; 18299708Sdd if (!no_timeout) 18399708Sdd setitimer(ITIMER_REAL, &ntimer, &otimer); 184100806Sdd if (vtylock) { 185100806Sdd /* 186100806Sdd * If this failed, we want to err out; warn isn't good 187100806Sdd * enough, since we don't want the user to think that 188100806Sdd * everything is nice and locked because they got a 189100806Sdd * "Key:" prompt. 190100806Sdd */ 191100806Sdd if (ioctl(0, VT_LOCKSWITCH, &vtylock) == -1) { 192110609Stjr (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &tty); 193100806Sdd err(1, "locking vty"); 194100806Sdd } 195100806Sdd vtyunlock = 0x2; 196100806Sdd } 1971590Srgrimes 1981590Srgrimes /* header info */ 199100806Sdd (void)printf("lock: %s on %s.", ttynam, hostname); 200100806Sdd if (no_timeout) 201100806Sdd (void)printf(" no timeout."); 202100806Sdd else 203100806Sdd (void)printf(" timeout in %d minute%s.", sectimeout, 204100806Sdd sectimeout != 1 ? "s" : ""); 205100806Sdd if (vtylock) 206100806Sdd (void)printf(" vty locked."); 207100806Sdd (void)printf("\ntime now is %.20s%s%s", ap, tzn, ap + 19); 208100806Sdd 20999708Sdd failures = 0; 2101590Srgrimes 2111590Srgrimes for (;;) { 2121590Srgrimes (void)printf("Key: "); 2131590Srgrimes if (!fgets(s, sizeof(s), stdin)) { 2141590Srgrimes clearerr(stdin); 21587286Sdwmalone hi(0); 2161590Srgrimes continue; 2171590Srgrimes } 2181590Srgrimes if (usemine) { 2191590Srgrimes s[strlen(s) - 1] = '\0'; 2201590Srgrimes if (!strcmp(mypw, crypt(s, mypw))) 2211590Srgrimes break; 2221590Srgrimes } 2231590Srgrimes else if (!strcmp(s, s1)) 2241590Srgrimes break; 2251590Srgrimes (void)printf("\07\n"); 22652158Snectar failures++; 22752158Snectar if (getuid() == 0) 22852158Snectar syslog(LOG_NOTICE, "%d ROOT UNLOCK FAILURE%s (%s on %s)", 22952158Snectar failures, failures > 1 ? "S": "", ttynam, hostname); 230110609Stjr if (tcgetattr(0, &ntty)) 2311590Srgrimes exit(1); 23252158Snectar sleep(1); /* to discourage guessing */ 2331590Srgrimes } 23452158Snectar if (getuid() == 0) 23599708Sdd syslog(LOG_NOTICE, "ROOT UNLOCK ON hostname %s port %s", 23699708Sdd hostname, ttynam); 23787286Sdwmalone quit(0); 23827575Scharnier return(0); /* not reached */ 2391590Srgrimes} 2401590Srgrimes 24127575Scharnier 24227575Scharnierstatic void 243102944Sdwmaloneusage(void) 24427575Scharnier{ 245100806Sdd (void)fprintf(stderr, "usage: lock [-npv] [-t timeout]\n"); 24627575Scharnier exit(1); 24727575Scharnier} 24827575Scharnier 2491590Srgrimesvoid 25087286Sdwmalonehi(int signo __unused) 2511590Srgrimes{ 2521590Srgrimes struct timeval timval; 2531590Srgrimes 25499708Sdd if (!gettimeofday(&timval, (struct timezone *)NULL)) { 25599708Sdd (void)printf("lock: type in the unlock key. "); 25699708Sdd if (no_timeout) { 25799708Sdd (void)putchar('\n'); 25899708Sdd } else { 25999708Sdd (void)printf("timeout in %ld:%ld minutes\n", 26099708Sdd (nexttime - timval.tv_sec) / 60, 26199708Sdd (nexttime - timval.tv_sec) % 60); 26299708Sdd } 26399708Sdd } 2641590Srgrimes} 2651590Srgrimes 2661590Srgrimesvoid 26787286Sdwmalonequit(int signo __unused) 2681590Srgrimes{ 2691590Srgrimes (void)putchar('\n'); 270110609Stjr (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &tty); 271100806Sdd if (vtyunlock) 272100806Sdd (void)ioctl(0, VT_LOCKSWITCH, &vtyunlock); 2731590Srgrimes exit(0); 2741590Srgrimes} 2751590Srgrimes 2761590Srgrimesvoid 27787286Sdwmalonebye(int signo __unused) 2781590Srgrimes{ 27999708Sdd if (!no_timeout) { 280110609Stjr (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &tty); 281100806Sdd if (vtyunlock) 282100806Sdd (void)ioctl(0, VT_LOCKSWITCH, &vtyunlock); 28399708Sdd (void)printf("lock: timeout\n"); 28499708Sdd exit(1); 28599708Sdd } 2861590Srgrimes} 287