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