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:
https://bitbucket.org/kushal_kumaran/libpam-encfs-2/overview
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).
--
regards,
kushal
Reply to: