Annotation of src/usr.bin/lock/lock.c, Revision 1.10
1.10 ! millert 1: /* $OpenBSD: lock.c,v 1.9 1997/07/27 21:29:59 millert Exp $ */
1.2 deraadt 2: /* $NetBSD: lock.c,v 1.8 1996/05/07 18:32:31 jtc Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1980, 1987, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * Bob Toxen.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the University of
22: * California, Berkeley and its contributors.
23: * 4. Neither the name of the University nor the names of its contributors
24: * may be used to endorse or promote products derived from this software
25: * without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37: * SUCH DAMAGE.
38: */
39:
40: #ifndef lint
41: static char copyright[] =
42: "@(#) Copyright (c) 1980, 1987, 1993\n\
43: The Regents of the University of California. All rights reserved.\n";
44: #endif /* not lint */
45:
46: #ifndef lint
47: #if 0
48: static char sccsid[] = "@(#)lock.c 8.1 (Berkeley) 6/6/93";
49: #endif
1.10 ! millert 50: static char rcsid[] = "$OpenBSD: lock.c,v 1.9 1997/07/27 21:29:59 millert Exp $";
1.1 deraadt 51: #endif /* not lint */
52:
53: /*
54: * Lock a terminal up until the given key is entered, until the root
55: * password is entered, or the given interval times out.
56: *
57: * Timeout interval is by default TIMEOUT, it can be changed with
58: * an argument of the form -time where time is in minutes
59: */
60:
61: #include <sys/param.h>
62: #include <sys/stat.h>
63: #include <sys/time.h>
64: #include <signal.h>
65:
66: #include <ctype.h>
67: #include <err.h>
68: #include <pwd.h>
69: #include <stdio.h>
1.2 deraadt 70: #include <stdlib.h>
1.1 deraadt 71: #include <string.h>
72: #include <termios.h>
1.2 deraadt 73: #include <unistd.h>
1.1 deraadt 74:
1.7 millert 75: #ifdef SKEY
76: #include <skey.h>
77: #endif
78:
1.1 deraadt 79: #define TIMEOUT 15
80:
1.10 ! millert 81: void bye __P((int));
! 82: void hi __P((int));
! 83: void quit __P((int));
! 84: int skey_auth __P((char *));
1.1 deraadt 85:
86: struct timeval timeout;
87: struct timeval zerotime;
88: struct termios tty, ntty;
89: long nexttime; /* keep the timeout time */
1.9 millert 90: int no_timeout; /* lock terminal forever */
1.1 deraadt 91:
92: /*ARGSUSED*/
1.9 millert 93: int
1.1 deraadt 94: main(argc, argv)
95: int argc;
96: char **argv;
97: {
98: struct passwd *pw;
99: struct timeval timval;
100: struct itimerval ntimer, otimer;
101: struct tm *timp;
102: time_t curtime;
103: int ch, sectimeout, usemine;
104: char *ap, *mypw, *ttynam, *tzn;
105: char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ];
106:
107: sectimeout = TIMEOUT;
108: mypw = NULL;
109: usemine = 0;
1.6 downsj 110: no_timeout = 0;
1.1 deraadt 111:
112: if (!(pw = getpwuid(getuid())))
113: errx(1, "unknown uid %d.", getuid());
114:
1.8 millert 115: while ((ch = getopt(argc, argv, "npt:")) != -1)
1.1 deraadt 116: switch((char)ch) {
117: case 't':
118: if ((sectimeout = atoi(optarg)) <= 0)
119: errx(1, "illegal timeout value: %s", optarg);
120: break;
121: case 'p':
122: usemine = 1;
123: mypw = strdup(pw->pw_passwd);
124: break;
1.6 downsj 125: case 'n':
126: no_timeout = 1;
127: break;
1.1 deraadt 128: case '?':
129: default:
1.10 ! millert 130: (void)fprintf(stderr,
! 131: "usage: lock [-n] [-p] [-t timeout]\n");
1.1 deraadt 132: exit(1);
133: }
134: timeout.tv_sec = sectimeout * 60;
135:
1.7 millert 136: seteuid(getuid()); /* discard what privs we can */
1.1 deraadt 137:
138: if (tcgetattr(0, &tty) < 0) /* get information for header */
139: exit(1);
140: gethostname(hostname, sizeof(hostname));
141: if (!(ttynam = ttyname(0)))
142: errx(1, "not a terminal?");
143: if (gettimeofday(&timval, (struct timezone *)NULL))
144: err(1, "gettimeofday");
145: curtime = timval.tv_sec;
146: nexttime = timval.tv_sec + (sectimeout * 60);
147: timp = localtime(&curtime);
148: ap = asctime(timp);
149: tzn = timp->tm_zone;
150:
151: (void)signal(SIGINT, quit);
152: (void)signal(SIGQUIT, quit);
153: ntty = tty; ntty.c_lflag &= ~ECHO;
154: (void)tcsetattr(0, TCSADRAIN, &ntty);
155:
156: if (!mypw) {
157: /* get key and check again */
1.10 ! millert 158: (void)fputs("Key: ", stdout);
1.1 deraadt 159: if (!fgets(s, sizeof(s), stdin) || *s == '\n')
1.9 millert 160: quit(0);
1.10 ! millert 161: (void)fputs("\nAgain: ", stdout);
1.1 deraadt 162: /*
163: * Don't need EOF test here, if we get EOF, then s1 != s
164: * and the right things will happen.
165: */
166: (void)fgets(s1, sizeof(s1), stdin);
167: (void)putchar('\n');
168: if (strcmp(s1, s)) {
1.7 millert 169: (void)puts("\alock: passwords didn't match.");
1.1 deraadt 170: (void)tcsetattr(0, TCSADRAIN, &tty);
171: exit(1);
172: }
1.5 deraadt 173: s[0] = '\0';
1.1 deraadt 174: mypw = s1;
175: }
176:
177: /* set signal handlers */
178: (void)signal(SIGINT, hi);
179: (void)signal(SIGQUIT, hi);
180: (void)signal(SIGTSTP, hi);
181: (void)signal(SIGALRM, bye);
182:
183: ntimer.it_interval = zerotime;
184: ntimer.it_value = timeout;
1.6 downsj 185: if (!no_timeout)
186: setitimer(ITIMER_REAL, &ntimer, &otimer);
1.1 deraadt 187:
188: /* header info */
1.6 downsj 189: if (no_timeout) {
1.10 ! millert 190: (void)printf("lock: %s on %s. no timeout\ntime now is %.20s%s%s",
1.6 downsj 191: ttynam, hostname, ap, tzn, ap + 19);
192: } else {
1.10 ! millert 193: (void)printf("lock: %s on %s. timeout in %d minutes\ntime now is %.20s%s%s",
1.6 downsj 194: ttynam, hostname, sectimeout, ap, tzn, ap + 19);
195: }
1.1 deraadt 196:
197: for (;;) {
1.10 ! millert 198: (void)fputs("Key: ", stdout);
1.1 deraadt 199: if (!fgets(s, sizeof(s), stdin)) {
200: clearerr(stdin);
1.9 millert 201: hi(0);
1.1 deraadt 202: continue;
203: }
204: if (usemine) {
205: s[strlen(s) - 1] = '\0';
206: #ifdef SKEY
207: if (strcasecmp(s, "s/key") == 0) {
1.7 millert 208: /* S/Key lookup needs to be done as root */
209: seteuid(0);
210: ch = skey_auth(pw->pw_name);
211: seteuid(getuid());
212: if (ch)
1.1 deraadt 213: break;
214: }
215: #endif
216: if (!strcmp(mypw, crypt(s, mypw)))
217: break;
218: }
219: else if (!strcmp(s, s1))
220: break;
1.10 ! millert 221: (void)puts("\a");
1.1 deraadt 222: if (tcsetattr(0, TCSADRAIN, &ntty) < 0)
223: exit(1);
224: }
1.9 millert 225:
226: quit(0);
227: exit(0); /*NOTREACHED*/
1.1 deraadt 228: }
229:
230: #ifdef SKEY
231: /*
232: * We can't use libskey's skey_authenticate() since it
233: * handles signals in a way that's inappropriate
234: * for our needs. Instead we roll our own.
235: */
236: int
1.5 deraadt 237: skey_auth(user)
238: char *user;
1.1 deraadt 239: {
1.7 millert 240: char s[256], *ask;
1.1 deraadt 241: int ret = 0;
242:
243: if (!skey_haskey(user) && (ask = skey_keyinfo(user))) {
1.10 ! millert 244: (void)printf("\n%s\nResponse: ", ask);
1.1 deraadt 245: if (!fgets(s, sizeof(s), stdin) || *s == '\n')
246: clearerr(stdin);
247: else {
1.10 ! millert 248: rip(s);
1.1 deraadt 249: if (skey_passcheck(user, s) != -1)
250: ret = 1;
251: }
252: } else
1.10 ! millert 253: (void)printf("Sorry, you have no s/key.\n");
! 254: return(ret);
1.1 deraadt 255: }
256: #endif
257:
258: void
1.9 millert 259: hi(dummy)
260: int dummy;
1.1 deraadt 261: {
262: struct timeval timval;
263:
1.6 downsj 264: if (!gettimeofday(&timval, (struct timezone *)NULL)) {
265: (void)printf("lock: type in the unlock key. ");
266: if (no_timeout) {
267: putchar('\n');
268: } else {
1.10 ! millert 269: (void)printf("timeout in %ld:%ld minutes\n",
1.6 downsj 270: (nexttime - timval.tv_sec) / 60,
271: (nexttime - timval.tv_sec) % 60);
272: }
273: }
1.1 deraadt 274: }
275:
276: void
1.9 millert 277: quit(dummy)
278: int dummy;
1.1 deraadt 279: {
1.4 deraadt 280: putchar('\n');
1.1 deraadt 281: (void)tcsetattr(0, TCSADRAIN, &tty);
282: exit(0);
283: }
284:
285: void
1.9 millert 286: bye(dummy)
287: int dummy;
1.1 deraadt 288: {
1.6 downsj 289: if (!no_timeout) {
290: (void)tcsetattr(0, TCSADRAIN, &tty);
1.10 ! millert 291: (void)puts("lock: timeout");
1.6 downsj 292: exit(1);
293: }
1.1 deraadt 294: }