LtspPersistentHome

Differences between revisions 11 and 12
Revision 11 as of 2006-11-07 05:33:39
Size: 5463
Editor: dsl-241-210-73
Comment:
Revision 12 as of 2006-11-07 20:51:41
Size: 9263
Editor: 207
Comment:
Deletions are marked like this. Additions are marked like this.
Line 15: Line 15:
Edubuntu with LTSP is enjoying much success in schools, especially in third world countries where the cost of a full function PC plus software plus support may exceed a teacher's monthly or even yearly salary. Universities and colleges in these countries also struggle to fund adequate PC labs for the use of students, which impacts on teaching. Edubuntu with LTSP could make a great contribution in tertiary education, but we need to recognise that many students at colleges, and even some at schools, have some access to computers at home, in libraries, and elsewhere. If they can only access their home directories when they are on school or college premises then they are less able to exploit any other computer resources to do homework, projects, or research. As well, some systems administrators of public systems (say, for instance, libraries), may not want to have to manage home directories for users. This would provide the perfect oportunity for library patrons to have a persistent home directory. Maintaining permanent home directories on an LTSP server may not be a desireable option for some administrators. For instance, in a public walk-up library terminal, where userids could be based off your library patron number, keeping the home directory around after the user logs out will be a management problem that the administrator won't want.
Line 24: Line 24:
 * ltsp-server-standalone
   * dependency on libpam_mount, libpam_script
 * libpam-modules
Line 51: Line 50:
However, while "complete", in the sense that it will provide a persistent home directory, it relies on a fuse filesystem that doesn't exist as of yet, as well as some fairly intrusive changes to the LTSP management process. So, a nice intermediate step would be to have proper temporary home directories.

 * The user's home directory is set to a special home root, i.e. /tmphome
 * When the user logs in, his or her home directory is automatically created.
 * The user then uses the computer as normal, including standard LTSP local device access to store their documents on their USB stick.
 * When the user logs out, their home directory is automatically removed.

The pam module pam_mkhomedir will MAKE the homedirectory, however, the pam_sm_close_session function in the module currently simply returns PAM_SUCCESS. What we'd like to do is modify pam_mkhomedir in the following way:

 * have a way on the pam module's command line to specify a tmphome parameter.
   * Without this parameter, pam_mkhomedir will behave as normal.
   * This parameter must be supplied a directory name under which temporary home directories will be created. '''THIS MUST BE A DIFFERENT HIERARCHY FROM /home'''
   * modify pam_sm_close_session to remove the home directory iff:
     * The home the tmphome value length is > 0
     * The home directory of the user starts with the tmphome hierachy
     * The users home directory exists.
Line 53: Line 69:
 * Design format for /etc/ltsp/persistent_homes
   * simple text file of userids
   * $HOME/.persistent_home simply has to exist.
 * package pam_script, write persistent_home checking scripts, promote to main.
 * Write fuse-filesystem:
   * fuseexmp.c, simple loopback filesystem.
   * Need to handle getattr, readdir, & link (soft and hard) system calls.
   * rest are passed through.
   * prototype in Python with python-fuse bindings. Rewrite in C if performance is a problem.
 * pam_mount, fuse-python need to be promoted to main.
 * Modify pam_mkhomedir.c with the additional functionality.
 * Don't modify common-session, leave things as normal.
 * Document the additional functionality in the packages documentation, and in the Edubuntu handbook, for LTSP administrators to set up as needed.
 * Send modifications upstream, with the intent of getting them included in pam.
