aboutsummaryrefslogtreecommitdiff
path: root/modules/pam_mkhomedir/mkhomedir_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_mkhomedir/mkhomedir_helper.c')
-rw-r--r--modules/pam_mkhomedir/mkhomedir_helper.c382
1 files changed, 178 insertions, 204 deletions
diff --git a/modules/pam_mkhomedir/mkhomedir_helper.c b/modules/pam_mkhomedir/mkhomedir_helper.c
index c6e10288..58195788 100644
--- a/modules/pam_mkhomedir/mkhomedir_helper.c
+++ b/modules/pam_mkhomedir/mkhomedir_helper.c
@@ -29,266 +29,240 @@
static unsigned long u_mask = 0022;
static char skeldir[BUFSIZ] = "/etc/skel";
-/* Do the actual work of creating a home dir */
+static int create_homedir(const struct passwd *, mode_t, const char *,
+ const char *);
+
static int
-create_homedir(const struct passwd *pwd, mode_t dir_mode,
- const char *source, const char *dest)
+copy_entry(const struct passwd *pwd, mode_t dir_mode,
+ const char *source, const char *dest, struct dirent *dent)
{
char remark[BUFSIZ];
- DIR *d;
- struct dirent *dent;
+ int srcfd = -1, destfd = -1;
+ int res;
int retval = PAM_SESSION_ERR;
+ struct stat st;
+ char *newsource = NULL, *newdest = NULL;
- /* Create the new directory */
- if (mkdir(dest, 0700))
+ /* Determine what kind of file it is. */
+ if (asprintf(&newsource, "%s/%s", source, dent->d_name) < 0)
{
- if (errno == EEXIST)
- return PAM_SUCCESS;
- pam_syslog(NULL, LOG_ERR, "unable to create directory %s: %m", dest);
- return PAM_PERM_DENIED;
+ pam_syslog(NULL, LOG_CRIT, "asprintf failed for 'newsource'");
+ retval = PAM_BUF_ERR;
+ goto go_out;
}
- /* See if we need to copy the skel dir over. */
- if ((source == NULL) || (strlen(source) == 0))
+ if (lstat(newsource, &st) != 0)
{
retval = PAM_SUCCESS;
goto go_out;
}
- /* Scan the directory */
- d = opendir(source);
- if (d == NULL)
+ /* We'll need the new file's name. */
+ if (asprintf(&newdest, "%s/%s", dest, dent->d_name) < 0)
{
- pam_syslog(NULL, LOG_DEBUG, "unable to read directory %s: %m", source);
- retval = PAM_PERM_DENIED;
+ pam_syslog(NULL, LOG_CRIT, "asprintf failed for 'newdest'");
+ retval = PAM_BUF_ERR;
goto go_out;
}
- for (dent = readdir(d); dent != NULL; dent = readdir(d))
+ /* If it's a directory, recurse. */
+ if (S_ISDIR(st.st_mode))
{
- int srcfd;
- int destfd;
- int res;
- struct stat st;
- char *newsource = NULL, *newdest = NULL;
-
- /* Skip some files.. */
- if (strcmp(dent->d_name,".") == 0 ||
- strcmp(dent->d_name,"..") == 0)
- continue;
-
- /* Determine what kind of file it is. */
- if (asprintf(&newsource, "%s/%s", source, dent->d_name) < 0)
- {
- pam_syslog(NULL, LOG_CRIT, "asprintf failed for 'newsource'");
- retval = PAM_BUF_ERR;
- goto go_out;
- }
-
- if (lstat(newsource, &st) != 0)
- {
- free(newsource);
- continue;
- }
-
-
- /* We'll need the new file's name. */
- if (asprintf(&newdest, "%s/%s", dest, dent->d_name) < 0)
- {
- pam_syslog(NULL, LOG_CRIT, "asprintf failed for 'newdest'");
- free(newsource);
- retval = PAM_BUF_ERR;
- goto go_out;
- }
-
+ retval = create_homedir(pwd, dir_mode & (~u_mask), newsource, newdest);
+ goto go_out;
+ }
- /* If it's a directory, recurse. */
- if (S_ISDIR(st.st_mode))
+ /* If it's a symlink, create a new link. */
+ if (S_ISLNK(st.st_mode))
+ {
+ int pointedlen = 0;
+#ifndef PATH_MAX
+ char *pointed = NULL;
{
- retval = create_homedir(pwd, dir_mode & (~u_mask), newsource, newdest);
-
- free(newsource);
- free(newdest);
-
- if (retval != PAM_SUCCESS)
- {
- closedir(d);
- goto go_out;
- }
- continue;
+ int size = 100;
+
+ while (1)
+ {
+ pointed = malloc(size);
+ if (pointed == NULL)
+ {
+ retval = PAM_BUF_ERR;
+ goto go_out;
+ }
+ pointedlen = readlink(newsource, pointed, size);
+ if (pointedlen < 0) break;
+ if (pointedlen < size) break;
+ free(pointed);
+ size *= 2;
+ }
}
-
- /* If it's a symlink, create a new link. */
- if (S_ISLNK(st.st_mode))
- {
- int pointedlen = 0;
-#ifndef PATH_MAX
- char *pointed = NULL;
- {
- int size = 100;
-
- while (1) {
- pointed = malloc(size);
- if (pointed == NULL) {
- free(newsource);
- free(newdest);
- retval = PAM_BUF_ERR;
- goto go_out;
- }
- pointedlen = readlink(newsource, pointed, size);
- if (pointedlen < 0) break;
- if (pointedlen < size) break;
- free(pointed);
- size *= 2;
- }
- }
- if (pointedlen < 0)
- free(pointed);
- else
- pointed[pointedlen] = 0;
+ if (pointedlen < 0)
+ free(pointed);
+ else
+ pointed[pointedlen] = 0;
#else
- char pointed[PATH_MAX] = {};
+ char pointed[PATH_MAX] = {};
- pointedlen = readlink(newsource, pointed, sizeof(pointed) - 1);
+ pointedlen = readlink(newsource, pointed, sizeof(pointed) - 1);
#endif
- if (pointedlen >= 0) {
- if(symlink(pointed, newdest) != 0)
- {
- retval = errno == EEXIST ? PAM_SUCCESS : PAM_PERM_DENIED;
+ if (pointedlen >= 0)
+ {
+ if (symlink(pointed, newdest) != 0)
+ {
+ retval = errno == EEXIST ? PAM_SUCCESS : PAM_PERM_DENIED;
- if (retval != PAM_SUCCESS)
- pam_syslog(NULL, LOG_DEBUG,
- "unable to create link %s: %m", newdest);
- closedir(d);
+ if (retval != PAM_SUCCESS)
+ pam_syslog(NULL, LOG_DEBUG,
+ "unable to create link %s: %m", newdest);
#ifndef PATH_MAX
- free(pointed);
+ free(pointed);
#endif
- free(newsource);
- free(newdest);
- goto go_out;
- }
-
- if (lchown(newdest, pwd->pw_uid, pwd->pw_gid) != 0)
- {
- pam_syslog(NULL, LOG_DEBUG,
- "unable to change perms on link %s: %m", newdest);
- closedir(d);
+ goto go_out;
+ }
+
+ if (lchown(newdest, pwd->pw_uid, pwd->pw_gid) != 0)
+ {
+ pam_syslog(NULL, LOG_DEBUG,
+ "unable to change perms on link %s: %m", newdest);
#ifndef PATH_MAX
- free(pointed);
+ free(pointed);
#endif
- free(newsource);
- free(newdest);
- retval = PAM_PERM_DENIED;
- goto go_out;
- }
+ retval = PAM_PERM_DENIED;
+ goto go_out;
+ }
#ifndef PATH_MAX
- free(pointed);
+ free(pointed);
#endif
- }
- free(newsource);
- free(newdest);
- continue;
}
+ retval = PAM_SUCCESS;
+ goto go_out;
+ }
- /* If it's not a regular file, it's probably not a good idea to create
- * the new device node, FIFO, or whatever it is. */
- if (!S_ISREG(st.st_mode))
- {
- free(newsource);
- free(newdest);
- continue;
- }
+ /* If it's not a regular file, it's probably not a good idea to create
+ * the new device node, FIFO, or whatever it is. */
+ if (!S_ISREG(st.st_mode))
+ {
+ retval = PAM_SUCCESS;
+ goto go_out;
+ }
- /* Open the source file */
- if ((srcfd = open(newsource, O_RDONLY)) < 0 || fstat(srcfd, &st) != 0)
- {
- pam_syslog(NULL, LOG_DEBUG,
- "unable to open or stat src file %s: %m", newsource);
- if (srcfd >= 0)
- close(srcfd);
- closedir(d);
+ /* Open the source file */
+ if ((srcfd = open(newsource, O_RDONLY)) < 0 || fstat(srcfd, &st) != 0)
+ {
+ pam_syslog(NULL, LOG_DEBUG,
+ "unable to open or stat src file %s: %m", newsource);
+ retval = PAM_PERM_DENIED;
+ goto go_out;
+ }
- free(newsource);
- free(newdest);
+ /* Open the dest file */
+ if ((destfd = open(newdest, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0)
+ {
+ retval = errno == EEXIST ? PAM_SUCCESS : PAM_PERM_DENIED;
+ if (retval != PAM_SUCCESS)
+ pam_syslog(NULL, LOG_DEBUG,
+ "unable to open dest file %s: %m", newdest);
+ goto go_out;
+ }
- retval = PAM_PERM_DENIED;
- goto go_out;
- }
+ /* Set the proper ownership and permissions for the module. We make
+ the file a+w and then mask it with the set mask. This preserves
+ execute bits */
+ if (fchmod(destfd, (st.st_mode | 0222) & (~u_mask)) != 0 ||
+ fchown(destfd, pwd->pw_uid, pwd->pw_gid) != 0)
+ {
+ pam_syslog(NULL, LOG_DEBUG,
+ "unable to change perms on copy %s: %m", newdest);
+ retval = PAM_PERM_DENIED;
+ goto go_out;
+ }
- /* Open the dest file */
- if ((destfd = open(newdest, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0)
- {
- retval = errno == EEXIST ? PAM_SUCCESS : PAM_PERM_DENIED;
- if (retval != PAM_SUCCESS)
- pam_syslog(NULL, LOG_DEBUG,
- "unable to open dest file %s: %m", newdest);
- close(srcfd);
- closedir(d);
+ /* Copy the file */
+ do
+ {
+ res = pam_modutil_read(srcfd, remark, sizeof(remark));
- free(newsource);
- free(newdest);
- goto go_out;
- }
+ if (res == 0)
+ continue;
- /* Set the proper ownership and permissions for the module. We make
- the file a+w and then mask it with the set mask. This preserves
- execute bits */
- if (fchmod(destfd, (st.st_mode | 0222) & (~u_mask)) != 0 ||
- fchown(destfd, pwd->pw_uid, pwd->pw_gid) != 0)
+ if (res > 0)
{
- pam_syslog(NULL, LOG_DEBUG,
- "unable to change perms on copy %s: %m", newdest);
- close(srcfd);
- close(destfd);
- closedir(d);
+ if (pam_modutil_write(destfd, remark, res) == res)
+ continue;
+ }
- free(newsource);
- free(newdest);
+ /* If we get here, pam_modutil_read returned a -1 or
+ pam_modutil_write returned something unexpected. */
+ pam_syslog(NULL, LOG_DEBUG, "unable to perform IO: %m");
+ retval = PAM_PERM_DENIED;
+ goto go_out;
+ }
+ while (res != 0);
- retval = PAM_PERM_DENIED;
- goto go_out;
- }
+ go_out:
+ if (srcfd >= 0)
+ close(srcfd);
+ if (destfd >= 0)
+ close(destfd);
- /* Copy the file */
- do
- {
- res = pam_modutil_read(srcfd, remark, sizeof(remark));
+ free(newsource);
+ free(newdest);
- if (res == 0)
- continue;
+ return retval;
+}
- if (res > 0) {
- if (pam_modutil_write(destfd, remark, res) == res)
- continue;
- }
+/* Do the actual work of creating a home dir */
+static int
+create_homedir(const struct passwd *pwd, mode_t dir_mode,
+ const char *source, const char *dest)
+{
+ DIR *d = NULL;
+ struct dirent *dent;
+ int retval = PAM_SESSION_ERR;
- /* If we get here, pam_modutil_read returned a -1 or
- pam_modutil_write returned something unexpected. */
- pam_syslog(NULL, LOG_DEBUG, "unable to perform IO: %m");
- close(srcfd);
- close(destfd);
- closedir(d);
+ /* Create the new directory */
+ if (mkdir(dest, 0700))
+ {
+ if (errno == EEXIST)
+ return PAM_SUCCESS;
+ pam_syslog(NULL, LOG_ERR, "unable to create directory %s: %m", dest);
+ return PAM_PERM_DENIED;
+ }
- free(newsource);
- free(newdest);
+ /* See if we need to copy the skel dir over. */
+ if ((source == NULL) || (strlen(source) == 0))
+ {
+ retval = PAM_SUCCESS;
+ goto go_out;
+ }
- retval = PAM_PERM_DENIED;
- goto go_out;
- }
- while (res != 0);
- close(srcfd);
- close(destfd);
+ /* Scan the directory */
+ d = opendir(source);
+ if (d == NULL)
+ {
+ pam_syslog(NULL, LOG_DEBUG, "unable to read directory %s: %m", source);
+ retval = PAM_PERM_DENIED;
+ goto go_out;
+ }
- free(newsource);
- free(newdest);
+ for (dent = readdir(d); dent != NULL; dent = readdir(d))
+ {
+ /* Skip some files.. */
+ if (strcmp(dent->d_name,".") == 0 ||
+ strcmp(dent->d_name,"..") == 0)
+ continue;
+ retval = copy_entry(pwd, dir_mode, source, dest, dent);
+ if (retval != PAM_SUCCESS)
+ goto go_out;
}
- closedir(d);
retval = PAM_SUCCESS;
go_out:
+ if (d != NULL)
+ closedir(d);
if (chmod(dest, dir_mode) != 0 ||
chown(dest, pwd->pw_uid, pwd->pw_gid) != 0)