예제 #1
0
파일: mkhome.c 프로젝트: Distrotech/proftpd
static int copy_symlink(pool *p, const char *src_dir, const char *src_path,
    const char *dst_dir, const char *dst_path, uid_t uid, gid_t gid) {
  char *link_path = pcalloc(p, PR_TUNABLE_BUFFER_SIZE);
  int len;

  len = pr_fsio_readlink(src_path, link_path, PR_TUNABLE_BUFFER_SIZE-1);
  if (len < 0) {
    pr_log_pri(PR_LOG_WARNING, "CreateHome: error reading link '%s': %s",
      src_path, strerror(errno));
    return -1;
  }
  link_path[len] = '\0';

  /* If the target of the link lies within the src path, rename that portion
   * of the link to be the corresponding part of the dst path.
   */
  if (strncmp(link_path, src_dir, strlen(src_dir)) == 0) {
    link_path = pdircat(p, dst_dir, link_path + strlen(src_dir), NULL);
  }

  if (pr_fsio_symlink(link_path, dst_path) < 0) {
    pr_log_pri(PR_LOG_WARNING, "CreateHome: error symlinking '%s' to '%s': %s",
      link_path, dst_path, strerror(errno));
    return -1;
  }

  /* Make sure the new symlink has the proper ownership. */
  if (pr_fsio_chown(dst_path, uid, gid) < 0) {
    pr_log_pri(PR_LOG_WARNING, "CreateHome: error chown'ing '%s' to %u/%u: %s",
      dst_path, (unsigned int) uid, (unsigned int) gid, strerror(errno));
  }

  return 0; 
}
예제 #2
0
파일: mkhome.c 프로젝트: proftpd/proftpd
static int create_dir(const char *dir, uid_t uid, gid_t gid,
    mode_t mode) {
  mode_t prev_mask;
  struct stat st;
  int res = -1;

  pr_fs_clear_cache2(dir);
  res = pr_fsio_stat(dir, &st);

  if (res == -1 &&
      errno != ENOENT) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_WARNING, "error checking '%s': %s", dir,
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  /* The directory already exists. */
  if (res == 0) {
    pr_trace_msg(trace_channel, 8, "'%s' already exists", dir);
    pr_log_debug(DEBUG3, "CreateHome: '%s' already exists", dir);
    return 0;
  }

  /* The given mode is absolute, not subject to any Umask setting. */
  prev_mask = umask(0);

  if (pr_fsio_mkdir(dir, mode) < 0) {
    int xerrno = errno;

    umask(prev_mask);
    pr_log_pri(PR_LOG_WARNING, "error creating '%s': %s", dir,
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  umask(prev_mask);

  if (pr_fsio_chown(dir, uid, gid) < 0) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_WARNING, "error setting ownership of '%s': %s", dir,
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  pr_trace_msg(trace_channel, 8, "directory '%s' created", dir);
  pr_log_debug(DEBUG6, "CreateHome: directory '%s' created", dir);
  return 0;
}
예제 #3
0
파일: mkhome.c 프로젝트: Distrotech/proftpd
/* srcdir is to be considered a "skeleton" directory, in the manner of
 * /etc/skel, and destdir is a user's newly created home directory that needs
 * to be populated with the files in srcdir.
 */
static int copy_dir(pool *p, const char *src_dir, const char *dst_dir,
    uid_t uid, gid_t gid) {
  DIR *dh = NULL;
  struct dirent *dent = NULL;

  dh = opendir(src_dir);
  if (dh == NULL) {
    pr_log_pri(PR_LOG_WARNING, "CreateHome: error copying '%s' skel files: %s",
      src_dir, strerror(errno));
    return -1;
  }

  while ((dent = readdir(dh)) != NULL) {
    struct stat st;
    char *src_path, *dst_path;

    pr_signals_handle();

    /* Skip "." and ".." */
    if (strncmp(dent->d_name, ".", 2) == 0 ||
        strncmp(dent->d_name, "..", 3) == 0) {
      continue;
    }

    src_path = pdircat(p, src_dir, dent->d_name, NULL);
    dst_path = pdircat(p, dst_dir, dent->d_name, NULL);

    if (pr_fsio_lstat(src_path, &st) < 0) {
      pr_log_debug(DEBUG3, "CreateHome: unable to stat '%s' (%s), skipping",
        src_path, strerror(errno));
      continue;
    }

    /* Is this path to a directory? */
    if (S_ISDIR(st.st_mode)) {
      create_dir(dst_path, uid, gid, st.st_mode);
      copy_dir(p, src_path, dst_path, uid, gid);
      continue;

    /* Is this path to a regular file? */
    } else if (S_ISREG(st.st_mode)) {
      mode_t dst_mode = st.st_mode;

      /* Make sure to prevent S{U,G}ID permissions on target files. */

      if (dst_mode & S_ISUID)
        dst_mode &= ~S_ISUID;

      if (dst_mode & S_ISGID)
        dst_mode &= ~S_ISGID;

      (void) pr_fs_copy_file(src_path, dst_path);

      /* Make sure the destination file has the proper ownership and mode. */
      if (pr_fsio_chown(dst_path, uid, gid) < 0) {
        pr_log_pri(PR_LOG_WARNING, "CreateHome: error chown'ing '%s' "
          "to %u/%u: %s", dst_path, (unsigned int) uid, (unsigned int) gid,
          strerror(errno));
      }

      if (pr_fsio_chmod(dst_path, dst_mode) < 0) {
        pr_log_pri(PR_LOG_WARNING, "CreateHome: error chmod'ing '%s' to "
          "%04o: %s", dst_path, (unsigned int) dst_mode, strerror(errno));
      }

      continue;

    /* Is this path a symlink? */
    } else if (S_ISLNK(st.st_mode)) {

      copy_symlink(p, src_dir, src_path, dst_dir, dst_path, uid, gid);
      continue;

    /* All other file types are skipped */
    } else {
      pr_log_debug(DEBUG3, "CreateHome: skipping skel file '%s'", src_path);
      continue;
    }
  }

  closedir(dh);
  return 0;
}