Exemplo n.º 1
0
int create_homedir(TALLOC_CTX *mem_ctx,
                   const char *skeldir,
                   const char *homedir,
                   const char *username,
                   uid_t uid,
                   gid_t gid,
                   mode_t default_umask)
{
    int ret;

    selinux_file_context(homedir);

    ret = mkdir(homedir, 0);
    if (ret != 0) {
        ret = errno;
        DEBUG(1, ("Cannot create user's home directory: [%d][%s].\n",
                  ret, strerror(ret)));
        goto done;
    }

    ret = chown(homedir, uid, gid);
    if (ret != 0) {
        ret = errno;
        DEBUG(1, ("Cannot chown user's home directory: [%d][%s].\n",
                  ret, strerror(ret)));
        goto done;
    }

    ret = chmod(homedir, 0777 & ~default_umask);
    if (ret != 0) {
        ret = errno;
        DEBUG(1, ("Cannot chmod user's home directory: [%d][%s].\n",
                  ret, strerror(ret)));
        goto done;
    }

    reset_selinux_file_context();

    ret = copy_tree(skeldir, homedir, uid, gid);
    if (ret != EOK) {
        DEBUG(1, ("Cannot populate user's home directory: [%d][%s].\n",
                  ret, strerror(ret)));
        goto done;
    }

done:
    reset_selinux_file_context();
    return ret;
}
Exemplo n.º 2
0
int create_homedir(const char *skeldir,
                   const char *homedir,
                   uid_t uid,
                   gid_t gid,
                   mode_t default_umask)
{
    int ret;

    selinux_file_context(homedir);

    ret = copy_tree(skeldir, homedir, 0777 & ~default_umask, uid, gid);
    if (ret != EOK) {
        DEBUG(1, ("Cannot populate user's home directory: [%d][%s].\n",
                  ret, strerror(ret)));
        goto done;
    }

done:
    reset_selinux_file_context();
    return ret;
}
Exemplo n.º 3
0
/*
 * copy_tree - copy files in a directory tree
 *
 *	copy_tree() walks a directory tree and copies ordinary files
 *	as it goes.
 *
 *	When reset_selinux is enabled, extended attributes (and thus
 *	SELinux attributes) are not copied.
 *
 *	old_uid and new_uid are used to set the ownership of the copied
 *	files. Unless old_uid is set to -1, only the files owned by
 *	old_uid have their ownership changed to new_uid. In addition, if
 *	new_uid is set to -1, no ownership will be changed.
 *
 *	The same logic applies for the group-ownership and
 *	old_gid/new_gid.
 */
