Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Jan 2001 02:04:03 -0500 (EST)
From:      djm@web.us.uu.net (David J. MacKenzie)
To:        n@nectar.com
Cc:        djm@web.us.uu.net, freebsd-security@freebsd.org
Subject:   Re: Fwd: [PAM broken design? pam_setcred]
Message-ID:  <20010120070403.43D3A12686@jenkins.web.us.uu.net>

next in thread | raw e-mail | index | archive | help
> Is it just me, or is pam_setcred broken?  For example, with the
> following config file:
>
>   login auth sufficient pam_skey.so
>   login auth sufficient pam_krb5.so
>   login auth required   pam_unix.so
>
> Regardless of whether you authenticate with `skey', `krb5', or `unix',
> pam_sm_setcred is called in pam_skey.so, i.e. the module search starts
> over.  By my reading of the Solaris man page, pam_sm_setcred should be
> called in the module that successfully authenticated the user.  At any
> rate this seems infinitely more useful.

Note a few complications:

1. That several auth checks could be listed as "required".
   It would be more common to have several account management
   functions be required, but it's possible for any module type.
2. The auth info saved can be used by the account management
   function as well as by the setcred function.  This is the case
   for the pam_krb5 module.

I checked against the reference implementation of PAM, Sun's, by creating
a pam_echo module that is like pam_permit but it also prints a line
when it enters each of its functions.  Then I duplicated it into a
pam_echo2 module that's the same except for the name and the messages
it prints.  Then I duplicated it again into a pam_echodeny module
that's the same except its auth function always fails instead of
always succeeding.  I duplicated it again to create pam_echodeny2,
where both the auth and setcred functions fail.

I ran a few tests on Solaris 8 and on FreeBSD 4.2-stable, using my
PAM-patched su.  I also ran them on Linux-Mandrake 7.0, using
Linux-PAM 0.72 just in case it's changed since FreeBSD imported it.

1: Everything required for both modules:

Solaris:

djm@rampart 21 $ su
pam_echo pam_sm_authenticate
pam_echo2 pam_sm_authenticate
pam_echo pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echo pam_sm_setcred
pam_echo2 pam_sm_setcred
bash-2.03# grep '^su' /etc/pam.conf
su      auth    required        /usr/lib/security/$ISA/pam_echo.so.1
su      auth    required        /usr/lib/security/$ISA/pam_echo2.so.1
su      account required        /usr/lib/security/$ISA/pam_echo.so.1
su      account required        /usr/lib/security/$ISA/pam_echo2.so.1
su      session required        /usr/lib/security/$ISA/pam_echo.so.1
su      session required        /usr/lib/security/$ISA/pam_echo2.so.1

FreeBSD:

djm@gaius 27 $ su
pam_echo pam_sm_authenticate
pam_echo2 pam_sm_authenticate
pam_echo pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echo pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echo pam_sm_setcred
pam_echo2 pam_sm_setcred
~
root@gaius 31 $ grep '^su' /etc/pam.conf
su      auth    required        pam_echo.so
su      auth    required        pam_echo2.so
su      account required        pam_echo.so
su      account required        pam_echo2.so
su      session required        pam_echo.so
su      session required        pam_echo2.so
~
root@gaius 32 $

Linux:

djm@dagger 2 $ su
pam_echo pam_sm_authenticate
pam_echo2 pam_sm_authenticate
pam_echo pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echo pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echo pam_sm_setcred
pam_echo2 pam_sm_setcred
~
root@dagger 1 $ cat /etc/pam.d/su
auth       required     /lib/security/pam_echo.so
auth       required     /lib/security/pam_echo2.so
account    required     /lib/security/pam_echo.so
account    required     /lib/security/pam_echo2.so
session    required     /lib/security/pam_echo.so
session    required     /lib/security/pam_echo2.so

2: First module auth sufficient:

Solaris:

djm@rampart 22 $ su
pam_echo pam_sm_authenticate
pam_echo pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echo pam_sm_setcred
pam_echo2 pam_sm_setcred
bash-2.03# grep '^su' /etc/pam.conf
su      auth    sufficient      /usr/lib/security/$ISA/pam_echo.so.1
su      auth    required        /usr/lib/security/$ISA/pam_echo2.so.1
su      account required        /usr/lib/security/$ISA/pam_echo.so.1
su      account required        /usr/lib/security/$ISA/pam_echo2.so.1
su      session required        /usr/lib/security/$ISA/pam_echo.so.1
su      session required        /usr/lib/security/$ISA/pam_echo2.so.1