Line 66: Line 76:
 * fuse filesystem will need:
   * name munging routines
   * dictionary for mapping realname to fakename, file attributes
      * Save this out to the disk in a pickle.
      * Some users will pull out their memory stick before logging out, so the filesystem should probably save the pickle periodically, if it has changed in the interim.
 {{{
--- pam-0.79/Linux-PAM/modules/pam_mkhomedir/pam_mkhomedir.c 2005-01-31 06:37:00.000000000 -0600
+++ pam-0.79-sbalneav/Linux-PAM/modules/pam_mkhomedir/pam_mkhomedir.c 2006-11-07 14:45:03.000000000 -0600
@@ -57,9 +57,11 @@
 /* argument parsing */
 #define MKHOMEDIR_DEBUG 020 /* keep quiet about things */
 #define MKHOMEDIR_QUIET 040 /* keep quiet about things */
+#define MKHOMEDIR_REMOVE 0200 /* Remove home dir on exit */
 
 static unsigned int UMask = 0022;
 static char SkelDir[BUFSIZ] = "/etc/skel"; /* THIS MODULE IS NOT THREAD SAFE */
+static char TmpHome[BUFSIZ] = "\0";
 
 /* some syslogging */
 static void _log_err(int err, const char *format, ...)
@@ -91,6 +93,10 @@
       } else if (!strncmp(*argv,"skel=",5)) {
   strncpy(SkelDir,*argv+5,sizeof(SkelDir));
   SkelDir[sizeof(SkelDir)-1] = '\0';
+ } else if (!strncmp(*argv,"tmphome=",5)) {
+ ctrl |= MKHOMEDIR_REMOVE;
+ strncpy(TmpHome,*argv+8,sizeof(TmpHome));
+ TmpHome[sizeof(TmpHome)-1] = '\0';
       } else {
   _log_err(LOG_ERR, "unknown option; %s", *argv);
       }
@@ -458,6 +464,42 @@
    return PAM_SUCCESS;
 }
 
+static int remove_homedir(pam_handle_t * pamh, int ctrl,
+ const struct passwd *pwd)
+{
+ int status;
+ pid_t child;
+ char *program;
+ char *null_env[] = { NULL };
+ char *remove_cmd[] = { "/bin/rm", "-r", "-f", pwd->pw_dir, NULL };
+
+ child = fork();
+
+ if (child == 0) {
+ execve(remove_cmd[0], remove_cmd, null_env);
+ _log_err(LOG_DEBUG, "execl() returned");
+ exit (1); /* exec should never return */
+ } else if (child > 0) {
+ if (waitpid(child, &status, 0) < 0) {
+ _log_err(LOG_DEBUG, "wait() failed");
+ exit(1);
+ }
+ } else if (child < 0) {
+ _log_err(LOG_DEBUG, "fork() failed");
+ exit(1);
+ }
+
+ if (!WIFEXITED(status)) {
+ _log_err(LOG_DEBUG, "execve() returned no status");
+ return PAM_SYSTEM_ERR;
+ }
+
+ if (WEXITSTATUS(status) != 0)
+ return PAM_SYSTEM_ERR;
+
+ return PAM_SUCCESS;
+}
+
 /* --- authentication management functions (only) --- */
 
 PAM_EXTERN
@@ -501,7 +543,42 @@
 int pam_sm_close_session(pam_handle_t * pamh, int flags, int argc
     ,const char **argv)
 {
- return PAM_SUCCESS;
+ int retval, ctrl, TmpHomelen;
+ const char *user;
+ const struct passwd *pwd;
+ struct stat St;
+
+ /* Parse the flag values */
+ ctrl = _pam_parse(flags, argc, argv);
+
+ /* Check and see if tmphome= has been specified. */
+ if ((ctrl & MKHOMEDIR_REMOVE) != MKHOMEDIR_REMOVE)
+ return PAM_SUCCESS;
+
+ /* Determine the user name so we can get the home directory */
+ retval = pam_get_item(pamh, PAM_USER, (const void **) &user);
+ if (retval != PAM_SUCCESS || user == NULL || *user == '\0')
+ {
+ _log_err(LOG_NOTICE, "user unknown");
+ return PAM_USER_UNKNOWN;
+ }
+
+ /* Get the password entry */
+ pwd = _pammodutil_getpwnam (pamh, user);
+ if (pwd == NULL)
+ {
+ D(("couldn't identify user %s", user));
+ return PAM_CRED_INSUFFICIENT;
+ }
+
+ TmpHomelen = strlen(TmpHome);
+
+ if ((TmpHomelen > 0) && /* TmpHome's not bogus */
+ (strncmp(pwd->pw_dir, TmpHome, TmpHomelen) == 0) &&
+ (stat(pwd->pw_dir,&St) == 0))
+ return remove_homedir(pamh,ctrl,pwd);
+ else
+ return PAM_SUCCESS;
 }
 
 #ifdef PAM_STATIC
}}}
Line 76: Line 195:
Administrator can add:

{{{session required pam_mkhomedir.so tmphome=/tmphome/ skel=/etc/skel/ umask=0077}}}

To their {{{/etc/pam.d/common-session}}} to use.
Line 79: Line 204:

Need more input from the rest of the LTSP team.

NOTE: This page is part of the Ubuntu Specification process. Please check the status and details in Launchpad before editing. If the spec is Approved then you should contact the Assignee, or another knowledgeable person, before making changes.

Summary

Rather than store their home directories up on a server, some users would like to plug in flash media, and run off their memory stick. This currently works on the live CD. We should look at getting this to work for LTSP thin clients as well.

