version 1.15, 2008/07/31 16:44:04 |
version 1.16, 2008/11/14 11:58:08 |
|
|
/* |
/* |
* Copyright (c) 1996, 1998-2005 Todd C. Miller <Todd.Miller@courtesan.com> |
* Copyright (c) 1996, 1998-2005, 2007-2008 |
|
* Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
|
|
#include "sudo.h" |
#include "sudo.h" |
|
|
#ifndef lint |
#ifndef lint |
__unused static const char rcsid[] = "$Sudo: tgetpass.c,v 1.111.2.7 2008/06/21 00:27:01 millert Exp $"; |
__unused static const char rcsid[] = "$Sudo: tgetpass.c,v 1.124 2008/11/08 15:30:42 millert Exp $"; |
#endif /* lint */ |
#endif /* lint */ |
|
|
#ifndef TCSASOFT |
#ifndef TCSASOFT |
|
|
|
|
static void handler __P((int)); |
static void handler __P((int)); |
static char *getln __P((int, char *, size_t)); |
static char *getln __P((int, char *, size_t)); |
|
static char *sudo_askpass(const char *); |
|
|
/* |
/* |
* Like getpass(3) but with timeout and echo flags. |
* Like getpass(3) but with timeout and echo flags. |
|
|
int input, output, save_errno; |
int input, output, save_errno; |
|
|
(void) fflush(stdout); |
(void) fflush(stdout); |
|
|
|
/* If using a helper program to get the password, run it instead. */ |
|
if (ISSET(flags, TGP_ASKPASS) && user_askpass) |
|
return(sudo_askpass(prompt)); |
|
|
restart: |
restart: |
signo = 0; |
signo = 0; |
pass = NULL; |
pass = NULL; |
|
|
* Catch signals that would otherwise cause the user to end |
* Catch signals that would otherwise cause the user to end |
* up with echo turned off in the shell. |
* up with echo turned off in the shell. |
*/ |
*/ |
|
zero_bytes(&sa, sizeof(sa)); |
sigemptyset(&sa.sa_mask); |
sigemptyset(&sa.sa_mask); |
sa.sa_flags = SA_INTERRUPT; /* don't restart system calls */ |
sa.sa_flags = SA_INTERRUPT; /* don't restart system calls */ |
sa.sa_handler = handler; |
sa.sa_handler = handler; |
|
|
#endif |
#endif |
(void) tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); |
(void) tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); |
} else { |
} else { |
memset(&term, 0, sizeof(term)); |
zero_bytes(&term, sizeof(term)); |
memset(&oterm, 0, sizeof(oterm)); |
zero_bytes(&oterm, sizeof(oterm)); |
} |
} |
|
|
/* No output if we are already backgrounded. */ |
/* No output if we are already backgrounded. */ |
|
|
return(pass); |
return(pass); |
} |
} |
|
|
|
/* |
|
* Fork a child and exec sudo-askpass to get the password from the user. |
|
*/ |
static char * |
static char * |
|
sudo_askpass(prompt) |
|
const char *prompt; |
|
{ |
|
static char buf[SUDO_PASS_MAX + 1], *pass; |
|
sigaction_t sa, saved_sa_pipe; |
|
int pfd[2]; |
|
pid_t pid; |
|
|
|
if (pipe(pfd) == -1) |
|
error(1, "unable to create pipe"); |
|
|
|
if ((pid = fork()) == -1) |
|
error(1, "unable to fork"); |
|
|
|
if (pid == 0) { |
|
/* child, point stdout to output side of the pipe and exec askpass */ |
|
(void) dup2(pfd[1], STDOUT_FILENO); |
|
set_perms(PERM_FULL_USER); |
|
closefrom(STDERR_FILENO + 1); |
|
execl(user_askpass, user_askpass, prompt, (char *)NULL); |
|
warning("unable to run %s", user_askpass); |
|
_exit(255); |
|
} |
|
|
|
/* Ignore SIGPIPE in case child exits prematurely */ |
|
zero_bytes(&sa, sizeof(sa)); |
|
sigemptyset(&sa.sa_mask); |
|
sa.sa_flags = 0; |
|
sa.sa_handler = SIG_IGN; |
|
(void) sigaction(SIGPIPE, &sa, &saved_sa_pipe); |
|
|
|
/* Get response from child (askpass) and restore SIGPIPE handler */ |
|
(void) close(pfd[1]); |
|
pass = getln(pfd[0], buf, sizeof(buf)); |
|
(void) close(pfd[0]); |
|
(void) sigaction(SIGPIPE, &saved_sa_pipe, NULL); |
|
|
|
return(pass); |
|
} |
|
|
|
static char * |
getln(fd, buf, bufsiz) |
getln(fd, buf, bufsiz) |
int fd; |
int fd; |
char *buf; |
char *buf; |
size_t bufsiz; |
size_t bufsiz; |
{ |
{ |
char c, *cp; |
ssize_t nr = -1; |
ssize_t nr; |
char *cp = buf; |
|
char c = '\0'; |
|
|
if (bufsiz == 0) { |
if (bufsiz == 0) { |
errno = EINVAL; |
errno = EINVAL; |
return(NULL); /* sanity */ |
return(NULL); /* sanity */ |
} |
} |
|
|
cp = buf; |
while (--bufsiz) { |
nr = -1; |
nr = read(fd, &c, 1); |
while (--bufsiz && (nr = read(fd, &c, 1)) == 1 && c != '\n' && c != '\r') |
if (nr != 1 || c == '\n' || c == '\r') |
|
break; |
*cp++ = c; |
*cp++ = c; |
|
} |
*cp = '\0'; |
*cp = '\0'; |
return(nr == -1 ? NULL : buf); |
|
|
return(nr == 1 ? buf : NULL); |
} |
} |
|
|
static void |
static void |