diff options
author | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 17:53:41 -0800 |
---|---|---|
committer | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 18:17:08 -0800 |
commit | 212b52cf29c06cc209bc8ac0540dbab1acdf1464 (patch) | |
tree | 58da0bf39f5c4122e4a1b4da20fdeea52b97a671 /modules/pam_exec/pam_exec.c | |
parent | 9c52e721044e7501c3d4567b36d222dc7326224a (diff) | |
parent | 56c8282d128fb484ffc77dff73abf42229b291d3 (diff) | |
download | pam-212b52cf29c06cc209bc8ac0540dbab1acdf1464.tar.gz pam-212b52cf29c06cc209bc8ac0540dbab1acdf1464.tar.bz2 pam-212b52cf29c06cc209bc8ac0540dbab1acdf1464.zip |
New upstream version 1.1.0
Diffstat (limited to 'modules/pam_exec/pam_exec.c')
-rw-r--r-- | modules/pam_exec/pam_exec.c | 195 |
1 files changed, 152 insertions, 43 deletions
diff --git a/modules/pam_exec/pam_exec.c b/modules/pam_exec/pam_exec.c index 14dddd54..7b2e402c 100644 --- a/modules/pam_exec/pam_exec.c +++ b/modules/pam_exec/pam_exec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Thorsten Kukuk <kukuk@thkukuk.de> + * Copyright (c) 2006, 2008 Thorsten Kukuk <kukuk@thkukuk.de> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -58,6 +58,7 @@ #include <security/pam_modules.h> #include <security/pam_modutil.h> #include <security/pam_ext.h> +#include <security/_pam_macros.h> #define ENV_ITEM(n) { (n), #n } static struct { @@ -71,15 +72,20 @@ static struct { ENV_ITEM(PAM_RUSER), }; + static int -call_exec (pam_handle_t *pamh, int argc, const char **argv) +call_exec (const char *pam_type, pam_handle_t *pamh, + int argc, const char **argv) { int debug = 0; int call_setuid = 0; int quiet = 0; + int expose_authtok = 0; int optargc; const char *logfile = NULL; + const char *authtok = NULL; pid_t pid; + int fds[2]; if (argc < 1) { pam_syslog (pamh, LOG_ERR, @@ -100,10 +106,63 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) call_setuid = 1; else if (strcasecmp (argv[optargc], "quiet") == 0) quiet = 1; + else if (strcasecmp (argv[optargc], "expose_authtok") == 0) + expose_authtok = 1; else break; /* Unknown option, assume program to execute. */ } + if (expose_authtok == 1) + { + if (strcmp (pam_type, "auth") != 0) + { + pam_syslog (pamh, LOG_ERR, + "expose_authtok not supported for type %s", pam_type); + expose_authtok = 0; + } + else + { + const void *void_pass; + int retval; + + retval = pam_get_item (pamh, PAM_AUTHTOK, &void_pass); + if (retval != PAM_SUCCESS) + { + if (debug) + pam_syslog (pamh, LOG_DEBUG, + "pam_get_item (PAM_AUTHTOK) failed, return %d", + retval); + return retval; + } + else if (void_pass == NULL) + { + char *resp = NULL; + + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, + &resp, _("Password: ")); + + if (retval != PAM_SUCCESS) + { + _pam_drop (resp); + if (retval == PAM_CONV_AGAIN) + retval = PAM_INCOMPLETE; + return retval; + } + + pam_set_item (pamh, PAM_AUTHTOK, resp); + authtok = strdupa (resp); + _pam_drop (resp); + } + else + authtok = void_pass; + + if (pipe(fds) != 0) + { + pam_syslog (pamh, LOG_ERR, "Could not create pipe: %m"); + return PAM_SYSTEM_ERR; + } + } + } if (optargc >= argc) { pam_syslog (pamh, LOG_ERR, "No path given as argument"); @@ -117,6 +176,28 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) { int status = 0; pid_t retval; + + if (expose_authtok) /* send the password to the child */ + { + if (authtok != NULL) + { /* send the password to the child */ + if (debug) + pam_syslog (pamh, LOG_DEBUG, "send password to child"); + if (write(fds[1], authtok, strlen(authtok)+1) == -1) + pam_syslog (pamh, LOG_ERR, + "sending password to child failed: %m"); + authtok = NULL; + } + else + { + if (write(fds[1], "", 1) == -1) /* blank password */ + pam_syslog (pamh, LOG_ERR, + "sending password to child failed: %m"); + } + close(fds[0]); /* close here to avoid possible SIGPIPE above */ + close(fds[1]); + } + while ((retval = waitpid (pid, &status, 0)) == -1 && errno == EINTR); if (retval == (pid_t)-1) @@ -160,17 +241,40 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) { char **arggv; int i; + char **envlist, **tmp; + int envlen, nitems; + char *envstr; - for (i = 0; i < sysconf (_SC_OPEN_MAX); i++) - close (i); + if (expose_authtok) + { + /* reopen stdin as pipe */ + if (dup2(fds[0], STDIN_FILENO) == -1) + { + int err = errno; + pam_syslog (pamh, LOG_ERR, "dup2 of STDIN failed: %m"); + _exit (err); + } - /* New stdin. */ - if ((i = open ("/dev/null", O_RDWR)) < 0) + for (i = 0; i < sysconf (_SC_OPEN_MAX); i++) + { + if (i != STDIN_FILENO) + close (i); + } + } + else { - int err = errno; - pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m"); - exit (err); + for (i = 0; i < sysconf (_SC_OPEN_MAX); i++) + close (i); + + /* New stdin. */ + if ((i = open ("/dev/null", O_RDWR)) < 0) + { + int err = errno; + pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m"); + _exit (err); + } } + /* New stdout and stderr. */ if (logfile) { @@ -183,7 +287,7 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) int err = errno; pam_syslog (pamh, LOG_ERR, "open of %s failed: %m", logfile); - exit (err); + _exit (err); } if (asprintf (&buffer, "*** %s", ctime (&tm)) > 0) { @@ -192,18 +296,22 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) } } else - if (dup (i) == -1) - { - int err = errno; - pam_syslog (pamh, LOG_ERR, "dup failed: %m"); - exit (err); - } + { + /* New stdout/stderr. */ + if ((i = open ("/dev/null", O_RDWR)) < 0) + { + int err = errno; + pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m"); + _exit (err); + } + } + if (dup (i) == -1) - { + { int err = errno; pam_syslog (pamh, LOG_ERR, "dup failed: %m"); - exit (err); - } + _exit (err); + } if (call_setuid) if (setuid (geteuid ()) == -1) @@ -211,27 +319,24 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) int err = errno; pam_syslog (pamh, LOG_ERR, "setuid(%lu) failed: %m", (unsigned long) geteuid ()); - exit (err); + _exit (err); } if (setsid () == -1) { int err = errno; pam_syslog (pamh, LOG_ERR, "setsid failed: %m"); - exit (err); + _exit (err); } arggv = calloc (argc + 4, sizeof (char *)); if (arggv == NULL) - exit (ENOMEM); + _exit (ENOMEM); for (i = 0; i < (argc - optargc); i++) arggv[i] = strdup(argv[i+optargc]); arggv[i] = NULL; - char **envlist, **tmp; - int envlen, nitems; - /* * Set up the child's environment list. It consists of the PAM * environment, plus a few hand-picked PAM items. @@ -240,18 +345,18 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) for (envlen = 0; envlist[envlen] != NULL; ++envlen) /* nothing */ ; nitems = sizeof(env_items) / sizeof(*env_items); - tmp = realloc(envlist, (envlen + nitems + 1) * sizeof(*envlist)); + /* + 2 because of PAM_TYPE and NULL entry */ + tmp = realloc(envlist, (envlen + nitems + 2) * sizeof(*envlist)); if (tmp == NULL) { free(envlist); pam_syslog (pamh, LOG_ERR, "realloc environment failed: %m"); - exit (ENOMEM); + _exit (ENOMEM); } envlist = tmp; for (i = 0; i < nitems; ++i) { const void *item; - char *envstr; if (pam_get_item(pamh, env_items[i].item, &item) != PAM_SUCCESS || item == NULL) continue; @@ -259,25 +364,29 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) { free(envlist); pam_syslog (pamh, LOG_ERR, "prepare environment failed: %m"); - exit (ENOMEM); + _exit (ENOMEM); } envlist[envlen++] = envstr; envlist[envlen] = NULL; } + if (asprintf(&envstr, "PAM_TYPE=%s", pam_type) < 0) + { + free(envlist); + pam_syslog (pamh, LOG_ERR, "prepare environment failed: %m"); + _exit (ENOMEM); + } + envlist[envlen++] = envstr; + envlist[envlen] = NULL; + if (debug) pam_syslog (pamh, LOG_DEBUG, "Calling %s ...", arggv[0]); - if (execve (arggv[0], arggv, envlist) == -1) - { - int err = errno; - pam_syslog (pamh, LOG_ERR, "execve(%s,...) failed: %m", - arggv[0]); - free(envlist); - exit (err); - } + execve (arggv[0], arggv, envlist); + i = errno; + pam_syslog (pamh, LOG_ERR, "execve(%s,...) failed: %m", arggv[0]); free(envlist); - exit (1); /* should never be reached. */ + _exit (i); } return PAM_SYSTEM_ERR; /* will never be reached. */ } @@ -286,7 +395,7 @@ PAM_EXTERN int pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - return call_exec (pamh, argc, argv); + return call_exec ("auth", pamh, argc, argv); } PAM_EXTERN int @@ -304,28 +413,28 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, { if (flags & PAM_PRELIM_CHECK) return PAM_SUCCESS; - return call_exec (pamh, argc, argv); + return call_exec ("password", pamh, argc, argv); } PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - return call_exec (pamh, argc, argv); + return call_exec ("account", pamh, argc, argv); } PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - return call_exec (pamh, argc, argv); + return call_exec ("open_session", pamh, argc, argv); } PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - return call_exec (pamh, argc, argv); + return call_exec ("close_session", pamh, argc, argv); } #ifdef PAM_STATIC |