Example #1
0
/* Creates a the parent directory of the specified path securely */
int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
    int ret = -1;
    char *dir;

    if (!(dir = pa_parent_dir(fn)))
        goto finish;

    if (pa_make_secure_dir(dir, m, uid, gid) < 0)
        goto finish;

    ret = 0;

finish:
    pa_xfree(dir);
    return ret;
}
Example #2
0
static int change_user(void) {
    struct passwd *pw;
    struct group * gr;
    int r;

    /* This function is called only in system-wide mode. It creates a
     * runtime dir in /var/run/ with proper UID/GID and drops privs
     * afterwards. */

    if (!(pw = getpwnam(PA_SYSTEM_USER))) {
        pa_log(_("Failed to find user '%s'."), PA_SYSTEM_USER);
        return -1;
    }

    if (!(gr = getgrnam(PA_SYSTEM_GROUP))) {
        pa_log(_("Failed to find group '%s'."), PA_SYSTEM_GROUP);
        return -1;
    }

    pa_log_info(_("Found user '%s' (UID %lu) and group '%s' (GID %lu)."),
                PA_SYSTEM_USER, (unsigned long) pw->pw_uid,
                PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid);

    if (pw->pw_gid != gr->gr_gid) {
        pa_log(_("GID of user '%s' and of group '%s' don't match."), PA_SYSTEM_USER, PA_SYSTEM_GROUP);
        return -1;
    }

    if (!pa_streq(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH))
        pa_log_warn(_("Home directory of user '%s' is not '%s', ignoring."), PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH);

    if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid, true) < 0) {
        pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno));
        return -1;
    }

    if (pa_make_secure_dir(PA_SYSTEM_STATE_PATH, 0700, pw->pw_uid, gr->gr_gid, true) < 0) {
        pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_STATE_PATH, pa_cstrerror(errno));
        return -1;
    }

    /* We don't create the config dir here, because we don't need to write to it */

    if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) {
        pa_log(_("Failed to change group list: %s"), pa_cstrerror(errno));
        return -1;
    }

#if defined(HAVE_SETRESGID)
    r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid);
#elif defined(HAVE_SETEGID)
    if ((r = setgid(gr->gr_gid)) >= 0)
        r = setegid(gr->gr_gid);
#elif defined(HAVE_SETREGID)
    r = setregid(gr->gr_gid, gr->gr_gid);
#else
#error "No API to drop privileges"
#endif

    if (r < 0) {
        pa_log(_("Failed to change GID: %s"), pa_cstrerror(errno));
        return -1;
    }

#if defined(HAVE_SETRESUID)
    r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
#elif defined(HAVE_SETEUID)
    if ((r = setuid(pw->pw_uid)) >= 0)
        r = seteuid(pw->pw_uid);
#elif defined(HAVE_SETREUID)
    r = setreuid(pw->pw_uid, pw->pw_uid);
#else
#error "No API to drop privileges"
#endif

    if (r < 0) {
        pa_log(_("Failed to change UID: %s"), pa_cstrerror(errno));
        return -1;
    }

    pa_drop_caps();

    pa_set_env("USER", PA_SYSTEM_USER);
    pa_set_env("USERNAME", PA_SYSTEM_USER);
    pa_set_env("LOGNAME", PA_SYSTEM_USER);
    pa_set_env("HOME", PA_SYSTEM_RUNTIME_PATH);

    /* Relevant for pa_runtime_path() */
    if (!getenv("PULSE_RUNTIME_PATH"))
        pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);

    if (!getenv("PULSE_CONFIG_PATH"))
        pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);

    if (!getenv("PULSE_STATE_PATH"))
        pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);

    pa_log_info(_("Successfully changed user to \"" PA_SYSTEM_USER "\"."));

    return 0;
}