Annotation of src/usr.bin/lock/lock.c, Revision 1.9
1.9 ! millert 1: /* $OpenBSD: lock.c,v 1.8 1997/01/15 23:42:45 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.9 ! millert 50: static char rcsid[] = "$OpenBSD: lock.c,v 1.8 1997/01/15 23:42:45 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.9 ! millert 81: int skey_auth __P((char *));
! 82: void quit __P((int));
! 83: void bye __P((int));
! 84: void hi __P((int));
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.6 downsj 130: fprintf(stderr, "usage: lock [-n] [-p] [-t timeout]\n");
1.1 deraadt 131: exit(1);
132: }
133: timeout.tv_sec = sectimeout * 60;
134:
1.7 millert 135: seteuid(getuid()); /* discard what privs we can */
1.1 deraadt 136:
137: if (tcgetattr(0, &tty) < 0) /* get information for header */
138: exit(1);
139: gethostname(hostname, sizeof(hostname));
140: if (!(ttynam = ttyname(0)))
141: errx(1, "not a terminal?");
142: if (gettimeofday(&timval, (struct timezone *)NULL))
143: err(1, "gettimeofday");
144: curtime = timval.tv_sec;
145: nexttime = timval.tv_sec + (sectimeout * 60);
146: timp = localtime(&curtime);
147: ap = asctime(timp);
148: tzn = timp->tm_zone;
149:
150: (void)signal(SIGINT, quit);
151: (void)signal(SIGQUIT, quit);
152: ntty = tty; ntty.c_lflag &= ~ECHO;
153: (void)tcsetattr(0, TCSADRAIN, &ntty);
154:
155: if (!mypw) {
156: /* get key and check again */
1.4 deraadt 157: printf("Key: ");
1.1 deraadt 158: if (!fgets(s, sizeof(s), stdin) || *s == '\n')
1.9 ! millert 159: quit(0);
1.4 deraadt 160: printf("\nAgain: ");
1.1 deraadt 161: /*
162: * Don't need EOF test here, if we get EOF, then s1 != s
163: * and the right things will happen.
164: */
165: (void)fgets(s1, sizeof(s1), stdin);
166: (void)putchar('\n');
167: if (strcmp(s1, s)) {
1.7 millert 168: (void)puts("\alock: passwords didn't match.");
1.1 deraadt 169: (void)tcsetattr(0, TCSADRAIN, &tty);
170: exit(1);
171: }
1.5 deraadt 172: s[0] = '\0';
1.1 deraadt 173: mypw = s1;
174: }
175:
176: /* set signal handlers */
177: (void)signal(SIGINT, hi);
178: (void)signal(SIGQUIT, hi);
179: (void)signal(SIGTSTP, hi);
180: (void)signal(SIGALRM, bye);
181:
182: ntimer.it_interval = zerotime;
183: ntimer.it_value = timeout;
1.6 downsj 184: if (!no_timeout)
185: setitimer(ITIMER_REAL, &ntimer, &otimer);
1.1 deraadt 186:
187: /* header info */
1.6 downsj 188: if (no_timeout) {
189: printf("lock: %s on %s. no timeout\ntime now is %.20s%s%s",
190: ttynam, hostname, ap, tzn, ap + 19);
191: } else {
192: printf("lock: %s on %s. timeout in %d minutes\ntime now is %.20s%s%s",
193: ttynam, hostname, sectimeout, ap, tzn, ap + 19);
194: }
1.1 deraadt 195:
196: for (;;) {
1.4 deraadt 197: printf("Key: ");
1.1 deraadt 198: if (!fgets(s, sizeof(s), stdin)) {
199: clearerr(stdin);
1.9 ! millert 200: hi(0);
1.1 deraadt 201: continue;
202: }
203: if (usemine) {
204: s[strlen(s) - 1] = '\0';
205: #ifdef SKEY
206: if (strcasecmp(s, "s/key") == 0) {
1.7 millert 207: /* S/Key lookup needs to be done as root */
208: seteuid(0);
209: ch = skey_auth(pw->pw_name);
210: seteuid(getuid());
211: if (ch)
1.1 deraadt 212: break;
213: }
214: #endif
215: if (!strcmp(mypw, crypt(s, mypw)))
216: break;
217: }
218: else if (!strcmp(s, s1))
219: break;
1.4 deraadt 220: printf("\a\n");
1.1 deraadt 221: if (tcsetattr(0, TCSADRAIN, &ntty) < 0)
222: exit(1);
223: }
1.9 ! millert 224:
! 225: quit(0);
! 226: exit(0); /*NOTREACHED*/
1.1 deraadt 227: }
228:
229: #ifdef SKEY
230: /*
231: * We can't use libskey's skey_authenticate() since it
232: * handles signals in a way that's inappropriate
233: * for our needs. Instead we roll our own.
234: */
235: int
1.5 deraadt 236: skey_auth(user)
237: char *user;
1.1 deraadt 238: {
1.7 millert 239: char s[256], *ask;
1.1 deraadt 240: int ret = 0;
241:
242: if (!skey_haskey(user) && (ask = skey_keyinfo(user))) {
1.7 millert 243: printf("\n%s\nResponse: ", ask);
1.1 deraadt 244: if (!fgets(s, sizeof(s), stdin) || *s == '\n')
245: clearerr(stdin);
246: else {
247: s[strlen(s) - 1] = '\0';
248: if (skey_passcheck(user, s) != -1)
249: ret = 1;
250: }
251: } else
252: printf("Sorry, you have no s/key.\n");
253: return ret;
254: }
255: #endif
256:
257: void
1.9 ! millert 258: hi(dummy)
! 259: int dummy;
1.1 deraadt 260: {
261: struct timeval timval;
262:
1.6 downsj 263: if (!gettimeofday(&timval, (struct timezone *)NULL)) {
264: (void)printf("lock: type in the unlock key. ");
265: if (no_timeout) {
266: putchar('\n');
267: } else {
268: printf("timeout in %ld:%ld minutes\n",
269: (nexttime - timval.tv_sec) / 60,
270: (nexttime - timval.tv_sec) % 60);
271: }
272: }
1.1 deraadt 273: }
274:
275: void
1.9 ! millert 276: quit(dummy)
! 277: int dummy;
1.1 deraadt 278: {
1.4 deraadt 279: putchar('\n');
1.1 deraadt 280: (void)tcsetattr(0, TCSADRAIN, &tty);
281: exit(0);
282: }
283:
284: void
1.9 ! millert 285: bye(dummy)
! 286: int dummy;
1.1 deraadt 287: {
1.6 downsj 288: if (!no_timeout) {
289: (void)tcsetattr(0, TCSADRAIN, &tty);
290: printf("lock: timeout\n");
291: exit(1);
292: }
1.1 deraadt 293: }