1 /** $MirOS: src/usr.bin/lock/lock.c,v 1.5 2005/12/17 00:23:31 tg Exp $ */
2 /* $OpenBSD: lock.c,v 1.21 2005/07/14 14:42:28 jmc Exp $ */
3 /* $NetBSD: lock.c,v 1.8 1996/05/07 18:32:31 jtc Exp $ */
4
5 /*
6 * Copyright (c) 1980, 1987, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Bob Toxen.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #ifndef lint
38 static char copyright[] =
39 "@(#) Copyright (c) 1980, 1987, 1993\n\
40 The Regents of the University of California. All rights reserved.\n";
41 #endif /* not lint */
42
43 /*
44 * Lock a terminal up until the given key is entered, until the root
45 * password is entered, or the given interval times out.
46 *
47 * Timeout interval is by default TIMEOUT, it can be changed with
48 * an argument of the form -time where time is in minutes
49 */
50
51 #include <sys/param.h>
52 #include <sys/stat.h>
53 #include <sys/time.h>
54 #include <signal.h>
55
56 #include <ctype.h>
57 #include <err.h>
58 #include <pwd.h>
59 #include <readpassphrase.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <termios.h>
64 #include <unistd.h>
65
66 #include <login_cap.h>
67 #include <bsd_auth.h>
68
69 __SCCSID("@(#)lock.c 8.1 (Berkeley) 6/6/93");
70 __RCSID("$MirOS: src/usr.bin/lock/lock.c,v 1.5 2005/12/17 00:23:31 tg Exp $");
71
72 #define TIMEOUT 15
73
74 void bye(int);
75 void hi(int);
76
77 struct timeval timeout;
78 struct timeval zerotime;
79 time_t nexttime; /* keep the timeout time */
80 int no_timeout; /* lock terminal forever */
81
82 extern char *__progname;
83
84 /*ARGSUSED*/
85 int
main(int argc,char * argv[])86 main(int argc, char *argv[])
87 {
88 char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ], date[256];
89 char *p, *style, *nstyle, *ttynam;
90 struct itimerval ntimer, otimer;
91 int ch, sectimeout, usemine;
92 struct passwd *pw;
93 struct tm *timp;
94 time_t curtime;
95 login_cap_t *lc;
96
97 sectimeout = TIMEOUT;
98 style = NULL;
99 usemine = 0;
100 no_timeout = 0;
101
102 if ((p = strrchr(argv[0], '/')) != NULL)
103 ++p;
104 else
105 p = argv[0];
106
107 if (!strcmp(p, "lock-np") || !strcmp(p, "SCREEN-LOCK")) {
108 no_timeout = 1;
109 usemine = 1;
110 }
111
112 if (!(pw = getpwuid(getuid())))
113 errx(1, "unknown uid %u.", getuid());
114
115 lc = login_getclass(pw->pw_class);
116
117 while ((ch = getopt(argc, argv, "a:npt:")) != -1)
118 switch (ch) {
119 case 'a':
120 if (lc) {
121 style = login_getstyle(lc, optarg, "auth-lock");
122 if (style == NULL)
123 errx(1,
124 "invalid authentication style: %s",
125 optarg);
126 }
127 usemine = 1;
128 break;
129 case 't':
130 if ((sectimeout = atoi(optarg)) <= 0)
131 errx(1, "illegal timeout value: %s", optarg);
132 break;
133 case 'p':
134 usemine = 1;
135 break;
136 case 'n':
137 no_timeout = 1;
138 break;
139 case '?':
140 default:
141 (void)fprintf(stderr,
142 "usage: %s [-np] [-a style] [-t timeout]\n",
143 __progname);
144 exit(1);
145 }
146 timeout.tv_sec = sectimeout * 60;
147
148 gethostname(hostname, sizeof(hostname));
149 if (!(ttynam = ttyname(STDIN_FILENO)))
150 errx(1, "not a terminal?");
151 curtime = time(NULL);
152 nexttime = curtime + (sectimeout * 60);
153 timp = localtime(&curtime);
154 strftime(date, sizeof(date), "%+", timp);
155
156 if (!usemine) {
157 /* get key and check again */
158 if (!readpassphrase("Key: ", s, sizeof(s), RPP_ECHO_OFF) ||
159 *s == '\0')
160 exit(0);
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)readpassphrase("Again: ", s1, sizeof(s1), RPP_ECHO_OFF);
166 if (strcmp(s1, s)) {
167 warnx("\apasswords didn't match.");
168 exit(1);
169 }
170 s[0] = '\0';
171 }
172
173 /* set signal handlers */
174 (void)signal(SIGINT, hi);
175 (void)signal(SIGQUIT, hi);
176 (void)signal(SIGTSTP, hi);
177 (void)signal(SIGALRM, bye);
178
179 ntimer.it_interval = zerotime;
180 ntimer.it_value = timeout;
181 if (!no_timeout)
182 setitimer(ITIMER_REAL, &ntimer, &otimer);
183
184 /* header info */
185 if (no_timeout) {
186 (void)fprintf(stderr,
187 "%s: %s on %s. no timeout\ntime now is %s\n",
188 __progname, ttynam, hostname, date);
189 } else {
190 (void)fprintf(stderr,
191 "%s: %s on %s. timeout in %d minutes\ntime now is %s\n",
192 __progname, ttynam, hostname, sectimeout, date);
193 }
194
195 for (;;) {
196 if (!readpassphrase("Key: ", s, sizeof(s), RPP_ECHO_OFF) ||
197 *s == '\0') {
198 hi(0);
199 continue;
200 }
201 if (usemine) {
202 /*
203 * If user entered 's/key' or the style specified via
204 * the '-a' argument, auth_userokay() will prompt
205 * for a new password. Otherwise, use what we have.
206 */
207 if ((strcmp(s, "s/key") == 0 &&
208 (nstyle = login_getstyle(lc, "skey", "auth-lock")))
209 || ((nstyle = style) && strcmp(s, nstyle) == 0))
210 p = NULL;
211 else
212 p = s;
213 if (auth_userokay(pw->pw_name, nstyle, "auth-lock", p))
214 break;
215 } else if (strcmp(s, s1) == 0)
216 break;
217 (void)putc('\a', stderr);
218 }
219
220 exit(0);
221 }
222
223 void
hi(int dummy)224 hi(int dummy)
225 {
226 char buf[1024], buf2[1024];
227 time_t now;
228
229 if (no_timeout)
230 buf2[0] = '\0';
231 else {
232 now = time(NULL);
233 (void)snprintf(buf2, sizeof buf2, " timeout in %d:%d minutes",
234 (int)((nexttime - now) / 60), (int)((nexttime - now) % 60));
235 }
236 snprintf(buf, sizeof buf, "%s: type in the unlock key.%s\n",
237 __progname, buf2);
238 (void) write(STDERR_FILENO, buf, strlen(buf));
239 }
240
241 void
bye(int dummy)242 bye(int dummy)
243 {
244
245 if (!no_timeout)
246 warnx("timeout");
247 _exit(1);
248 }
249