Rationale

Maintaining permanent home directories on an LTSP server may not be a desireable option for some administrators. For instance, in a public walk-up library terminal, where userids could be based off your library patron number, keeping the home directory around after the user logs out will be a management problem that the administrator won't want.

Use cases

  • Joseph is studying journalism at a college. He gets an assignment to study and report on the employment opportunities that the growth of biofuel feedstock crops may offer to subsistence farmers. He starts developing his report on a memory stick inserted into a lab computer at college, then goes to the town library to access more information resources. He wants to further edit his report using a computer available within the library.

Scope

Affects:

  • libpam-modules

Design

Currently, the persistent home system on the live cd requires the user to reformat/repartition their usb stick with an EXT3 filesystem. We'd like to avoid this, for support reasons. This requires us to create another layer of filesystem.

We'll need a filesystem shim that will provide standard unix filesystem semantics on top of a vfat filesystem. Things we'll need to handle that a fat formatted memory stick don't have are:

  • proper times (utime, mtime, ctime) witout constant updates to the memory stick (so as not to wear out the flash)
  • long filenames/directories simulation with 8.3 real names.
  • permissions, user, and group auth.
  • symlink and hardlink emulation.

Overall process will look something like the following:

  • The user will have to pre-prepare the stick for use.
    • This will be simple. No reformatting will be required, the user just has to create the /pershome directory.
    • Perhaps a simple shell script using zenity can be created to facilitate this.
  • User plugs in media into the workstation before login.
  • User logs in.
  • the pam module pam_script will run, and determine from either /etc/ltsp/persistent_homes, or $HOME/.persistent_home, that the user wishes to have a USB persistent home dir.
  • pam_mount executes a ltspfs mount to /media/username, which mounts the vfat formatted media.
  • pam_mount then executes a layered mount of a fuse based filesystem that behaves much like the rockridge extentions for CD's, in that it maps long filenames and permissions (but not userid or groupids) into the corresponding files in a /pershome directory on the vfat media. This directory then is mounted onto $HOME for the user.
    • If there is no /pershome directory, then we pop up a dialogue box indicating that the /pershome directory hasn't been created, possibly with instructions on how to do it.
  • On logout, reverse unmounting is done. The libpam-mount module does this. NOT VERIFIED

However, while "complete", in the sense that it will provide a persistent home directory, it relies on a fuse filesystem that doesn't exist as of yet, as well as some fairly intrusive changes to the LTSP management process. So, a nice intermediate step would be to have proper temporary home directories.

  • The user's home directory is set to a special home root, i.e. /tmphome
  • When the user logs in, his or her home directory is automatically created.
  • The user then uses the computer as normal, including standard LTSP local device access to store their documents on their USB stick.
  • When the user logs out, their home directory is automatically removed.

The pam module pam_mkhomedir will MAKE the homedirectory, however, the pam_sm_close_session function in the module currently simply returns PAM_SUCCESS. What we'd like to do is modify pam_mkhomedir in the following way:

  • have a way on the pam module's command line to specify a tmphome parameter.
    • Without this parameter, pam_mkhomedir will behave as normal.
    • This parameter must be supplied a directory name under which temporary home directories will be created. THIS MUST BE A DIFFERENT HIERARCHY FROM /home

    • modify pam_sm_close_session to remove the home directory iff:
      • The home the tmphome value length is > 0

      • The home directory of the user starts with the tmphome hierachy
      • The users home directory exists.

Implementation

  • Modify pam_mkhomedir.c with the additional functionality.
  • Don't modify common-session, leave things as normal.
  • Document the additional functionality in the packages documentation, and in the Edubuntu handbook, for LTSP administrators to set up as needed.
  • Send modifications upstream, with the intent of getting them included in pam.

