~ubuntu-branches/ubuntu/quantal/sudo/quantal

« back to all changes in this revision

Viewing changes to tgetpass.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2011-11-20 12:07:45 UTC
  • mfrom: (1.3.17 sid)
  • Revision ID: package-import@ubuntu.com-20111120120745-o3qpklobmygytndc
Tags: 1.8.3p1-1ubuntu1
* Merge from debian/testing, remaining changes:
  - debian/patches/keep_home_by_default.patch:
    + Set HOME in initial_keepenv_table. (rebased for 1.8.3p1)
  - debian/patches/enable_badpass.patch: turn on "mail_badpass" by default:
    + attempting sudo without knowing a login password is as bad as not
      being listed in the sudoers file, especially if getting the password
      wrong means doing the access-check-email-notification never happens
      (rebased for 1.8.3p1)
  - debian/rules:
    + compile with --without-lecture --with-tty-tickets (Ubuntu specific)
    + install man/man8/sudo_root.8 (Ubuntu specific)
    + install apport hooks
    + The ubuntu-sudo-as-admin-successful.patch was taken upstream by
      Debian however it requires a --enable-admin-flag configure flag to
      actually enable it.
  - debian/sudoers: 
    + grant admin group sudo access
  - debian/sudo-ldap.dirs, debian/sudo.dirs: 
    + add usr/share/apport/package-hooks
  - debian/sudo.preinst:
    + avoid conffile prompt by checking for known default /etc/sudoers
      and if found installing the correct default /etc/sudoers file

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 1996, 1998-2005, 2007-2010
3
 
 *      Todd C. Miller <Todd.Miller@courtesan.com>
4
 
 *
5
 
 * Permission to use, copy, modify, and distribute this software for any
6
 
 * purpose with or without fee is hereby granted, provided that the above
7
 
 * copyright notice and this permission notice appear in all copies.
8
 
 *
9
 
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 
 *
17
 
 * Sponsored in part by the Defense Advanced Research Projects
18
 
 * Agency (DARPA) and Air Force Research Laboratory, Air Force
19
 
 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
20
 
 */
21
 
 
22
 
#ifdef __TANDEM
23
 
# include <floss.h>
24
 
#endif
25
 
 
26
 
#include <config.h>
27
 
 
28
 
#include <sys/types.h>
29
 
#include <sys/param.h>
30
 
#include <stdio.h>
31
 
#ifdef STDC_HEADERS
32
 
# include <stdlib.h>
33
 
# include <stddef.h>
34
 
#else
35
 
# ifdef HAVE_STDLIB_H
36
 
#  include <stdlib.h>
37
 
# endif
38
 
#endif /* STDC_HEADERS */
39
 
#ifdef HAVE_STRING_H
40
 
# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
41
 
#  include <memory.h>
42
 
# endif
43
 
# include <string.h>
44
 
#endif /* HAVE_STRING_H */
45
 
#ifdef HAVE_STRINGS_H
46
 
# include <strings.h>
47
 
#endif /* HAVE_STRINGS_H */
48
 
#ifdef HAVE_UNISTD_H
49
 
# include <unistd.h>
50
 
#endif /* HAVE_UNISTD_H */
51
 
#include <pwd.h>
52
 
#include <errno.h>
53
 
#include <signal.h>
54
 
#include <fcntl.h>
55
 
 
56
 
#include "sudo.h"
57
 
 
58
 
static volatile sig_atomic_t signo[NSIG];
59
 
 
60
 
static void handler __P((int));
61
 
static char *getln __P((int, char *, size_t, int));
62
 
static char *sudo_askpass __P((const char *));
63
 
 
64
 
/*
65
 
 * Like getpass(3) but with timeout and echo flags.
66
 
 */
67
 
char *
68
 
tgetpass(prompt, timeout, flags)
69
 
    const char *prompt;
70
 
    int timeout;
71
 
    int flags;
72
 
