[Samba] Create user home directory or user-own folder on samba server on first login to samba

Michael Heydon michaelh at jaswin.com.au
Wed Oct 22 00:17:35 GMT 2008


Русаков Денис wrote:
>   I'd like to create user home directory or user-own folder on samba server on first login to samba without using PAM
>   

I use this along with a "root preexec" (and "preexec close") setting on 
the homes share.

*Michael Heydon - IT Administrator *
michaelh at jaswin.com.au <mailto:michaelh at jaswin.com.au>

-------------- next part --------------
/*
 *  Program Name: smbmkhome
 *  Version: 1.0
 *  Author: Michael Heydon
 *  Purpose: This program is designed to be run by samba prior to a user
 *           accessing their home directory. Since the users are set up in LDAP
 *           it is possible (probable) that their home directory was not created
 *           when their account was. This program will create the user's home
 *           directory and fix ownership and permissions if necessary.
 * 
 *           The program should be called with 1 parameter
 * 
 *           smbmkhome <username>
 * 
 *           <username> is the user to create/fix the home directory for.
 * 
 *           smbmkhome will return: 0 - success
 *                                  1 - incorrect parameters
 *                                  2 - invalid user
 *                                  3 - home exists but is not a directory
 *                                  4 - mkdir/chown failed
 * 
 *  Notes: compile with "gcc -o smbmkhome smbmkhome.c"
 *         tested under slackware linux 10.2
 *         requires cpio to copy skel when creating a directory
 */

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>

void printUsage(char* argv0);
int createHomeDir(struct passwd* user, char* skel);
void fixPerms(struct passwd* user);

int main (int argc, char* argv[]) {

  char* skel = "/etc/skel";
  struct passwd* userpw = 0;
  struct stat dirstat;
  char* homedir = 0;
  int returnval = 0;

  if ( argc != 2 ) {
    printUsage(argv[0]);
    returnval = 1;
  } else {
    userpw = getpwnam(argv[1]);
    if ( userpw != 0 ) {
      homedir = userpw->pw_dir;
    } else {
      // Since this is unlikely to occur if the program is being called by
      // samba as I intended we will allow a little bit of user interaction
      // here.
      printf ("%s: User does not exist.\n", argv[0]);
      returnval = 2;
    }
  }

  if ( returnval == 0 ) 
    if ( stat(homedir, &dirstat) == 0 ) {

      if ( (dirstat.st_mode & S_IFMT) == S_IFDIR ) {

        // Make sure the user and the users primary group are the owners of the
        // home directory and make sure at least the user has RWX permissions.
        //
        // The last comparison isn't terrible intuitive it just happens that
        // the bitmask S_IRWXU is exactly equal to the bits we want set. Rather
        // than or'ing together the bits for RWX to get exactly the same value
        // I decided to use the mask itself.
        if ( (dirstat.st_uid != userpw->pw_uid) || \
             (dirstat.st_gid != userpw->pw_gid) || \
             ( (dirstat.st_mode & S_IRWXU) != S_IRWXU) )
          fixPerms(userpw);

      } else {

        // stat returned, meaning the home "directory" exists on the FS, but 
        // the st_mode variable indicates that its not a directory. Oops :/
        // We won't try and force things because this could be used by admins
        // to stop a particular user from having a home directory (guest users
        // etc).
        returnval = 3;

      }

    } else {
      // home directory does not exist at all, try and create it and chown it
      // to the user and their primary group. copy skel to the new home dir if
      // possible but dont worry if that bit fails.
      if ( ! createHomeDir(userpw, skel) == 0 )
        returnval=4;
    }

  return returnval;

}

void printUsage (char* argv0) {
  printf ("Usage: %s <username>\n\n", argv0);
  printf ("Create/fix a user's home directory (prior to accessing via samba).\n");
}

int createHomeDir(struct passwd* user, char* skel) {

  int returnval=0;
  char command[255];

  if ( (mkdir(user->pw_dir, 0755) == 0) ) {
    returnval=chown(user->pw_dir, user->pw_uid, user->pw_gid);
  } else {
    returnval=1;
  }

  if ( returnval == 0 ) {
    // Don't worry if this fails, the directory exists and is owned by the user
    // this is really just a courtesy.
    sprintf(command, "cd %s && find . -print | cpio -pd %s 2>&1 > /dev/null"
                                                         ,skel, user->pw_dir);
    system(command);
    sprintf(command, "chown -R %s. %s", user->pw_name, user->pw_dir);
    system(command);
  }

  return returnval;

}

void fixPerms(struct passwd* user) {

  // We don't return anything here, since the directory already exists its
  // possible that who ever created the directory set things up in such a way
  // that this function fails but the share works the way they want, we don't
  // want to tell samba to drop the user's connection just because their admin
  // is being wierd :)

  if ( (chmod(user->pw_dir, 0755) == 0) ) {
    chown(user->pw_dir, user->pw_uid, user->pw_gid);
  }

}


More information about the samba mailing list