Anyone using Linux-PAM on 5.x?

Mikko Työläjärvi mbsd at pacbell.net
Sun Oct 5 10:39:16 PDT 2003


On Sat, 4 Oct 2003, Bill Campbell wrote:

> On Sat, Oct 04, 2003, Mikko Työläjärvi wrote:
> ...
> >Having had some experience writing pam modules on a number of
> >platforms, I whipped out my suite of pam test modules to have a look
> >at this incredbible breakage you speak of.  I mean, there is a
> >specification for pam after all.
>
> Could you suggest where to look for information on writing modules to
> handle session tasks?  I've looked at the PAM stuff superficially over the
> years, and would be very interested in doing something with the session
> modules to do things like automatically creating missing home directories
> with appropriate links to automounted directories.
>
> I haven't done much with this on FreeBSD yet since I need pam_ldap and
> nss_ldap support which only seems to be available in the 5.x tree.

Well, it isn't exactly rocket science, just a small matter of
programming.  The pam interface itself is not very complicated; any
decent programmer can pick it up in an afternoon.  The specification
can be downloaded from the OpenGroup, abd google will happily locate
lots of sample code of varying quality for you.  Modules aren't harder
to port than any other code, the actual pam bits are mostly the same,
modulo non-standard utility extensions, but those are usually trivial
to port, replace or re-implement.

One of the problems with pam is that there are very few guarantees on
the context the module will be called in will look like.  Will the uid
be zero, or that of a user? Will all phases of the module be called
from inside the same process?  Will the session be closed twice after
a fork?  Will the service name stay the same over all phases?

Trying to do anything more clever than verifying a password quickly
leads to a jungle of special cases (number of pamified applications
times number of platforms). Attempts at managing some kind of state
between modules or different callbacks in the same module are more
or less doomed to fail.

Anyhow, just for kicks I grabbed the pam_mkhomedir module from
RedHat9, and made it build on FreeBSD.  It involved fixing the usual
linuxisms (remove non-standard header files, add missing standard
header files), and adding some FreeBSD-isms, like the leading "dot."
used for template files.

A quick test with telnet shows that it seems to work, at least once :)

The test also illustrates how the interaction between application and
pam doesn't always work smoothly: the FreeBSD login program will
already have discovered there there is no home directory, printed an
error message and potentially denied access before the session modules
are invoked.

Thus there login messages contain:

 No home directory.
 Logging in with home = "/".
 Creating directory '/home/testguy'.

And then, as a band-aid, I threw in a chdir($HOME) in the session
module to avoid having the user end up in "/".

Patch and build instructions below. Comes with no warranty. Slippery
when wet.  May cause bodily injury. Will probably break with NFS
automounted home dirs. Etc...

   Enjoy,
   /Mikko

Build:
  fetch ftp://ftp.redhat.com/pub/redhat/linux/9/en/os/i386/SRPMS/pam-0.75-48.src.rpm
  rpm2cpio pam-0.75-48.src.rpm > pam-0.75-48.src.cpio
  cpio -id < pam-0.75-48.src.cpio
  tar jxf Linux-PAM-0.75.tar.bz2
  patch < pam-0.75-mkhomedir-recurse.patch
  cd Linux-PAM-0.75/modules/pam_mkhomedir
  patch < THIS_FILE
  cc -Wall -shared -fpic -o pam_mkhomedir.so pam_mkhomedir.c -lpam

Patch:
--- pam_mkhomedir.c.rh9	Sat Oct  4 22:10:49 2003
+++ pam_mkhomedir.c	Sat Oct  4 22:14:51 2003
@@ -39,6 +39,8 @@
 #include <stdio.h>
 #include <string.h>
 #include <dirent.h>
+#include <syslog.h>
+#include <limits.h>

 /*
  * here, we make a definition for the externally accessible function
@@ -50,14 +52,15 @@
 #define PAM_SM_SESSION

 #include <security/pam_modules.h>
-#include <security/_pam_macros.h>
+#include <security/pam_appl.h>
+#define D(x)

 /* argument parsing */
 #define MKHOMEDIR_DEBUG      020	/* keep quiet about things */
 #define MKHOMEDIR_QUIET      040	/* keep quiet about things */

 static unsigned int UMask = 0022;
-static char SkelDir[BUFSIZ] = "/etc/skel";
+static char SkelDir[BUFSIZ] = "/usr/share/skel";

 /* some syslogging */
 static void _log_err(int err, const char *format, ...)
@@ -151,15 +154,12 @@

       mesg[0] = &msg[0];
       msg[0].msg_style = PAM_TEXT_INFO;
-      msg[0].msg = remark;
+      msg[0].msg = (char *)remark;

       retval = converse(pamh, ctrl, 1, mesg, &resp);

       msg[0].msg = NULL;
-      if (resp)
-      {
-	 _pam_drop_reply(resp, 1);
-      }
+      free(resp);
    }
    else
    {
@@ -232,7 +232,8 @@
          continue;

       /* We'll need the new file's name. */
-      snprintf(newdest,sizeof(newdest),"%s/%s",dest,Dir->d_name);
+      snprintf(newdest,sizeof(newdest),"%s/%s",dest,Dir->d_name
+	       + (strncmp(Dir->d_name, "dot.", 4) == 0 ? 3 : 0));

       /* If it's a directory, recurse. */
       if (S_ISDIR(St.st_mode))
@@ -351,7 +352,10 @@
    if (stat(pwd->pw_dir,&St) == 0)
       return PAM_SUCCESS;

-   return create_homedir(pamh,ctrl,pwd,SkelDir,pwd->pw_dir);
+   retval = create_homedir(pamh,ctrl,pwd,SkelDir,pwd->pw_dir);
+   chdir(pwd->pw_dir); /* XXX */
+
+   return retval;
 }

 /* Ignore */


More information about the freebsd-questions mailing list