Annotation of src/usr.bin/lock/lock.c, Revision 1.8
1.8 ! millert 1: /* $OpenBSD: lock.c,v 1.7 1996/10/16 00:09:20 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.8 ! millert 50: static char rcsid[] = "$OpenBSD: lock.c,v 1.7 1996/10/16 00:09:20 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:
81: void quit(), bye(), hi();
82:
83: struct timeval timeout;
84: struct timeval zerotime;
85: struct termios tty, ntty;
86: long nexttime; /* keep the timeout time */
1.6 downsj 87: int no_timeout; /* lock terminal forever */
1.1 deraadt 88:
89: /*ARGSUSED*/
90: main(argc, argv)
91: int argc;
92: char **argv;
93: {
94: struct passwd *pw;
95: struct timeval timval;
96: struct itimerval ntimer, otimer;
97: struct tm *timp;
98: time_t curtime;
99: int ch, sectimeout, usemine;
100: char *ap, *mypw, *ttynam, *tzn;
101: char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ];
102:
103: sectimeout = TIMEOUT;
104: mypw = NULL;
105: usemine = 0;
1.6 downsj 106: no_timeout = 0;
1.1 deraadt 107:
108: if (!(pw = getpwuid(getuid())))
109: errx(1, "unknown uid %d.", getuid());
110:
1.8 ! millert 111: while ((ch = getopt(argc, argv, "npt:")) != -1)
1.1 deraadt 112: switch((char)ch) {
113: case 't':
114: if ((sectimeout = atoi(optarg)) <= 0)
115: errx(1, "illegal timeout value: %s", optarg);
116: break;
117: case 'p':
118: usemine = 1;
119: mypw = strdup(pw->pw_passwd);
120: break;
1.6 downsj 121: case 'n':
122: no_timeout = 1;
123: break;
1.1 deraadt 124: case '?':
125: default:
1.6 downsj 126: fprintf(stderr, "usage: lock [-n] [-p] [-t timeout]\n");
1.1 deraadt 127: exit(1);
128: }
129: timeout.tv_sec = sectimeout * 60;
130:
1.7 millert 131: seteuid(getuid()); /* discard what privs we can */
1.1 deraadt 132:
133: if (tcgetattr(0, &tty) < 0) /* get information for header */
134: exit(1);
135: gethostname(hostname, sizeof(hostname));
136: if (!(ttynam = ttyname(0)))
137: errx(1, "not a terminal?");
138: if (gettimeofday(&timval, (struct timezone *)NULL))
139: err(1, "gettimeofday");
140: curtime = timval.tv_sec;
141: nexttime = timval.tv_sec + (sectimeout * 60);
142: timp = localtime(&curtime);
143: ap = asctime(timp);
144: tzn = timp->tm_zone;
145:
146: (void)signal(SIGINT, quit);
147: (void)signal(SIGQUIT, quit);
148: ntty = tty; ntty.c_lflag &= ~ECHO;
149: (void)tcsetattr(0, TCSADRAIN, &ntty);
150:
151: if (!mypw) {
152: /* get key and check again */
1.4 deraadt 153: printf("Key: ");
1.1 deraadt 154: if (!fgets(s, sizeof(s), stdin) || *s == '\n')
155: quit();
1.4 deraadt 156: printf("\nAgain: ");
1.1 deraadt 157: /*
158: * Don't need EOF test here, if we get EOF, then s1 != s
159: * and the right things will happen.
160: */
161: (void)fgets(s1, sizeof(s1), stdin);
162: (void)putchar('\n');
163: if (strcmp(s1, s)) {
1.7 millert 164: (void)puts("\alock: passwords didn't match.");
1.1 deraadt 165: (void)tcsetattr(0, TCSADRAIN, &tty);
166: exit(1);
167: }
1.5 deraadt 168: s[0] = '\0';
1.1 deraadt 169: mypw = s1;
170: }
171:
172: /* set signal handlers */
173: (void)signal(SIGINT, hi);
174: (void)signal(SIGQUIT, hi);
175: (void)signal(SIGTSTP, hi);
176: (void)signal(SIGALRM, bye);
177:
178: ntimer.it_interval = zerotime;
179: ntimer.it_value = timeout;
1.6 downsj 180: if (!no_timeout)
181: setitimer(ITIMER_REAL, &ntimer, &otimer);
1.1 deraadt 182:
183: /* header info */
1.6 downsj 184: if (no_timeout) {
185: printf("lock: %s on %s. no timeout\ntime now is %.20s%s%s",
186: ttynam, hostname, ap, tzn, ap + 19);
187: } else {
188: printf("lock: %s on %s. timeout in %d minutes\ntime now is %.20s%s%s",
189: ttynam, hostname, sectimeout, ap, tzn, ap + 19);
190: }
1.1 deraadt 191:
192: for (;;) {
1.4 deraadt 193: printf("Key: ");
1.1 deraadt 194: if (!fgets(s, sizeof(s), stdin)) {
195: clearerr(stdin);
196: hi();
197: continue;
198: }
199: if (usemine) {
200: s[strlen(s) - 1] = '\0';
201: #ifdef SKEY
202: if (strcasecmp(s, "s/key") == 0) {
1.7 millert 203: /* S/Key lookup needs to be done as root */
204: seteuid(0);
205: ch = skey_auth(pw->pw_name);
206: seteuid(getuid());
207: if (ch)
1.1 deraadt 208: break;
209: }
210: #endif
211: if (!strcmp(mypw, crypt(s, mypw)))
212: break;
213: }
214: else if (!strcmp(s, s1))
215: break;
1.4 deraadt 216: printf("\a\n");
1.1 deraadt 217: if (tcsetattr(0, TCSADRAIN, &ntty) < 0)
218: exit(1);
219: }
220: quit();
221: }
222:
223: #ifdef SKEY
224: /*
225: * We can't use libskey's skey_authenticate() since it
226: * handles signals in a way that's inappropriate
227: * for our needs. Instead we roll our own.
228: */
229: int
1.5 deraadt 230: skey_auth(user)
231: char *user;
1.1 deraadt 232: {
1.7 millert 233: char s[256], *ask;
1.1 deraadt 234: int ret = 0;
235:
236: if (!skey_haskey(user) && (ask = skey_keyinfo(user))) {
1.7 millert 237: printf("\n%s\nResponse: ", ask);
1.1 deraadt 238: if (!fgets(s, sizeof(s), stdin) || *s == '\n')
239: clearerr(stdin);
240: else {
241: s[strlen(s) - 1] = '\0';
242: if (skey_passcheck(user, s) != -1)
243: ret = 1;
244: }
245: } else
246: printf("Sorry, you have no s/key.\n");
247: return ret;
248: }
249: #endif
250:
251: void
252: hi()
253: {
254: struct timeval timval;
255:
1.6 downsj 256: if (!gettimeofday(&timval, (struct timezone *)NULL)) {
257: (void)printf("lock: type in the unlock key. ");
258: if (no_timeout) {
259: putchar('\n');
260: } else {
261: printf("timeout in %ld:%ld minutes\n",
262: (nexttime - timval.tv_sec) / 60,
263: (nexttime - timval.tv_sec) % 60);
264: }
265: }
1.1 deraadt 266: }
267:
268: void
269: quit()
270: {
1.4 deraadt 271: putchar('\n');
1.1 deraadt 272: (void)tcsetattr(0, TCSADRAIN, &tty);
273: exit(0);
274: }
275:
276: void
277: bye()
278: {
1.6 downsj 279: if (!no_timeout) {
280: (void)tcsetattr(0, TCSADRAIN, &tty);
281: printf("lock: timeout\n");
282: exit(1);
283: }
1.1 deraadt 284: }