root/pam/pam_mkuserdir.c

Revision fa60e971dd54655f02b2112f3cec25c17880f4ce, 5.2 KB (checked in by Martin Collins <martin@…>, 10 months ago)

simple pam session to create userdir in base folder with permissions/user/group - modified from pam_mkhomedir

  • Property mode set to 100644
Line 
1/* PAM Make Home Dir module
2
3   This module will create a users home directory if it does not exist
4   when the session begins. This allows users to be present in central
5   database (such as nis, kerb or ldap) without using a distributed
6   file system or pre-creating a large number of directories.
7
8   Here is a sample /etc/pam.d/login file for Debian GNU/Linux
9   2.1:
10
11   auth       requisite  pam_securetty.so
12   auth       sufficient pam_ldap.so
13   auth       required   pam_unix.so
14   auth       optional   pam_group.so
15   auth       optional   pam_mail.so
16   account    requisite  pam_time.so
17   account    sufficient pam_ldap.so
18   account    required   pam_unix.so
19   session    required   pam_mkhomedir.so skel=/etc/skel/ umask=0022
20   session    required   pam_unix.so
21   session    optional   pam_lastlog.so
22   password   required   pam_unix.so
23
24   Released under the GNU LGPL version 2 or later
25   Originally written by Jason Gunthorpe <jgg@debian.org> Feb 1999
26   Structure taken from pam_lastlogin by Andrew Morgan
27     <morgan@parc.power.net> 1996
28 */
29
30// #include "config.h"
31
32#include <stdarg.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <fcntl.h>
36#include <unistd.h>
37#include <pwd.h>
38#include <grp.h>
39#include <errno.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <string.h>
43#include <dirent.h>
44#include <syslog.h>
45
46/*
47 * here, we make a definition for the externally accessible function
48 * in this file (this definition is required for static a module
49 * but strongly encouraged generally) it is used to instruct the
50 * modules include file to define the function prototypes.
51 */
52
53#define PAM_SM_SESSION
54
55#include <security/pam_modules.h>
56#include <security/_pam_macros.h>
57#include <security/pam_modutil.h>
58#include <security/pam_ext.h>
59
60
61/* argument parsing */
62#define MKHOMEDIR_DEBUG      020  /* keep quiet about things */
63#define MKHOMEDIR_QUIET      040  /* keep quiet about things */
64#define UNUSED
65
66static unsigned int Mask = 0777;
67static char SkelDir[BUFSIZ] = "/etc/skel"; /* THIS MODULE IS NOT THREAD SAFE */
68static char DestDir[BUFSIZ] = ""; /* THIS MODULE IS NOT THREAD SAFE */
69static char  UserId[BUFSIZ] = "";      /* THIS MODULE IS NOT THREAD SAFE */
70static char GroupId[BUFSIZ] = "";      /* THIS MODULE IS NOT THREAD SAFE */
71
72static int
73_pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv)
74{
75   int ctrl = 0;
76
77   /* does the appliction require quiet? */
78   if ((flags & PAM_SILENT) == PAM_SILENT)
79      ctrl |= MKHOMEDIR_QUIET;
80
81   /* step through arguments */
82   for (; argc-- > 0; ++argv)
83   {
84      if (!strcmp(*argv, "silent")) {
85   ctrl |= MKHOMEDIR_QUIET;
86      } else if (!strncmp(*argv,"mode=",5)) {
87   Mask = strtol(*argv+5,0,0);
88      } else if (!strncmp(*argv,"uid=",4)) {
89  strncpy(UserId,*argv+4,sizeof(UserId));
90  UserId[sizeof(UserId)-1] = '\0';
91      } else if (!strncmp(*argv,"gid=",4)) {
92  strncpy(GroupId,*argv+4,sizeof(GroupId));
93  GroupId[sizeof(GroupId)-1] = '\0';
94      } else if (!strncmp(*argv,"base=",5)) {
95  strncpy(DestDir,*argv+5,sizeof(DestDir));
96  DestDir[sizeof(DestDir)-1] = '\0';
97      } else {
98  pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
99      }
100   }
101
102   D(("ctrl = %o", ctrl));
103   return ctrl;
104}
105
106int create_dir (pam_handle_t * pamh, int ctrl,
107                const char *source, const char *dest)
108{
109   const struct passwd *pwd;
110   const struct group  *grp;
111   mode_t mode;
112   /* Get the password entry */
113   pwd = pam_modutil_getpwnam (pamh, UserId);
114   if (pwd == NULL)
115   {
116      pam_syslog(pamh, LOG_NOTICE, "couldn't identify user %s",UserId);
117      return PAM_USER_UNKNOWN;
118   }
119   grp = pam_modutil_getgrnam(pamh, GroupId);
120   if (grp == NULL)
121   {
122      pam_syslog(pamh, LOG_NOTICE, "couldn't identify gropu %s",GroupId);
123      return PAM_USER_UNKNOWN;
124   }
125
126  mode = umask(0);
127  if (mkdir (dest, Mask)  != 0 && errno != EEXIST)
128  {
129    pam_syslog(pamh, LOG_DEBUG, "unable to create directory %s:", dest);
130    return PAM_PERM_DENIED;
131  }
132  umask(mode);
133
134  if(chown(dest,pwd->pw_uid,grp->gr_gid) != 0)
135  {
136    pam_syslog(pamh, LOG_DEBUG, "unable to change permissions on directory %s", dest);
137    return PAM_PERM_DENIED;
138  }
139
140  return PAM_SUCCESS;
141}
142
143/* --- authentication management functions (only) --- */
144
145PAM_EXTERN int
146pam_sm_open_session (pam_handle_t *pamh, int flags, int argc,
147         const char **argv)
148{
149   int retval, ctrl;
150   const void *user;
151   struct stat St;
152
153   /* Parse the flag values */
154   ctrl = _pam_parse(pamh, flags, argc, argv);
155
156   /* Determine the user name so we can get the home directory */
157   retval = pam_get_item(pamh, PAM_USER, &user);
158   if (retval != PAM_SUCCESS || user == NULL || *(const char *)user == '\0')
159   {
160      pam_syslog(pamh, LOG_NOTICE, "user unknown");
161      return PAM_USER_UNKNOWN;
162   }
163
164   char home[BUFSIZ] = "";
165   strncpy(home, DestDir, strnlen(DestDir,BUFSIZ-1));
166   strncat(home, "/", 1);
167   strncat(home, user, strlen(user));
168   home[strnlen(home,BUFSIZ)] = '\0';
169
170   /* Stat the home directory, if something exists then we assume it is
171      correct and return a success*/
172   if (stat(home,&St) == 0)
173      return PAM_SUCCESS;
174
175   return create_dir(pamh, ctrl, SkelDir, home);
176}
177
178/* Ignore */
179PAM_EXTERN
180int pam_sm_close_session (pam_handle_t * pamh UNUSED, int flags UNUSED,
181        int argc UNUSED, const char **argv UNUSED)
182{
183   return PAM_SUCCESS;
184}
185
Note: See TracBrowser for help on using the browser.