Steps to reproduce: put this to /etc/pam.d/system: auth optional pam_exec.so expose_authtok /etc/pam.d/test put this to /etc/pam.d/test: #!/bin/sh read token exit 0 Expected result: Prompt for password on each authentication Actual result: Prompt for password on every pam function, e.g. twice on su (pam_sm_authenticate and pam_sm_setcred, the second one has no effect) Patch: Index: pam_exec.c =================================================================== --- pam_exec.c (revision 348097) +++ pam_exec.c (working copy) @@ -4,6 +4,7 @@ * Copyright (c) 2001,2003 Networks Associates Technology, Inc. * Copyright (c) 2017 Dag-Erling Smørgrav * Copyright (c) 2018 Thomas Munro + * Copyright (c) 2019 Qiantan Hong * All rights reserved. * * This software was developed for the FreeBSD Project by ThinkSec AS and @@ -495,7 +496,7 @@ ret = parse_options(__func__, &argc, &argv, &options); if (ret != 0) return (PAM_SERVICE_ERR); - + options.expose_authtok = 0; ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); /* @@ -535,7 +536,7 @@ ret = parse_options(__func__, &argc, &argv, &options); if (ret != 0) return (PAM_SERVICE_ERR); - + options.expose_authtok = 0; ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); /* @@ -575,7 +576,7 @@ ret = parse_options(__func__, &argc, &argv, &options); if (ret != 0) return (PAM_SERVICE_ERR); - + options.expose_authtok = 0; ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); /* @@ -612,7 +613,7 @@ ret = parse_options(__func__, &argc, &argv, &options); if (ret != 0) return (PAM_SERVICE_ERR); - + options.expose_authtok = 0; ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); /* @@ -649,7 +650,7 @@ ret = parse_options(__func__, &argc, &argv, &options); if (ret != 0) return (PAM_SERVICE_ERR); - + options.expose_authtok = 0; ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); /* Index: pam_exec.8 =================================================================== --- pam_exec.8 (revision 348097) +++ pam_exec.8 (working copy) @@ -1,6 +1,7 @@ .\" Copyright (c) 2001,2003 Networks Associates Technology, Inc. .\" Copyright (c) 2017 Dag-Erling Smørgrav .\" Copyright (c) 2018 Thomas Munro +.\" Copyright (c) 2019 Qiantan Hong .\" All rights reserved. .\" .\" Portions of this software were developed for the FreeBSD Project by
Thanks for the report. I'm not sure this is the best way to fix the problem. I'll look into it.
On second thought, the patch is completely incorrect. It disables the option for every service function except pam_sm_auth(), when the only problematic case is pam_sm_setcred(); in every other case, the correct solution is to not specify the option. It would probably be a good idea to implement use_first_pass as well. In the future, please submit patches as attachments.
(In reply to Dag-Erling Smørgrav from comment #3) What do you mean by not spercifying? I'm thinking that it should prompt for password only for pam_sm_authenticate(). If I do nothing it will prompt for password everytime one pam function is called. The current implementation for those cases is definitely improper. Did you mean that we should obtain the token (but without prompting) in other cases and pass to the script? pam_exec is not a module spercified in the standard, but the Linux implementation manpage says that it only pass token to the script during authentication. I think my current patch behaves the same like the Linux one. I also don't think token is always available at the time when other functions are called.
The password prompt will show for other pam services too. During a normal login, it will show before the actual login: password: combo. I have to Ctrl C and kill it. It will also show the second time after the actual password prompt (which ahs to be CtrlCed too). These are probably caused by open_session etc.
It will only prompt for a password if you use the `expose_password` option. You probably don't need it for accounting, session management etc., so just leave it out of those lines. If you *do* want to use `expose_password` for those services as well, use the `use_first_pass` option which I am about to add. Note that the Linux version of `pam_exec(8)` does not support `pam_setcred(3)` at all. That might be a better solution, but it breaks backward compatibility.
A commit references this bug: Author: des Date: Sun Jun 30 14:46:16 UTC 2019 New revision: 349556 URL: https://svnweb.freebsd.org/changeset/base/349556 Log: Changes to the expose_password functionality: - Implement use_first_pass, allowing expose_password to be used by other service functions than pam_auth() without prompting a second time. - Don't prompt for a password during pam_setcred(). PR: 238041 MFC after: 3 weeks Changes: head/lib/libpam/modules/pam_exec/pam_exec.8 head/lib/libpam/modules/pam_exec/pam_exec.c
Hello, Everyone! What you say about try_first_pass?
(In reply to Dag-Erling Smørgrav from comment #6) Asking for a password at a stage other than the authentication stage seems to be wrong.
Created attachment 222960 [details] pam_exec.c.diff Сorrect fix for this issue
Created attachment 222967 [details] pam_exec.c.diff Most programs using pam do not expect to be prompted for a password at a stage other than the authentication stage.
Created attachment 223141 [details] pam_exec.c.diff - fixed return_prog_exit_status (did not work as expected) - added support expose_authtok for pam_sm_chauthtok
After preparing the man page, I will post this fix at https://reviews.freebsd.org/