[BACK]Return to tgetpass.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Annotation of src/usr.bin/sudo/tgetpass.c, Revision 1.15

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.15    ! millert    73: __unused static const char rcsid[] = "$Sudo: tgetpass.c,v 1.111.2.7 2008/06/21 00:27:01 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
1.13      millert    89: #endif
                     90:
                     91: /*
                     92:  * Compat macros for non-termios systems.
                     93:  */
                     94: #ifndef HAVE_TERMIOS_H
1.5       millert    95: # ifdef HAVE_TERMIO_H
1.13      millert    96: #  undef termios
                     97: #  define termios              termio
                     98: #  define tcgetattr(f, t)      ioctl(f, TCGETA, t)
                     99: #  define tcsetattr(f, a, t)   ioctl(f, a, t)
                    100: #  undef TCSAFLUSH
                    101: #  define TCSAFLUSH            TCSETAF
1.5       millert   102: # else
1.13      millert   103: #  undef termios
                    104: #  define termios              sgttyb
                    105: #  define c_lflag              sg_flags
                    106: #  define tcgetattr(f, t)      ioctl(f, TIOCGETP, t)
                    107: #  define tcsetattr(f, a, t)   ioctl(f, a, t)
                    108: #  undef TCSAFLUSH
                    109: #  define TCSAFLUSH            TIOCSETP
1.5       millert   110: # endif /* HAVE_TERMIO_H */
                    111: #endif /* HAVE_TERMIOS_H */
1.1       millert   112:
1.7       millert   113: static volatile sig_atomic_t signo;
                    114:
                    115: static void handler __P((int));
1.10      millert   116: static char *getln __P((int, char *, size_t));
1.1       millert   117:
                    118: /*
                    119:  * Like getpass(3) but with timeout and echo flags.
                    120:  */
                    121: char *
1.5       millert   122: tgetpass(prompt, timeout, flags)
1.1       millert   123:     const char *prompt;
                    124:     int timeout;
