/*
 * pam_homedir: checks if the user home directory exists. If not, the module
 *              returns an error. Else it is a success. 
 *              (Useful for no-auto mountable /home)
 *
 * Made by: Patrick MARIE <mycroft@virgaria.org>
 *
 * As this module is mostly cut'n past from pam_mkhomedir, it is under GPL
 * restriction licence.
Here is the Makefile:
----((----
#!/bin/sh

rm -f *.o *.so
echo "Compiling pam_homedir.so"
gcc -g -D_GNU_SOURCE -D_REENTRANT -fPIC -O2 \
    -c -o pam_homedir.o pam_homedir.c 

ld -shared -o pam_homedir.so pam_homedir.o
ls -lh pam_homedir.so
----))----
 */
#define _GNU_SOURCE 1
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>

#define PAM_SM_SESSION

#include <security/pam_modules.h>
#include <security/_pam_macros.h>

/* some syslogging */
static void 
_log_err(int err, const char *format, ...)
{
  va_list args;

  va_start(args, format);
  openlog("PAM-homedir", LOG_CONS|LOG_PID, LOG_AUTH);
  vsyslog(err, format, args);
  va_end(args);
  closelog();
}

PAM_EXTERN int
pam_sm_open_session(pam_handle_t * pamh, int flags, int argc, 
		    const char **argv)
{
  int retval;
  const char *user;
  const struct passwd *pwd;
  struct stat St;

  /* 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 = getpwnam(user);
  if (pwd == NULL)
  {
    D(("couldn't identify user %s", user));
    return PAM_CRED_INSUFFICIENT;
  }

  /* Stat the home directory, if something exists then we assume it is
     correct and return a success. */
  if (stat(pwd->pw_dir,&St) == 0)
    return PAM_SUCCESS;

  return PAM_PERM_DENIED;
}

/* Ignore */
PAM_EXTERN int
pam_sm_close_session(pam_handle_t * pamh, int flags, int argc,
                     const char **argv)
{
  return PAM_SUCCESS;
}