int copy_tree (const char *src_root, const char *dst_root,
               bool copy_root, bool reset_selinux,
               uid_t old_uid, uid_t new_uid,
               gid_t old_gid, gid_t new_gid)
{
    int err = 0;
    bool set_orig = false;
    struct DIRECT *ent;
    DIR *dir;

    if (copy_root) {
        struct stat sb;
        if (access (dst_root, F_OK) == 0) {
            return -1;
        }

        if (LSTAT (src_root, &sb) == -1) {
            return -1;
        }

        if (!S_ISDIR (sb.st_mode)) {
            fprintf (stderr,
                     "%s: %s is not a directory",
                     Prog, src_root);
            return -1;
        }

        return copy_entry (src_root, dst_root, reset_selinux,
                           old_uid, new_uid, old_gid, new_gid);
    }

    /*
     * Make certain both directories exist.  This routine is called
     * after the home directory is created, or recursively after the
     * target is created.  It assumes the target directory exists.
     */

    if (   (access (src_root, F_OK) != 0)
            || (access (dst_root, F_OK) != 0)) {
        return -1;
    }

    /*
     * Open the source directory and read each entry.  Every file
     * entry in the directory is copied with the UID and GID set
     * to the provided values.  As an added security feature only
     * regular files (and directories ...) are copied, and no file
     * is made set-ID.
     */
    dir = opendir (src_root);
    if (NULL == dir) {
        return -1;
    }

    if (src_orig == NULL) {
        src_orig = src_root;
        dst_orig = dst_root;
        set_orig = true;
    }
    while ((0 == err) && (ent = readdir (dir)) != NULL) {
        /*
         * Skip the "." and ".." entries
         */
        if ((strcmp (ent->d_name, ".") != 0) &&
                (strcmp (ent->d_name, "..") != 0)) {
            char *src_name;
            char *dst_name;
            size_t src_len = strlen (ent->d_name) + 2;
            size_t dst_len = strlen (ent->d_name) + 2;
            src_len += strlen (src_root);
            dst_len += strlen (dst_root);

            src_name = (char *) malloc (src_len);
            dst_name = (char *) malloc (dst_len);

            if ((NULL == src_name) || (NULL == dst_name)) {
                err = -1;
            } else {
                /*
                 * Build the filename for both the source and
                 * the destination files.
                 */
                (void) snprintf (src_name, src_len, "%s/%s",
                                 src_root, ent->d_name);
                (void) snprintf (dst_name, dst_len, "%s/%s",
                                 dst_root, ent->d_name);

                err = copy_entry (src_name, dst_name,
                                  reset_selinux,
                                  old_uid, new_uid,
                                  old_gid, new_gid);
            }
            if (NULL != src_name) {
                free (src_name);
            }
            if (NULL != dst_name) {
                free (dst_name);
            }
        }
    }
    (void) closedir (dir);

    if (set_orig) {
        src_orig = NULL;
        dst_orig = NULL;
        /* FIXME: clean links
         * Since there can be hardlinks elsewhere on the device,
         * we cannot check that all the hardlinks were found:
        assert (NULL == links);
         */
    }

#ifdef WITH_SELINUX
    /* Reset SELinux to create files with default contexts.
     * Note that the context is only reset on exit of copy_tree (it is
     * assumed that the program would quit without needing a restored
     * context if copy_tree failed previously), and that copy_tree can
     * be called recursively (hence the context is set on the
     * sub-functions of copy_entry).
     */
    if (reset_selinux_file_context () != 0) {
        err = -1;
    }
#endif				/* WITH_SELINUX */

    return err;
}
Exemplo n.º 4
0
/* The reason for not putting this into create_homedir
 * is better granularity when it comes to reporting error
 * messages and tracebacks in pysss
 */
int create_mail_spool(TALLOC_CTX *mem_ctx,
                      const char *username,
                      const char *maildir,
                      uid_t uid, gid_t gid)
{
    char *spool_file = NULL;
    int fd = -1;
    int ret;

    spool_file = talloc_asprintf(mem_ctx, "%s/%s", maildir, username);
    if (spool_file == NULL) {
        ret = ENOMEM;
        goto fail;
    }

    selinux_file_context(spool_file);

    fd = open(spool_file, O_CREAT | O_WRONLY | O_EXCL, 0);
    if (fd < 0) {
        ret = errno;
        DEBUG(1, ("Cannot open() the spool file: [%d][%s]\n",
                  ret, strerror(ret)));
        goto fail;
    }

    ret = fchmod(fd, 0600);
    if (ret != 0) {
        ret = errno;
        DEBUG(1, ("Cannot fchmod() the spool file: [%d][%s]\n",
                  ret, strerror(ret)));
        goto fail;
    }

    ret = fchown(fd, uid, gid);
    if (ret != 0) {
        ret = errno;
        DEBUG(1, ("Cannot fchown() the spool file: [%d][%s]\n",
                  ret, strerror(ret)));
        goto fail;
    }

    ret = fsync(fd);
    if (ret != 0) {
        ret = errno;
        DEBUG(1, ("Cannot fsync() the spool file: [%d][%s]\n",
                  ret, strerror(ret)));
    }

fail:
    if (fd >= 0) {
        ret = close(fd);
        if (ret != 0) {
            ret = errno;
            DEBUG(1, ("Cannot close() the spool file: [%d][%s]\n",
                      ret, strerror(ret)));
        }
    }

    reset_selinux_file_context();
    talloc_free(spool_file);
    return ret;
}