Debian – Why does pam_exec.so work with sudo, not with su

debianfedorapamsu

I'm trying to allow root access from a regular user shell based on the successful execution of a special program, and the goal is to have both su and sudo respond to the new PAM configuration. The special program is the sole criteria for authorization.

The config I'm trying on Debian 9 in /etc/pam.d/common-auth is:

auth  [success=done default=die]  pam_exec.so seteuid /usr/bin/whoami

…where whoami is a program that returns successful status as a placeholder for the special program. The rest of the common-auth file is commented-out.

The /etc/pam.d/su file has:

auth       sufficient pam_rootok.so
session       required   pam_env.so readenv=1
session       required   pam_env.so readenv=1 envfile=/etc/default/locale
session    optional   pam_mail.so nopen
session    required   pam_limits.so
@include common-auth
@include common-account
@include common-session

The result is that sudo will be authorized, but su will not be:

$ su
su: Permission denied

(Same results on Fedora 25 using the system-auth file: sudo works and su doesn't.)

It looks as if su simply refuses to work with pam_exec. At this point I'm at a loss and could use some clues to work through this issue…


Looking through /var/log/messages, this gets logged when su is attempted:

Mar 18 08:46:39 localhost kernel: [   61.622184] audit: type=1100 audit(1489841199.166:114): pid=1107 uid=1000 auid=1000 ses=1 msg='op=PAM:authentication acct="root" exe="/bin/su" hostname=? addr=? terminal=/dev/pts/0 res=success'
Mar 18 08:46:39 localhost kernel: [   61.622480] audit: type=1101 audit(1489841199.166:115): pid=1107 uid=1000 auid=1000 ses=1 msg='op=PAM:accounting acct="root" exe="/bin/su" hostname=? addr=? terminal=/dev/pts/0 res=success'
Mar 18 08:46:39 localhost kernel: [   61.623224] audit: type=1103 audit(1489841199.167:116): pid=1107 uid=1000 auid=1000 ses=1 msg='op=PAM:setcred acct="root" exe="/bin/su" hostname=? addr=? terminal=/dev/pts/0 res=failed'

For comparison, here is what happens with sudo:

Mar 18 08:47:00 localhost kernel: [   82.750720] audit: type=1123 audit(1489841220.294:117): pid=1110 uid=1000 auid=1000 ses=1 msg='cwd="/home/user" cmd=67726570202D69206175646974202F7661722F6C6F672F6D65737361676573 terminal=pts/0 res=success'
Mar 18 08:47:00 localhost kernel: [   82.751369] audit: type=1110 audit(1489841220.295:118): pid=1110 uid=0 auid=1000 ses=1 msg='op=PAM:setcred acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=failed'
Mar 18 08:47:00 localhost kernel: [   82.751814] audit: type=1105 audit(1489841220.295:119): pid=1110 uid=0 auid=1000 ses=1 msg='op=PAM:session_open acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'


UPDATE

I arrived at a solution reflecting Debian's way of handling this issue, which is getting a solid determination of success or fail despite various commands which authenticate in different contexts, as @hildred pointed out. First, I'll show relevant lines from Debian's default common-auth:

auth  [success=1 default=ignore]  pam_unix.so nullok_secure
auth  requisite  pam_deny.so
auth  required   pam_permit.so

And here is the replacement that utilizes the Qubes auth prompt:

auth  [success=1 default=ignore]  pam_exec.so seteuid /usr/lib/qubes/qrexec-client-vm dom0 qubes.VMAuth /bin/grep -q ^1$
auth  requisite  pam_deny.so
auth  required   pam_permit.so

This "skips one" to permit only on success, otherwise deny.

The suggestion from @hildred to 'prime' the stack with a pam_permit line before the pam_exec line (where the decision is made) is less expressive but does also work and it put me on the path of finding a clear solution.

Best Answer

There are two issues I see right off the bat (other than trying experimental pam configs on common instead of just one service) is that su always authenticates as root whereas sudo usually authenticates as the user, and su has a auth sufficient line and you use bracket notation in the common file. The bracket notation does not always set your success state. This can be fixed by adding an auth requires permit line before the exec or dropping the bracket notation as for your use case it is not needed or by also using bracket notation on the root ok line so that failing the sufficient test does not set negative success.