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

relationship between pam_module and PAM chains



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?

-------------------

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.

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?


Reply to: