[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: relationship between pam_module and PAM chains

Joe Pfeiffer <pfeiffer@cs.nmsu.edu> writes:

> My question takes enough explanation that I'll just start by asking it;
> afterwards I'll explain where it arises.
> I'm trying to understand how PAM works, and have a question regarding
> the relationship between PAM chains as defined in /etc/pam.d/* and
> fields in struct pam_module.
> When a module is specified in a configuration file, it is identified
> with one of the four chains:  auth, account, session, or password.
> When the module is written, the external calls to it are specified in a
> struct pam_module:
> struct pam_module {
>     const char *name;           /* Name of the module */
>     /* These are function pointers to the module's key functions.  */
>     int (*pam_sm_authenticate)(pam_handle_t *pamh, int flags,
>                                int argc, const char **argv);
>     int (*pam_sm_setcred)(pam_handle_t *pamh, int flags,
>                           int argc, const char **argv);
>     int (*pam_sm_acct_mgmt)(pam_handle_t *pamh, int flags,
>                             int argc, const char **argv);
>     int (*pam_sm_open_session)(pam_handle_t *pamh, int flags,
>                                int argc, const char **argv);
>     int (*pam_sm_close_session)(pam_handle_t *pamh, int flags,
>                                 int argc, const char **argv);
>     int (*pam_sm_chauthtok)(pam_handle_t *pamh, int flags,
>                             int argc, const char **argv);
> };
> As I understand it, when a program calls pam_authenticate(), the
> pam_sm_authenticate functions for all the modules specified in the auth
> chain for that program are called (subject to the various ways a chain
> can skip modules or exit early, of course).  Similarly, when the program
> is starting a session, it calls pam_open_session(), and every module in
> the session chain has its pam_sm_open_session() function.
> It's also my understanding that only the functions specified for a chain
> are called -- so if a module is specified as being in the auth chain but
> not the session chain (for instance), then when the program calls
> pam_authenticate() its pam_sm_authenticate() function is called, but
> when the program calls pam_open_session() its pam_sm_open_session() is
> not (even if it has one).
> So where I'm confused is with pam_setcred().  When the program calls
> pam_setcred(), which modules' pam_sm_setcred() functions get called?
> Are they associated with one of the chains, and if so, which one?

Look at the "What is expected of a module" section in the pam manual.
pam_sm_authenticate and pam_sm_setcred are both called for the auth
chains.  That said, do you need pam_sm_setcred for your purpose below?

> -------------------
> So here's what I'm trying to do:  I'd like to use libpam_mount to mount
> an encfs filesystem when I login using ssh.  This is working just fine
> with console and gdm3 logins, but when I login using ssh my password
> doesn't get passed to libpam_mount so the mount fails.  From googling,
> it looks like many people before me have jumped down this particular
> rabbit hole, and if any have ever emerged successfully they haven't
> posted their results.

In a past life, I wrote a python module (using pam_python) to do this:

It's been a while since I wrote that, so the details are a bit fuzzy.
pam_sm_authenticate is called first, and it has to get the user's
password by calling pam_get_item(PAM_AUTHTOK).  This translates to line
146 in the source (accessing pamh.authtok translates to the
pam_get_item(PAM_AUTHTOK) call).

My pam_sm_setcred implementation is a do-nothing-return-success
function.  Apparently I did not need it.

If you're doing this as a learning exercise, great!  If not, consider
https://code.google.com/p/pam-encfs/ as well.

Note that if you are logging in with a public key, you will not be able
to do this (you don't get AUTHTOK).  This was the main reason I
eventually stopped using it, because I do not enable password
authentication for ssh.

> Looking at the pam chains for login, gdm, and sshd I was struck by
> things they did differently.  Notably, login contains the line (quoted
> material below is indented for clarity)
>     session       required   pam_env.so readenv=1
> which makes perfect sense to me, while sshd has
>     auth       required     pam_env.so # [1]
> which struck me very odd (as an aside, if somebody knows what the [1] is
> referring to I'd be grateful to have that explained as well!).  What
> does setting up environment variables have to do with authentication?
> I got curious enough that I got the source for pam_env, and found
>     pam_sm_authenticate (pam_handle_t *pamh UNUSED, int flags UNUSED,
>                          int argc UNUSED, const char **argv UNUSED)
>     {
>       return PAM_IGNORE;
>     }
>     PAM_EXTERN int
>     pam_sm_setcred (pam_handle_t *pamh, int flags UNUSED,
>                     int argc, const char **argv)
>     {
>       D(("Called"));
>       return handle_env (pamh, argc, argv);
>     }
>     PAM_EXTERN int
>     pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED,
>                      int argc, const char **argv)
>     {
>       D(("Called"));
>       return handle_env (pamh, argc, argv);
>     }
> So if sshd really ends up calling pam_env's pam_sm_authenticate, it
> doesn't get any environment variables.  Does putting a module in the
> auth chain register its pam_sm_setcred() with the pam_setcred() module?

sshd will also call pam_open_session, so it does not really matter
whether it calls pam_setcred also.

I'm not sure why you are suspecting problems with environment
variables.  See the manpage for pam_env for what it does.  It's just a
convenient way to (un)set environment variables from a variety of
sources (/etc/security/pam_env.conf being the default).


Reply to: