Annotation of src/usr.bin/sudo/tgetpass.c, Revision 1.11
1.1 millert 1: /*
1.11 ! millert 2: * Copyright (c) 1996, 1998-2005 Todd C. Miller <Todd.Miller@courtesan.com>
1.1 millert 3: *
1.10 millert 4: * Permission to use, copy, modify, and distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.9 millert 15: *
16: * Sponsored in part by the Defense Advanced Research Projects
17: * Agency (DARPA) and Air Force Research Laboratory, Air Force
18: * Materiel Command, USAF, under agreement number F39502-99-1-0512.
1.1 millert 19: */
20:
1.10 millert 21: #ifdef __TANDEM
22: # include <floss.h>
23: #endif
24:
1.11 ! millert 25: #include <config.h>
1.1 millert 26:
1.7 millert 27: #include <sys/types.h>
28: #include <sys/param.h>
29: #ifdef HAVE_SYS_BSDTYPES_H
30: # include <sys/bsdtypes.h>
31: #endif /* HAVE_SYS_BSDTYPES_H */
32: #include <sys/time.h>
1.1 millert 33: #include <stdio.h>
34: #ifdef STDC_HEADERS
1.7 millert 35: # include <stdlib.h>
36: # include <stddef.h>
37: #else
38: # ifdef HAVE_STDLIB_H
39: # include <stdlib.h>
40: # endif
1.1 millert 41: #endif /* STDC_HEADERS */
1.7 millert 42: #ifdef HAVE_STRING_H
43: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
44: # include <memory.h>
45: # endif
46: # include <string.h>
47: #else
48: # ifdef HAVE_STRINGS_H
49: # include <strings.h>
50: # endif
51: #endif /* HAVE_STRING_H */
1.1 millert 52: #ifdef HAVE_UNISTD_H
1.7 millert 53: # include <unistd.h>
1.1 millert 54: #endif /* HAVE_UNISTD_H */
55: #include <pwd.h>
56: #include <errno.h>
57: #include <signal.h>
58: #include <fcntl.h>
59: #ifdef HAVE_TERMIOS_H
1.7 millert 60: # include <termios.h>
1.1 millert 61: #else
1.7 millert 62: # ifdef HAVE_TERMIO_H
63: # include <termio.h>
64: # else
65: # include <sgtty.h>
66: # include <sys/ioctl.h>
67: # endif /* HAVE_TERMIO_H */
1.1 millert 68: #endif /* HAVE_TERMIOS_H */
69:
70: #include "sudo.h"
71:
1.5 millert 72: #ifndef lint
1.11 ! millert 73: __unused static const char rcsid[] = "$Sudo: tgetpass.c,v 1.111.2.2 2007/06/12 01:26:35 millert Exp $";
1.5 millert 74: #endif /* lint */
75:
1.1 millert 76: #ifndef TCSASOFT
1.7 millert 77: # define TCSASOFT 0
78: #endif
79: #ifndef ECHONL
80: # define ECHONL 0
81: #endif
82:
83: #ifndef _POSIX_VDISABLE
84: # ifdef VDISABLE
85: # define _POSIX_VDISABLE VDISABLE
86: # else
87: # define _POSIX_VDISABLE 0
88: # endif
89: #endif
1.1 millert 90:
1.5 millert 91: /*
92: * Abstract method of getting at the term flags.
93: */
94: #undef TERM
95: #undef tflags
96: #ifdef HAVE_TERMIOS_H
97: # define TERM termios
98: # define tflags c_lflag
99: # define term_getattr(f, t) tcgetattr(f, t)
1.11 ! millert 100: # define term_setattr(f, t) tcsetattr(f, TCSADRAIN|TCSASOFT, t)
1.5 millert 101: #else
102: # ifdef HAVE_TERMIO_H
103: # define TERM termio
104: # define tflags c_lflag
105: # define term_getattr(f, t) ioctl(f, TCGETA, t)
1.7 millert 106: # define term_setattr(f, t) ioctl(f, TCSETAF, t)
1.5 millert 107: # else
108: # define TERM sgttyb
109: # define tflags sg_flags
110: # define term_getattr(f, t) ioctl(f, TIOCGETP, t)
111: # define term_setattr(f, t) ioctl(f, TIOCSETP, t)
112: # endif /* HAVE_TERMIO_H */
113: #endif /* HAVE_TERMIOS_H */
1.1 millert 114:
1.7 millert 115: static volatile sig_atomic_t signo;
116:
117: static void handler __P((int));
1.10 millert 118: static char *getln __P((int, char *, size_t));
1.1 millert 119:
120: /*
121: * Like getpass(3) but with timeout and echo flags.
122: */
123: char *
1.5 millert 124: tgetpass(prompt, timeout, flags)
1.1 millert 125: const char *prompt;
126: int timeout;
1.5 millert 127: int flags;
1.1 millert 128: {
1.10 millert 129: sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
1.7 millert 130: sigaction_t savetstp, savettin, savettou;
1.10 millert 131: struct TERM term, oterm;
132: char *pass;
1.7 millert 133: static char buf[SUDO_PASS_MAX + 1];
134: int input, output, save_errno;
1.1 millert 135:
1.10 millert 136: (void) fflush(stdout);
1.7 millert 137: restart:
1.1 millert 138: /* Open /dev/tty for reading/writing if possible else use stdin/stderr. */
1.10 millert 139: if (ISSET(flags, TGP_STDIN) ||
1.5 millert 140: (input = output = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) {
1.1 millert 141: input = STDIN_FILENO;
142: output = STDERR_FILENO;
143: }
144:
1.7 millert 145: /*
146: * Catch signals that would otherwise cause the user to end
1.10 millert 147: * up with echo turned off in the shell.
1.7 millert 148: */
149: sigemptyset(&sa.sa_mask);
1.10 millert 150: sa.sa_flags = SA_INTERRUPT; /* don't restart system calls */
1.7 millert 151: sa.sa_handler = handler;
1.10 millert 152: (void) sigaction(SIGALRM, &sa, &savealrm);
1.7 millert 153: (void) sigaction(SIGINT, &sa, &saveint);
154: (void) sigaction(SIGHUP, &sa, &savehup);
155: (void) sigaction(SIGQUIT, &sa, &savequit);
156: (void) sigaction(SIGTERM, &sa, &saveterm);
157: (void) sigaction(SIGTSTP, &sa, &savetstp);
158: (void) sigaction(SIGTTIN, &sa, &savettin);
159: (void) sigaction(SIGTTOU, &sa, &savettou);
160:
1.5 millert 161: /* Turn echo off/on as specified by flags. */
1.7 millert 162: if (term_getattr(input, &oterm) == 0) {
163: (void) memcpy(&term, &oterm, sizeof(term));
1.10 millert 164: if (!ISSET(flags, TGP_ECHO))
165: CLR(term.tflags, (ECHO | ECHONL));
1.7 millert 166: #ifdef VSTATUS
167: term.c_cc[VSTATUS] = _POSIX_VDISABLE;
168: #endif
169: (void) term_setattr(input, &term);
170: } else {
171: memset(&term, 0, sizeof(term));
172: memset(&oterm, 0, sizeof(oterm));
173: }
1.8 millert 174:
175: if (prompt)
176: (void) write(output, prompt, strlen(prompt));
1.1 millert 177:
1.10 millert 178: if (timeout > 0)
179: alarm(timeout);
180: pass = getln(input, buf, sizeof(buf));
181: alarm(0);
1.7 millert 182: save_errno = errno;
1.1 millert 183:
1.10 millert 184: if (!ISSET(term.tflags, ECHO))
1.1 millert 185: (void) write(output, "\n", 1);
186:
1.7 millert 187: /* Restore old tty settings and signals. */
188: if (memcmp(&term, &oterm, sizeof(term)) != 0)
189: (void) term_setattr(input, &oterm);
1.10 millert 190: (void) sigaction(SIGALRM, &savealrm, NULL);
1.7 millert 191: (void) sigaction(SIGINT, &saveint, NULL);
192: (void) sigaction(SIGHUP, &savehup, NULL);
193: (void) sigaction(SIGQUIT, &savequit, NULL);
194: (void) sigaction(SIGTERM, &saveterm, NULL);
195: (void) sigaction(SIGTSTP, &savetstp, NULL);
196: (void) sigaction(SIGTTIN, &savettin, NULL);
197: (void) sigaction(SIGTTOU, &savettou, NULL);
1.1 millert 198: if (input != STDIN_FILENO)
199: (void) close(input);
200:
1.7 millert 201: /*
202: * If we were interrupted by a signal, resend it to ourselves
203: * now that we have restored the signal handlers.
204: */
205: if (signo) {
1.10 millert 206: kill(getpid(), signo);
1.7 millert 207: switch (signo) {
208: case SIGTSTP:
209: case SIGTTIN:
210: case SIGTTOU:
211: signo = 0;
212: goto restart;
213: }
214: }
215:
216: errno = save_errno;
217: return(pass);
1.1 millert 218: }
219:
220: static char *
1.10 millert 221: getln(fd, buf, bufsiz)
1.1 millert 222: int fd;
223: char *buf;
224: size_t bufsiz;
225: {
1.10 millert 226: char c, *cp;
227: ssize_t nr;
1.1 millert 228:
1.7 millert 229: if (bufsiz == 0) {
230: errno = EINVAL;
1.1 millert 231: return(NULL); /* sanity */
1.7 millert 232: }
1.1 millert 233:
1.2 millert 234: cp = buf;
1.10 millert 235: nr = -1;
236: while (--bufsiz && (nr = read(fd, &c, 1)) == 1 && c != '\n' && c != '\r')
237: *cp++ = c;
1.1 millert 238: *cp = '\0';
1.10 millert 239: return(nr == -1 ? NULL : buf);
1.7 millert 240: }
241:
1.10 millert 242: static void
243: handler(s)
1.7 millert 244: int s;
245: {
1.10 millert 246: if (s != SIGALRM)
247: signo = s;
1.1 millert 248: }