Code

  • --- pam-0.79/Linux-PAM/modules/pam_mkhomedir/pam_mkhomedir.c    2005-01-31 06:37:00.000000000 -0600
    +++ pam-0.79-sbalneav/Linux-PAM/modules/pam_mkhomedir/pam_mkhomedir.c   2006-11-07 14:45:03.000000000 -0600
    @@ -57,9 +57,11 @@
     /* argument parsing */
     #define MKHOMEDIR_DEBUG      020       /* keep quiet about things */
     #define MKHOMEDIR_QUIET      040       /* keep quiet about things */
    +#define MKHOMEDIR_REMOVE    0200       /* Remove home dir on exit */
     
     static unsigned int UMask = 0022;
     static char SkelDir[BUFSIZ] = "/etc/skel"; /* THIS MODULE IS NOT THREAD SAFE */
    +static char TmpHome[BUFSIZ] = "\0";
     
     /* some syslogging */
     static void _log_err(int err, const char *format, ...)
    @@ -91,6 +93,10 @@
           } else if (!strncmp(*argv,"skel=",5)) {
             strncpy(SkelDir,*argv+5,sizeof(SkelDir));
             SkelDir[sizeof(SkelDir)-1] = '\0';
    +      } else if (!strncmp(*argv,"tmphome=",5)) {
    +        ctrl |= MKHOMEDIR_REMOVE;
    +        strncpy(TmpHome,*argv+8,sizeof(TmpHome));
    +        TmpHome[sizeof(TmpHome)-1] = '\0';
           } else {
             _log_err(LOG_ERR, "unknown option; %s", *argv);
           }
    @@ -458,6 +464,42 @@
        return PAM_SUCCESS;
     }
     
    +static int remove_homedir(pam_handle_t * pamh, int ctrl,
    +                          const struct passwd *pwd)
    +{
    +   int status;
    +   pid_t child;
    +   char *program;
    +   char *null_env[] = { NULL };
    +   char *remove_cmd[] = { "/bin/rm", "-r", "-f",  pwd->pw_dir, NULL };
    +
    +   child = fork();
    +
    +   if (child == 0) {
    +      execve(remove_cmd[0], remove_cmd, null_env);
    +      _log_err(LOG_DEBUG, "execl() returned");
    +      exit (1);                 /* exec should never return */
    +   } else if (child > 0) {
    +      if (waitpid(child, &status, 0) < 0) {
    +         _log_err(LOG_DEBUG, "wait() failed");
    +         exit(1);
    +      }
    +   } else if (child < 0) {
    +      _log_err(LOG_DEBUG, "fork() failed");
    +      exit(1);
    +   }
    +
    +   if (!WIFEXITED(status)) {
    +      _log_err(LOG_DEBUG, "execve() returned no status");
    +      return PAM_SYSTEM_ERR;
    +   }
    +
    +   if (WEXITSTATUS(status) != 0)
    +      return PAM_SYSTEM_ERR;
    +
    +   return PAM_SUCCESS;
    +}
    +
     /* --- authentication management functions (only) --- */
     
     PAM_EXTERN
    @@ -501,7 +543,42 @@
     int pam_sm_close_session(pam_handle_t * pamh, int flags, int argc
                             ,const char **argv)
     {
    -   return PAM_SUCCESS;
    +   int retval, ctrl, TmpHomelen;
    +   const char *user;
    +   const struct passwd *pwd;
    +   struct stat St;
    +
    +   /* Parse the flag values */
    +   ctrl = _pam_parse(flags, argc, argv);
    +
    +   /* Check and see if tmphome= has been specified. */
    +   if ((ctrl & MKHOMEDIR_REMOVE) != MKHOMEDIR_REMOVE)
    +      return PAM_SUCCESS;
    +
    +   /* Determine the user name so we can get the home directory */
    +   retval = pam_get_item(pamh, PAM_USER, (const void **) &user);
    +   if (retval != PAM_SUCCESS || user == NULL || *user == '\0')
    +   {
    +      _log_err(LOG_NOTICE, "user unknown");
    +      return PAM_USER_UNKNOWN;
    +   }
    +
    +   /* Get the password entry */
    +   pwd = _pammodutil_getpwnam (pamh, user);
    +   if (pwd == NULL)
    +   {
    +      D(("couldn't identify user %s", user));
    +      return PAM_CRED_INSUFFICIENT;
    +   }
    +
    +   TmpHomelen = strlen(TmpHome);
    +
    +   if ((TmpHomelen > 0) &&             /* TmpHome's not bogus */
    +       (strncmp(pwd->pw_dir, TmpHome, TmpHomelen) == 0) &&
    +       (stat(pwd->pw_dir,&St) == 0))
    +      return remove_homedir(pamh,ctrl,pwd);
    +   else
    +      return PAM_SUCCESS;
     }
     
     #ifdef PAM_STATIC

Data preservation and migration

None.

Administrator can add:

session required        pam_mkhomedir.so tmphome=/tmphome/ skel=/etc/skel/ umask=0077

To their /etc/pam.d/common-session to use.

Unresolved issues

BoF agenda and discussion


CategorySpec

LtspPersistentHome (last edited 2009-07-24 03:07:01 by 201)