{
73
 
    sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
74
 
    sigaction_t savetstp, savettin, savettou, savepipe;
75
 
    char *pass;
76
 
    static char buf[SUDO_PASS_MAX + 1];
77
 
    int i, input, output, save_errno, neednl = 0, need_restart;
78
 
 
79
 
    (void) fflush(stdout);
80
 
 
81
 
    /* If using a helper program to get the password, run it instead. */
82
 
    if (ISSET(flags, TGP_ASKPASS) && user_askpass)
83
 
        return(sudo_askpass(prompt));
84
 
 
85
 
restart:
86
 
    for (i = 0; i < NSIG; i++)
87
 
        signo[i] = 0;
88
 
    pass = NULL;
89
 
    save_errno = 0;
90
 
    need_restart = 0;
91
 
    /* Open /dev/tty for reading/writing if possible else use stdin/stderr. */
92
 
    if (ISSET(flags, TGP_STDIN) ||
93
 
        (input = output = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) {
94
 
        input = STDIN_FILENO;
95
 
        output = STDERR_FILENO;
96
 
    }
97
 
 
98
 
    /*
99
 
     * If we are using a tty but are not the foreground pgrp this will
100
 
     * generate SIGTTOU, so do it *before* installing the signal handlers.
101
 
     */
102
 
    if (!ISSET(flags, TGP_ECHO)) {
103
 
        if (def_pwfeedback)
104
 
            neednl = term_cbreak(input);
105
 
        else
106
 
            neednl = term_noecho(input);
107
 
    }
108
 
 
109
 
    /*
110
 
     * Catch signals that would otherwise cause the user to end
111
 
     * up with echo turned off in the shell.
112
 
     */
113
 
    zero_bytes(&sa, sizeof(sa));
114
 
    sigemptyset(&sa.sa_mask);
115
 
    sa.sa_flags = SA_INTERRUPT; /* don't restart system calls */
116
 
    sa.sa_handler = handler;
117
 
    (void) sigaction(SIGALRM, &sa, &savealrm);
118
 
    (void) sigaction(SIGINT, &sa, &saveint);
119
 
    (void) sigaction(SIGHUP, &sa, &savehup);
120
 
    (void) sigaction(SIGQUIT, &sa, &savequit);
121
 
    (void) sigaction(SIGTERM, &sa, &saveterm);
122
 
    (void) sigaction(SIGTSTP, &sa, &savetstp);
123
 
    (void) sigaction(SIGTTIN, &sa, &savettin);
124
 
    (void) sigaction(SIGTTOU, &sa, &savettou);
125
 
 
126
 
    /* Ignore SIGPIPE in case stdin is a pipe and TGP_STDIN is set */
127
 
    sa.sa_handler = SIG_IGN;
128
 
    (void) sigaction(SIGPIPE, &sa, &savepipe);
129
 
 
130
 
    if (prompt)
131
 
        (void) write(output, prompt, strlen(prompt));
132
 
 
133
 
    if (timeout > 0)
134
 
        alarm(timeout);
135
 
    pass = getln(input, buf, sizeof(buf), def_pwfeedback);
136
 
    alarm(0);
137
 
    save_errno = errno;
138
 
 
139
 
    if (neednl || pass == NULL)
140
 
        (void) write(output, "\n", 1);
141
 
 
142
 
    /* Restore old tty settings and signals. */
143
 
    if (!ISSET(flags, TGP_ECHO))
144
 
        term_restore(input, 1);
145
 
    (void) sigaction(SIGALRM, &savealrm, NULL);
146
 
    (void) sigaction(SIGINT, &saveint, NULL);
147
 
    (void) sigaction(SIGHUP, &savehup, NULL);
148
 
    (void) sigaction(SIGQUIT, &savequit, NULL);
149
 
    (void) sigaction(SIGTERM, &saveterm, NULL);
150
 
    (void) sigaction(SIGTSTP, &savetstp, NULL);
151
 
    (void) sigaction(SIGTTIN, &savettin, NULL);
152
 
    (void) sigaction(SIGTTOU, &savettou, NULL);
153
 
    (void) sigaction(SIGTTOU, &savepipe, NULL);
154
 
    if (input != STDIN_FILENO)
155
 
        (void) close(input);
156
 
 
157
 
    /*
158
 
     * If we were interrupted by a signal, resend it to ourselves
159
 
     * now that we have restored the signal handlers.
160
 
     */
161
 
    for (i = 0; i < NSIG; i++) {
162
 
        if (signo[i]) {
163
 
            kill(getpid(), i);
164
 
            switch (i) {
165
 
                case SIGTSTP:
166
 
                case SIGTTIN:
167
 
                case SIGTTOU:
168
 
                    need_restart = 1;
169
 
                    break;
170
 
            }
171
 
        }
172
 
    }
173
 
    if (need_restart)
174
 
        goto restart;
175
 
 
176
 
    if (save_errno)
177
 
        errno = save_errno;
178
 
    return(pass);
179
 
}
180
 
 
181
 
/*
182
 
 * Fork a child and exec sudo-askpass to get the password from the user.
183
 
 */
184
 
static char *
185
 
sudo_askpass(prompt)
186
 
    const char *prompt;
187
 
{
188
 
    static char buf[SUDO_PASS_MAX + 1], *pass;
189
 
    sigaction_t sa, saved_sa_pipe;
190
 
    int pfd[2];
191
 
    pid_t pid;
192
 
 
193
 
    if (pipe(pfd) == -1)
194
 
        error(1, "unable to create pipe");
195
 
 
196
 
    if ((pid = fork()) == -1)
197
 
        error(1, "unable to fork");
198
 
 
199
 
    if (pid == 0) {
200
 
        /* child, point stdout to output side of the pipe and exec askpass */
201
 
        if (dup2(pfd[1], STDOUT_FILENO) == -1) {
202
 
            warning("dup2");
203
 
            _exit(255);
204
 
        }
205
 
        (void) dup2(pfd[1], STDOUT_FILENO);
206
 
        set_perms(PERM_FULL_USER);
207
 
        closefrom(STDERR_FILENO + 1);
208
 
        execl(user_askpass, user_askpass, prompt, (char *)NULL);
209
 
        warning("unable to run %s", user_askpass);
210
 
        _exit(255);
211
 
    }
212
 
 
213
 
    /* Ignore SIGPIPE in case child exits prematurely */
214
 
    zero_bytes(&sa, sizeof(sa));
215
 
    sigemptyset(&sa.sa_mask);
216
 
    sa.sa_flags = SA_INTERRUPT;
217
 
    sa.sa_handler = SIG_IGN;
218
 
    (void) sigaction(SIGPIPE, &sa, &saved_sa_pipe);
219
 
 
220
 
    /* Get response from child (askpass) and restore SIGPIPE handler */
221
 
    (void) close(pfd[1]);
222
 
    pass = getln(pfd[0], buf, sizeof(buf), 0);
223
 
    (void) close(pfd[0]);
224
 
    (void) sigaction(SIGPIPE, &saved_sa_pipe, NULL);
225
 
 
226
 
    return(pass);
227
 
}
228
 
 
229
 
extern int term_erase, term_kill;
230
 
 
231
 
static char *
232
 
getln(fd, buf, bufsiz, feedback)
233
 
    int fd;
234
 
    char *buf;
235
 
    size_t bufsiz;
236
 
    int feedback;
237
 
{
238
 
    size_t left = bufsiz;
239
 
    ssize_t nr = -1;
240
 
    char *cp = buf;
241
 
    char c = '\0';
242
 
 
243
 
    if (left == 0) {
244
 
        errno = EINVAL;
245
 
        return(NULL);                   /* sanity */
246
 
    }
247
 
 
248
 
    while (--left) {
249
 
        nr = read(fd, &c, 1);
250
 
        if (nr != 1 || c == '\n' || c == '\r')
251
 
            break;
252
 
        if (feedback) {
253
 
            if (c == term_kill) {
254
 
                while (cp > buf) {
255
 
                    (void) write(fd, "\b \b", 3);
256
 
                    --cp;
257
 
                }
258
 
                left = bufsiz;
259
 
                continue;
260
 
            } else if (c == term_erase) {
261
 
                if (cp > buf) {
262
 
                    (void) write(fd, "\b \b", 3);
263
 
                    --cp;
264
 
                    left++;
265
 
                }
266
 
                continue;
267
 
            }
268
 
            (void) write(fd, "*", 1);
269
 
        }
270
 
        *cp++ = c;
271
 
    }
272
 
    *cp = '\0';
273
 
    if (feedback) {
274
 
        /* erase stars */
275
 
        while (cp > buf) {
276
 
            (void) write(fd, "\b \b", 3);
277
 
            --cp;
278
 
        }
279
 
    }
280
 
 
281
 
    return(nr == 1 ? buf : NULL);
282
 
}
283
 
 
284
 
static void
285
 
handler(s)
286
 
    int s;
287
 
{
288
 
    if (s != SIGALRM)
289
 
        signo[s] = 1;
290
 
}
291
 
 
292
 
int
293
 
tty_present()
294
 
{
295
 
    int fd;
296
 
 
297
 
    if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) != -1)
298
 
        close(fd);
299
 
    return(fd != -1);
300
 
}