1.5       millert   125:     int flags;
1.1       millert   126: {
1.10      millert   127:     sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
1.7       millert   128:     sigaction_t savetstp, savettin, savettou;
1.13      millert   129:     struct termios term, oterm;
1.10      millert   130:     char *pass;
1.7       millert   131:     static char buf[SUDO_PASS_MAX + 1];
                    132:     int input, output, save_errno;
1.1       millert   133:
1.10      millert   134:     (void) fflush(stdout);
1.7       millert   135: restart:
1.12      millert   136:     signo = 0;
                    137:     pass = NULL;
                    138:     save_errno = 0;
1.1       millert   139:     /* Open /dev/tty for reading/writing if possible else use stdin/stderr. */
1.10      millert   140:     if (ISSET(flags, TGP_STDIN) ||
1.5       millert   141:        (input = output = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) {
1.1       millert   142:        input = STDIN_FILENO;
                    143:        output = STDERR_FILENO;
                    144:     }
                    145:
1.7       millert   146:     /*
                    147:      * Catch signals that would otherwise cause the user to end
1.10      millert   148:      * up with echo turned off in the shell.
1.7       millert   149:      */
                    150:     sigemptyset(&sa.sa_mask);
1.10      millert   151:     sa.sa_flags = SA_INTERRUPT;        /* don't restart system calls */
1.7       millert   152:     sa.sa_handler = handler;
1.10      millert   153:     (void) sigaction(SIGALRM, &sa, &savealrm);
1.7       millert   154:     (void) sigaction(SIGINT, &sa, &saveint);
                    155:     (void) sigaction(SIGHUP, &sa, &savehup);
                    156:     (void) sigaction(SIGQUIT, &sa, &savequit);
                    157:     (void) sigaction(SIGTERM, &sa, &saveterm);
                    158:     (void) sigaction(SIGTSTP, &sa, &savetstp);
                    159:     (void) sigaction(SIGTTIN, &sa, &savettin);
                    160:     (void) sigaction(SIGTTOU, &sa, &savettou);
                    161:
1.5       millert   162:     /* Turn echo off/on as specified by flags.  */
1.13      millert   163:     if (tcgetattr(input, &oterm) == 0) {
1.7       millert   164:        (void) memcpy(&term, &oterm, sizeof(term));
1.10      millert   165:        if (!ISSET(flags, TGP_ECHO))
1.13      millert   166:            CLR(term.c_lflag, ECHO|ECHONL);
1.7       millert   167: #ifdef VSTATUS
                    168:        term.c_cc[VSTATUS] = _POSIX_VDISABLE;
                    169: #endif
1.13      millert   170:        (void) tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
1.7       millert   171:     } else {
                    172:        memset(&term, 0, sizeof(term));
                    173:        memset(&oterm, 0, sizeof(oterm));
                    174:     }
1.8       millert   175:
1.12      millert   176:     /* No output if we are already backgrounded. */
                    177:     if (signo != SIGTTOU && signo != SIGTTIN) {
                    178:        if (prompt)
                    179:            (void) write(output, prompt, strlen(prompt));
                    180:
                    181:        if (timeout > 0)
                    182:            alarm(timeout);
                    183:        pass = getln(input, buf, sizeof(buf));
                    184:        alarm(0);
                    185:        save_errno = errno;
1.1       millert   186:
1.13      millert   187:        if (!ISSET(term.c_lflag, ECHO))
1.12      millert   188:            (void) write(output, "\n", 1);
                    189:     }
1.1       millert   190:
1.7       millert   191:     /* Restore old tty settings and signals. */
1.13      millert   192:     if (memcmp(&term, &oterm, sizeof(term)) != 0) {
1.14      millert   193:        while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&
1.13      millert   194:            errno == EINTR)
                    195:            continue;
                    196:     }
1.10      millert   197:     (void) sigaction(SIGALRM, &savealrm, NULL);
1.7       millert   198:     (void) sigaction(SIGINT, &saveint, NULL);
                    199:     (void) sigaction(SIGHUP, &savehup, NULL);
                    200:     (void) sigaction(SIGQUIT, &savequit, NULL);
                    201:     (void) sigaction(SIGTERM, &saveterm, NULL);
                    202:     (void) sigaction(SIGTSTP, &savetstp, NULL);
                    203:     (void) sigaction(SIGTTIN, &savettin, NULL);
                    204:     (void) sigaction(SIGTTOU, &savettou, NULL);
1.1       millert   205:     if (input != STDIN_FILENO)
                    206:        (void) close(input);
                    207:
1.7       millert   208:     /*
                    209:      * If we were interrupted by a signal, resend it to ourselves
                    210:      * now that we have restored the signal handlers.
                    211:      */
                    212:     if (signo) {
1.10      millert   213:        kill(getpid(), signo);
1.7       millert   214:        switch (signo) {
                    215:            case SIGTSTP:
                    216:            case SIGTTIN:
                    217:            case SIGTTOU:
                    218:                goto restart;
                    219:        }
                    220:     }
                    221:
1.12      millert   222:     if (save_errno)
                    223:        errno = save_errno;
1.7       millert   224:     return(pass);
1.1       millert   225: }
                    226:
                    227: static char *
1.10      millert   228: getln(fd, buf, bufsiz)
1.1       millert   229:     int fd;
                    230:     char *buf;
                    231:     size_t bufsiz;
                    232: {
1.10      millert   233:     char c, *cp;
                    234:     ssize_t nr;
1.1       millert   235:
1.7       millert   236:     if (bufsiz == 0) {
                    237:        errno = EINVAL;
1.1       millert   238:        return(NULL);                   /* sanity */
1.7       millert   239:     }
1.1       millert   240:
1.2       millert   241:     cp = buf;
1.10      millert   242:     nr = -1;
                    243:     while (--bufsiz && (nr = read(fd, &c, 1)) == 1 && c != '\n' && c != '\r')
                    244:        *cp++ = c;
1.1       millert   245:     *cp = '\0';
1.10      millert   246:     return(nr == -1 ? NULL : buf);
1.7       millert   247: }
                    248:
1.10      millert   249: static void
                    250: handler(s)
1.7       millert   251:     int s;
                    252: {
1.10      millert   253:     if (s != SIGALRM)
                    254:        signo = s;
1.1       millert   255: }