FreeBSD:

djm@gaius 28 $ su
pam_echo pam_sm_authenticate
pam_echo pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echo pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echo pam_sm_setcred
~
root@gaius 31 $ grep '^su' /etc/pam.conf
su      auth    sufficient      pam_echo.so
su      auth    required        pam_echo2.so
su      account required        pam_echo.so
su      account required        pam_echo2.so
su      session required        pam_echo.so
su      session required        pam_echo2.so

Linux:

djm@dagger 3 $ su
pam_echo pam_sm_authenticate
pam_echo pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echo pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echo pam_sm_setcred
~
root@dagger 1 $ cat /etc/pam.d/su
auth       sufficient   /lib/security/pam_echo.so
auth       required     /lib/security/pam_echo2.so
account    required     /lib/security/pam_echo.so
account    required     /lib/security/pam_echo2.so
session    required     /lib/security/pam_echo.so
session    required     /lib/security/pam_echo2.so

3. First auth is sufficient but fails, every setcred succeeds
(this is your case):

Solaris:

djm@rampart 28 $ su
pam_echodeny pam_sm_authenticate
pam_echo2 pam_sm_authenticate
pam_echodeny pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echodeny pam_sm_setcred
pam_echo2 pam_sm_setcred
bash-2.03# grep '^su' /etc/pam.conf
su      auth    sufficient      /usr/lib/security/$ISA/pam_echodeny.so.1
su      auth    required        /usr/lib/security/$ISA/pam_echo2.so.1
su      account required        /usr/lib/security/$ISA/pam_echodeny.so.1
su      account required        /usr/lib/security/$ISA/pam_echo2.so.1
su      session required        /usr/lib/security/$ISA/pam_echodeny.so.1
su      session required        /usr/lib/security/$ISA/pam_echo2.so.1

FreeBSD:

djm@gaius 55 $ su
pam_echodeny pam_sm_authenticate
pam_echo2 pam_sm_authenticate
pam_echodeny pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echodeny pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echodeny pam_sm_setcred
~
root@gaius 31 $ grep '^su' /etc/pam.conf
su      auth    sufficient      pam_echodeny.so
su      auth    required        pam_echo2.so
su      account required        pam_echodeny.so
su      account required        pam_echo2.so
su      session required        pam_echodeny.so
su      session required        pam_echo2.so

Linux:

djm@dagger 4 $ su
pam_echodeny pam_sm_authenticate
pam_echo2 pam_sm_authenticate
pam_echodeny pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echodeny pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echodeny pam_sm_setcred
~
root@dagger 1 $ cat /etc/pam.d/su
auth       sufficient   /lib/security/pam_echodeny.so
auth       required     /lib/security/pam_echo2.so
account    required     /lib/security/pam_echodeny.so
account    required     /lib/security/pam_echo2.so
session    required     /lib/security/pam_echodeny.so
session    required     /lib/security/pam_echo2.so

4. First auth is sufficient, first auth and first setcred fail
(similar to your case):

Solaris:

pam_echodeny2 pam_sm_authenticate
pam_echo2 pam_sm_authenticate
pam_echodeny2 pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echodeny2 pam_sm_setcred
pam_echo2 pam_sm_setcred
bash-2.03# grep '^su' /etc/pam.conf
su      auth    sufficient      /usr/lib/security/$ISA/pam_echodeny2.so.1
su      auth    required        /usr/lib/security/$ISA/pam_echo2.so.1
su      account required        /usr/lib/security/$ISA/pam_echodeny2.so.1
su      account required        /usr/lib/security/$ISA/pam_echo2.so.1
su      session required        /usr/lib/security/$ISA/pam_echodeny2.so.1
su      session required        /usr/lib/security/$ISA/pam_echo2.so.1

FreeBSD:

