lock.c revision 100806
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1980, 1987, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from software contributed to Berkeley by 61541Srgrimes * Bob Toxen. 71541Srgrimes * 81541Srgrimes * Redistribution and use in source and binary forms, with or without 91541Srgrimes * modification, are permitted provided that the following conditions 101541Srgrimes * are met: 111541Srgrimes * 1. Redistributions of source code must retain the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer. 131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer in the 151541Srgrimes * documentation and/or other materials provided with the distribution. 161541Srgrimes * 3. All advertising materials mentioning features or use of this software 171541Srgrimes * must display the following acknowledgement: 181541Srgrimes * This product includes software developed by the University of 191541Srgrimes * California, Berkeley and its contributors. 201541Srgrimes * 4. Neither the name of the University nor the names of its contributors 211541Srgrimes * may be used to endorse or promote products derived from this software 221541Srgrimes * without specific prior written permission. 231541Srgrimes * 241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341541Srgrimes * SUCH DAMAGE. 351541Srgrimes */ 361541Srgrimes 371541Srgrimes#ifndef lint 3844510Swollmanstatic const char copyright[] = 3950477Speter"@(#) Copyright (c) 1980, 1987, 1993\n\ 401541Srgrimes The Regents of the University of California. All rights reserved.\n"; 411541Srgrimes#endif /* not lint */ 421541Srgrimes 431541Srgrimes#ifndef lint 4433392Sphk#if 0 451541Srgrimesstatic char sccsid[] = "@(#)lock.c 8.1 (Berkeley) 6/6/93"; 461541Srgrimes#endif 4733392Sphk#endif /* not lint */ 4833392Sphk#include <sys/cdefs.h> 4933392Sphk__FBSDID("$FreeBSD: head/usr.bin/lock/lock.c 100806 2002-07-28 07:13:53Z dd $"); 5033392Sphk 5133392Sphk/* 5233392Sphk * Lock a terminal up until the given key is entered or the given 5329680Sgibbs * interval times out. 5429680Sgibbs * 5529680Sgibbs * Timeout interval is by default TIMEOUT, it can be changed with 5629680Sgibbs * an argument of the form -time where time is in minutes 5733392Sphk */ 582112Swollman 5929680Sgibbs#include <sys/param.h> 601541Srgrimes#include <sys/stat.h> 611541Srgrimes#include <sys/time.h> 6229680Sgibbs#include <sys/signal.h> 6329680Sgibbs#include <sys/consio.h> 6429680Sgibbs#include <err.h> 6529680Sgibbs#include <ctype.h> 6629680Sgibbs#include <pwd.h> 6729680Sgibbs#include <sgtty.h> 6829680Sgibbs#include <stdio.h> 6929680Sgibbs#include <stdlib.h> 7029680Sgibbs#include <string.h> 7129680Sgibbs#include <syslog.h> 7232388Sphk#include <unistd.h> 7329680Sgibbs#include <varargs.h> 741541Srgrimes 751541Srgrimes#define TIMEOUT 15 761541Srgrimes 771541Srgrimesvoid quit(int); 7832391Sphkvoid bye(int); 791541Srgrimesvoid hi(int); 801541Srgrimesstatic void usage(void); 8129805Sgibbs 821541Srgrimesstruct timeval timeout; 8329805Sgibbsstruct timeval zerotime; 8433392Sphkstruct sgttyb tty, ntty; 851541Srgrimeslong nexttime; /* keep the timeout time */ 8633392Sphkint no_timeout; /* lock terminal forever */ 8733392Sphkint vtyunlock; /* Unlock flag and code. */ 8833392Sphk 8929680Sgibbs/*ARGSUSED*/ 9029680Sgibbsint 911541Srgrimesmain(argc, argv) 9229680Sgibbs int argc; 9329805Sgibbs char **argv; 9429805Sgibbs{ 9529805Sgibbs struct passwd *pw; 9629805Sgibbs struct timeval timval; 9729805Sgibbs time_t timval_sec; 9829805Sgibbs struct itimerval ntimer, otimer; 9929805Sgibbs struct tm *timp; 10029805Sgibbs int ch, failures, sectimeout, usemine, vtylock; 10129680Sgibbs char *ap, *mypw, *ttynam, *tzn; 10229805Sgibbs char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ]; 10329680Sgibbs 10429680Sgibbs openlog("lock", LOG_ODELAY, LOG_AUTH); 10529680Sgibbs 10629680Sgibbs sectimeout = TIMEOUT; 10729805Sgibbs mypw = NULL; 10829680Sgibbs usemine = 0; 10929680Sgibbs no_timeout = 0; 11029680Sgibbs vtylock = 0; 11129680Sgibbs while ((ch = getopt(argc, argv, "npt:v")) != -1) 11229680Sgibbs switch((char)ch) { 11329680Sgibbs case 't': 11429680Sgibbs if ((sectimeout = atoi(optarg)) <= 0) 11529680Sgibbs errx(1, "illegal timeout value"); 11629680Sgibbs break; 11729680Sgibbs case 'p': 11829805Sgibbs usemine = 1; 11929680Sgibbs if (!(pw = getpwuid(getuid()))) 12029680Sgibbs errx(1, "unknown uid %d", getuid()); 12129680Sgibbs mypw = strdup(pw->pw_passwd); 12244510Swollman break; 12344510Swollman case 'n': 12444510Swollman no_timeout = 1; 12544510Swollman break; 12644510Swollman case 'v': 12744510Swollman vtylock = 1; 12850673Sjlemon break; 12944510Swollman case '?': 13029680Sgibbs default: 13129680Sgibbs usage(); 13229680Sgibbs } 13329680Sgibbs timeout.tv_sec = sectimeout * 60; 13429680Sgibbs 13529680Sgibbs setuid(getuid()); /* discard privs */ 13629680Sgibbs 1371541Srgrimes if (ioctl(0, TIOCGETP, &tty)) /* get information for header */ 13829680Sgibbs exit(1); 1391541Srgrimes gethostname(hostname, sizeof(hostname)); 1401541Srgrimes if (!(ttynam = ttyname(0))) 1411541Srgrimes errx(1, "not a terminal?"); 1421541Srgrimes if (gettimeofday(&timval, (struct timezone *)NULL)) 1431541Srgrimes err(1, "gettimeofday"); 1441541Srgrimes nexttime = timval.tv_sec + (sectimeout * 60); 1451541Srgrimes timval_sec = timval.tv_sec; 1461541Srgrimes timp = localtime(&timval_sec); 1471541Srgrimes ap = asctime(timp); 1481541Srgrimes tzn = timp->tm_zone; 14929680Sgibbs 15029680Sgibbs (void)signal(SIGINT, quit); 15129680Sgibbs (void)signal(SIGQUIT, quit); 1521541Srgrimes ntty = tty; ntty.sg_flags &= ~ECHO; 15329680Sgibbs (void)ioctl(0, TIOCSETP, &ntty); 15429680Sgibbs 15529680Sgibbs if (!mypw) { 15629680Sgibbs /* get key and check again */ 1571541Srgrimes (void)printf("Key: "); 15829680Sgibbs if (!fgets(s, sizeof(s), stdin) || *s == '\n') 15929680Sgibbs quit(0); 16033824Sbde (void)printf("\nAgain: "); 1611541Srgrimes /* 16229680Sgibbs * Don't need EOF test here, if we get EOF, then s1 != s 1631541Srgrimes * and the right things will happen. 16429680Sgibbs */ 16529680Sgibbs (void)fgets(s1, sizeof(s1), stdin); 16629680Sgibbs (void)putchar('\n'); 1671541Srgrimes if (strcmp(s1, s)) { 1681541Srgrimes (void)printf("\07lock: passwords didn't match.\n"); 1691541Srgrimes ioctl(0, TIOCSETP, &tty); 1701541Srgrimes exit(1); 17129680Sgibbs } 17229680Sgibbs s[0] = '\0'; 17329680Sgibbs mypw = s1; 1741541Srgrimes } 17529680Sgibbs 17644510Swollman /* set signal handlers */ 17744510Swollman (void)signal(SIGINT, hi); 1781541Srgrimes (void)signal(SIGQUIT, hi); 17944510Swollman (void)signal(SIGTSTP, hi); 1801541Srgrimes (void)signal(SIGALRM, bye); 18129680Sgibbs 1821541Srgrimes ntimer.it_interval = zerotime; 1831541Srgrimes ntimer.it_value = timeout; 1841541Srgrimes if (!no_timeout) 18529680Sgibbs setitimer(ITIMER_REAL, &ntimer, &otimer); 18633824Sbde if (vtylock) { 1871541Srgrimes /* 18829680Sgibbs * If this failed, we want to err out; warn isn't good 1891541Srgrimes * enough, since we don't want the user to think that 1901541Srgrimes * everything is nice and locked because they got a 1911541Srgrimes * "Key:" prompt. 19229680Sgibbs */ 19329680Sgibbs if (ioctl(0, VT_LOCKSWITCH, &vtylock) == -1) { 19429680Sgibbs (void)ioctl(0, TIOCSETP, &tty); 19529680Sgibbs err(1, "locking vty"); 19629680Sgibbs } 19729680Sgibbs vtyunlock = 0x2; 19829680Sgibbs } 19929680Sgibbs 2001541Srgrimes /* header info */ 20144510Swollman (void)printf("lock: %s on %s.", ttynam, hostname); 20244510Swollman if (no_timeout) 2031541Srgrimes (void)printf(" no timeout."); 2041541Srgrimes else 2051541Srgrimes (void)printf(" timeout in %d minute%s.", sectimeout, 20624101Sbde sectimeout != 1 ? "s" : ""); 20729680Sgibbs if (vtylock) 20829680Sgibbs (void)printf(" vty locked."); 20929680Sgibbs (void)printf("\ntime now is %.20s%s%s", ap, tzn, ap + 19); 21029680Sgibbs 21129680Sgibbs failures = 0; 21244510Swollman 21344510Swollman for (;;) { 21444510Swollman (void)printf("Key: "); 21544510Swollman if (!fgets(s, sizeof(s), stdin)) { 21644510Swollman clearerr(stdin); 21744510Swollman hi(0); 21844510Swollman continue; 21944510Swollman } 22050673Sjlemon if (usemine) { 22144510Swollman s[strlen(s) - 1] = '\0'; 22250673Sjlemon if (!strcmp(mypw, crypt(s, mypw))) 22350673Sjlemon break; 22450673Sjlemon } 22544510Swollman else if (!strcmp(s, s1)) 22644510Swollman break; 22744510Swollman (void)printf("\07\n"); 22844510Swollman failures++; 22944510Swollman if (getuid() == 0) 23044510Swollman syslog(LOG_NOTICE, "%d ROOT UNLOCK FAILURE%s (%s on %s)", 23144510Swollman failures, failures > 1 ? "S": "", ttynam, hostname); 23244510Swollman if (ioctl(0, TIOCGETP, &ntty)) 23344510Swollman exit(1); 23444510Swollman sleep(1); /* to discourage guessing */ 23544510Swollman } 23644510Swollman if (getuid() == 0) 23744510Swollman syslog(LOG_NOTICE, "ROOT UNLOCK ON hostname %s port %s", 23844510Swollman hostname, ttynam); 23944510Swollman quit(0); 24044510Swollman return(0); /* not reached */ 24144510Swollman} 24250673Sjlemon 24344510Swollman 24444510Swollmanstatic void 24544510Swollmanusage() 24644510Swollman{ 24744510Swollman (void)fprintf(stderr, "usage: lock [-npv] [-t timeout]\n"); 24850673Sjlemon exit(1); 24944510Swollman} 25044510Swollman 25144510Swollmanvoid 25244510Swollmanhi(int signo __unused) 25344510Swollman{ 25444510Swollman struct timeval timval; 25544510Swollman 25644510Swollman if (!gettimeofday(&timval, (struct timezone *)NULL)) { 25744510Swollman (void)printf("lock: type in the unlock key. "); 25844510Swollman if (no_timeout) { 25944510Swollman (void)putchar('\n'); 26044510Swollman } else { 26144510Swollman (void)printf("timeout in %ld:%ld minutes\n", 26244510Swollman (nexttime - timval.tv_sec) / 60, 26344510Swollman (nexttime - timval.tv_sec) % 60); 26444510Swollman } 26544510Swollman } 26644510Swollman} 26744510Swollman 26850673Sjlemonvoid 26944510Swollmanquit(int signo __unused) 27044510Swollman{ 27144510Swollman (void)putchar('\n'); 27250673Sjlemon (void)ioctl(0, TIOCSETP, &tty); 27344510Swollman if (vtyunlock) 27444510Swollman (void)ioctl(0, VT_LOCKSWITCH, &vtyunlock); 27544510Swollman exit(0); 27644510Swollman} 27744510Swollman 27844510Swollmanvoid 27944510Swollmanbye(int signo __unused) 28044510Swollman{ 28144510Swollman if (!no_timeout) { 28244510Swollman (void)ioctl(0, TIOCSETP, &tty); 28344510Swollman if (vtyunlock) 28444510Swollman (void)ioctl(0, VT_LOCKSWITCH, &vtyunlock); 28544510Swollman (void)printf("lock: timeout\n"); 28644510Swollman exit(1); 28744510Swollman } 28844510Swollman} 28944510Swollman