1 /* $OpenBSD: lock.c,v 1.13 2001/05/29 21:38:15 millert Exp $ */ 2 /* $NetBSD: lock.c,v 1.8 1996/05/07 18:32:31 jtc Exp $ */ 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 50 static char rcsid[] = "$OpenBSD: lock.c,v 1.13 2001/05/29 21:38:15 millert Exp $"; 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 <readpassphrase.h> 70 #include <stdio.h> 71 #include <stdlib.h> 72 #include <string.h> 73 #include <termios.h> 74 #include <unistd.h> 75 76 #include <login_cap.h> 77 #include <bsd_auth.h> 78 79 #define TIMEOUT 15 80 81 void bye __P((int)); 82 void hi __P((int)); 83 84 struct timeval timeout; 85 struct timeval zerotime; 86 time_t nexttime; /* keep the timeout time */ 87 int no_timeout; /* lock terminal forever */ 88 89 extern char *__progname; 90 91 /*ARGSUSED*/ 92 int 93 main(argc, argv) 94 int argc; 95 char **argv; 96 { 97 struct passwd *pw; 98 struct itimerval ntimer, otimer; 99 struct tm *timp; 100 time_t curtime; 101 int ch, sectimeout, usemine; 102 char *p, *style, *nstyle, *ttynam; 103 char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ], date[256]; 104 login_cap_t *lc; 105 106 sectimeout = TIMEOUT; 107 style = NULL; 108 usemine = 0; 109 no_timeout = 0; 110 111 if (!(pw = getpwuid(getuid()))) 112 errx(1, "unknown uid %d.", getuid()); 113 114 lc = login_getclass(pw->pw_class); 115 116 while ((ch = getopt(argc, argv, "a:npt:")) != -1) 117 switch(ch) { 118 case 'a': 119 if (lc) { 120 style = login_getstyle(lc, optarg, "auth-lock"); 121 if (style == NULL) 122 errx(1, 123 "invalid authentication style: %s", 124 optarg); 125 } 126 usemine = 1; 127 break; 128 case 't': 129 if ((sectimeout = atoi(optarg)) <= 0) 130 errx(1, "illegal timeout value: %s", optarg); 131 break; 132 case 'p': 133 usemine = 1; 134 break; 135 case 'n': 136 no_timeout = 1; 137 break; 138 case '?': 139 default: 140 (void)fprintf(stderr, 141 "usage: %s [-n] [-p] [-a style] [-t timeout]\n", 142 __progname); 143 exit(1); 144 } 145 timeout.tv_sec = sectimeout * 60; 146 147 gethostname(hostname, sizeof(hostname)); 148 if (!(ttynam = ttyname(STDIN_FILENO))) 149 errx(1, "not a terminal?"); 150 curtime = time(NULL); 151 nexttime = curtime + (sectimeout * 60); 152 timp = localtime(&curtime); 153 strftime(date, sizeof(date), "%c", timp); 154 155 if (!usemine) { 156 /* get key and check again */ 157 if (!readpassphrase("Key: ", s, sizeof(s), RPP_ECHO_OFF) || 158 *s == '\0') 159 exit(0); 160 /* 161 * Don't need EOF test here, if we get EOF, then s1 != s 162 * and the right things will happen. 163 */ 164 (void)readpassphrase("Again: ", s1, sizeof(s1), RPP_ECHO_OFF); 165 if (strcmp(s1, s)) { 166 warnx("\apasswords didn't match."); 167 exit(1); 168 } 169 s[0] = '\0'; 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; 180 if (!no_timeout) 181 setitimer(ITIMER_REAL, &ntimer, &otimer); 182 183 /* header info */ 184 if (no_timeout) { 185 (void)fprintf(stderr, 186 "%s: %s on %s. no timeout\ntime now is %s\n", 187 __progname, ttynam, hostname, date); 188 } else { 189 (void)fprintf(stderr, 190 "%s: %s on %s. timeout in %d minutes\ntime now is %s\n", 191 __progname, ttynam, hostname, sectimeout, date); 192 } 193 194 for (;;) { 195 if (!readpassphrase("Key: ", s, sizeof(s), RPP_ECHO_OFF) || 196 *s == '\0') { 197 hi(0); 198 continue; 199 } 200 if (usemine) { 201 /* 202 * If user entered 's/key' or the style specified via 203 * the '-a' argument, auth_userokay() will prompt 204 * for a new password. Otherwise, use what we have. 205 */ 206 if ((strcmp(s, "s/key") == 0 && 207 (nstyle = login_getstyle(lc, "skey", "auth-lock"))) 208 || ((nstyle = style) && strcmp(s, nstyle) == 0)) 209 p = NULL; 210 else 211 p = s; 212 if (auth_userokay(pw->pw_name, nstyle, "auth-lock", p)) 213 break; 214 } else if (strcmp(s, s1) == 0) 215 break; 216 (void)putc('\a', stderr); 217 } 218 219 exit(0); 220 } 221 222 void 223 hi(dummy) 224 int dummy; 225 { 226 time_t now; 227 228 (void)fprintf(stderr, "%s: type in the unlock key.", __progname); 229 if (!no_timeout) { 230 now = time(NULL); 231 (void)fprintf(stderr, " timeout in %d:%d minutes", 232 (nexttime - now) / 60, 233 (nexttime - now) % 60); 234 } 235 putc('\n', stderr); 236 } 237 238 void 239 bye(dummy) 240 int dummy; 241 { 242 243 if (!no_timeout) 244 errx(1, "timeout"); 245 } 246