pam_echodeny2 pam_sm_authenticate
pam_echo2 pam_sm_authenticate
pam_echodeny2 pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echodeny2 pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echodeny2 pam_sm_setcred
pam_echo2 pam_sm_setcred
~
root@gaius 31 $ grep '^su' /etc/pam.conf
su      auth    sufficient      pam_echodeny2.so
su      auth    required        pam_echo2.so
su      account required        pam_echodeny2.so
su      account required        pam_echo2.so
su      session required        pam_echodeny2.so
su      session required        pam_echo2.so

Linux:

djm@dagger 5 $ su
pam_echodeny2 pam_sm_authenticate
pam_echo2 pam_sm_authenticate
pam_echodeny2 pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echodeny2 pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echodeny2 pam_sm_setcred
pam_echo2 pam_sm_setcred
~
root@dagger 1 $ cat /etc/pam.d/su
auth       sufficient   /lib/security/pam_echodeny2.so
auth       required     /lib/security/pam_echo2.so
account    required     /lib/security/pam_echodeny2.so
account    required     /lib/security/pam_echo2.so
session    required     /lib/security/pam_echodeny2.so
session    required     /lib/security/pam_echo2.so

5. Only one auth module specified, and everything succeeds:

Solaris:

djm@rampart 40 $ su
pam_echo pam_sm_authenticate
pam_echo pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echo pam_sm_setcred
bash-2.03# grep '^su' /etc/pam.conf
su      auth    required        /usr/lib/security/$ISA/pam_echo.so.1
su      account required        /usr/lib/security/$ISA/pam_echo.so.1
su      account required        /usr/lib/security/$ISA/pam_echo2.so.1
su      session required        /usr/lib/security/$ISA/pam_echo.so.1
su      session required        /usr/lib/security/$ISA/pam_echo2.so.1

FreeBSD:

djm@gaius 73 $ su
pam_echo pam_sm_authenticate
pam_echo pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echo pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echo pam_sm_setcred
~
root@gaius 31 $ grep '^su' /etc/pam.conf
su      auth    required        pam_echo.so
su      account required        pam_echo.so
su      account required        pam_echo2.so
su      session required        pam_echo.so
su      session required        pam_echo2.so

Linux:

djm@dagger 6 $ su
pam_echo pam_sm_authenticate
pam_echo pam_sm_acct_mgmt
pam_echo2 pam_sm_acct_mgmt
pam_echo pam_sm_open_session
pam_echo2 pam_sm_open_session
pam_echo pam_sm_setcred
~
root@dagger 1 $ cat /etc/pam.d/su
auth       required     /lib/security/pam_echo.so
account    required     /lib/security/pam_echo.so
account    required     /lib/security/pam_echo2.so
session    required     /lib/security/pam_echo.so
session    required     /lib/security/pam_echo2.so

Conclusions:

It looks like su on Solaris doesn't call open/close session;
apparently that's just for logins.  I wonder how it deletes
credentials (e.g., Kerberos ticket file) that it's created,
when su exits.  I'll have to explore that.  My patches for the
FreeBSD su do what the Linux su does, and also what the
stock MIT krb5 su does in order to delete the ticket file,
namely, fork and wait.  It looks like su should be using
setcred(PAM_DELETE_CRED) when it ends, and not using the
session functions.  I'll fix that.

The main difference is in cases 2 and 3, where Solaris is calling
setcred for all modules that have auth entries.  It appears to be
ignoring the "sufficient" tag for the setcred call.  This is
arguably a bug in Solaris PAM.  The Solaris pam.conf man page does say:
     An authentication service module provides functionality
     to authenticate a user and set up user credentials.
That indicates that the "auth" line should control the setcred call,
and test 5 shows that it does.

Linux-PAM (both versions) seems to be starting its loop at the top
of the auth list for setcred calls and considering the first setcred
to be "sufficient".

Neither behavior is what you were hoping for, which would be
for libpam to remember which module(s) succeeded in the authenticate
call and only call setcred for those modules.

I think the philosophy of the PAM config file is that the
various entries are considered to be independent, and that the
framework does not make assumptions about the needs of the modules.
Thus the Linux-PAM behavior can be considered reasonable.

This behavior should, however, be documented!

I just read through the Linux-PAM HTML documentation and it doesn't
specify subtleties such as this, either.


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010120070403.43D3A12686>