/* gets the homedir of the current user. Probably should take username as an argument */ MVMString * MVM_proc_gethomedir(MVMThreadContext *tc) { apr_uid_t userid = (apr_uid_t)MVM_proc_getuid(tc); MVMString *result; apr_status_t rv; char *namestring; apr_pool_t *tmp_pool; char *dirname; /* need a temporary pool */ if ((rv = apr_pool_create(&tmp_pool, POOL(tc))) != APR_SUCCESS) { MVM_exception_throw_apr_error(tc, rv, "Failed to get user name from uid: "); } if ((rv = apr_uid_name_get(&namestring, (apr_uid_t)userid, tmp_pool)) != APR_SUCCESS) { apr_pool_destroy(tmp_pool); MVM_exception_throw_apr_error(tc, rv, "Failed to get user name from uid: "); } if ((rv = apr_uid_homepath_get(&dirname, namestring, tmp_pool)) != APR_SUCCESS) { apr_pool_destroy(tmp_pool); MVM_exception_throw_apr_error(tc, rv, "Failed to get homedir: "); } result = MVM_string_utf8_decode(tc, tc->instance->VMString, dirname, strlen(dirname)); apr_pool_destroy(tmp_pool); return result; }
static void fail_userinfo(CuTest *tc) { apr_uid_t uid; apr_gid_t gid; apr_status_t rv; char *tmp; errno = 0; gid = uid = 9999999; tmp = NULL; rv = apr_uid_name_get(&tmp, uid, p); CuAssert(tc, "apr_uid_name_get should fail or " "return a user name", rv != APR_SUCCESS || tmp != NULL); errno = 0; tmp = NULL; rv = apr_gid_name_get(&tmp, gid, p); CuAssert(tc, "apr_gid_name_get should fail or " "return a group name", rv != APR_SUCCESS || tmp != NULL); gid = 424242; errno = 0; rv = apr_gid_get(&gid, "I_AM_NOT_A_GROUP", p); CuAssert(tc, "apr_gid_get should fail or " "set a group number", rv != APR_SUCCESS || gid == 424242); gid = uid = 424242; errno = 0; rv = apr_uid_get(&uid, &gid, "I_AM_NOT_A_USER", p); CuAssert(tc, "apr_gid_get should fail or " "set a user and group number", rv != APR_SUCCESS || uid == 424242 || gid == 4242442); errno = 0; tmp = NULL; rv = apr_uid_homepath_get(&tmp, "I_AM_NOT_A_USER", p); CuAssert(tc, "apr_uid_homepath_get should fail or " "set a path name", rv != APR_SUCCESS || tmp != NULL); }
static int translate_userdir(request_rec *r) { ap_conf_vector_t *server_conf; const userdir_config *s_cfg; const char *userdirs; const char *user, *dname; char *redirect; apr_finfo_t statbuf; /* * If the URI doesn't match our basic pattern, we've nothing to do with * it. */ if (r->uri[0] != '/' || r->uri[1] != '~') { return DECLINED; } server_conf = r->server->module_config; s_cfg = ap_get_module_config(server_conf, &userdir_module); userdirs = s_cfg->userdir; if (userdirs == NULL) { return DECLINED; } dname = r->uri + 2; user = ap_getword(r->pool, &dname, '/'); /* * The 'dname' funny business involves backing it up to capture the '/' * delimiting the "/~user" part from the rest of the URL, in case there * was one (the case where there wasn't being just "GET /~user HTTP/1.0", * for which we don't want to tack on a '/' onto the filename). */ if (dname[-1] == '/') { --dname; } /* * If there's no username, it's not for us. Ignore . and .. as well. */ if (user[0] == '\0' || (user[1] == '.' && (user[2] == '\0' || (user[2] == '.' && user[3] == '\0')))) { return DECLINED; } /* * Nor if there's an username but it's in the disabled list. */ if (apr_table_get(s_cfg->disabled_users, user) != NULL) { return DECLINED; } /* * If there's a global interdiction on UserDirs, check to see if this * name is one of the Blessed. */ if (s_cfg->globally_disabled == O_DISABLE && apr_table_get(s_cfg->enabled_users, user) == NULL) { return DECLINED; } /* * Special cases all checked, onward to normal substitution processing. */ while (*userdirs) { const char *userdir = ap_getword_conf(r->pool, &userdirs); char *filename = NULL, *prefix = NULL; apr_status_t rv; int is_absolute = ap_os_is_path_absolute(r->pool, userdir); if (ap_strchr_c(userdir, '*')) prefix = ap_getword(r->pool, &userdir, '*'); if (userdir[0] == '\0' || is_absolute) { if (prefix) { #ifdef HAVE_DRIVE_LETTERS /* * Crummy hack. Need to figure out whether we have been * redirected to a URL or to a file on some drive. Since I * know of no protocols that are a single letter, ignore * a : as the first or second character, and assume a file * was specified */ if (strchr(prefix + 2, ':')) #else if (strchr(prefix, ':') && !is_absolute) #endif /* HAVE_DRIVE_LETTERS */ { redirect = apr_pstrcat(r->pool, prefix, user, userdir, dname, NULL); apr_table_setn(r->headers_out, "Location", redirect); return HTTP_MOVED_TEMPORARILY; } else filename = apr_pstrcat(r->pool, prefix, user, userdir, NULL); } else filename = apr_pstrcat(r->pool, userdir, "/", user, NULL); } else if (prefix && ap_strchr_c(prefix, ':')) { redirect = apr_pstrcat(r->pool, prefix, user, dname, NULL); apr_table_setn(r->headers_out, "Location", redirect); return HTTP_MOVED_TEMPORARILY; } else { #if APR_HAS_USER char *homedir; if (apr_uid_homepath_get(&homedir, user, r->pool) == APR_SUCCESS) { filename = apr_pstrcat(r->pool, homedir, "/", userdir, NULL); } #else return DECLINED; #endif } /* * Now see if it exists, or we're at the last entry. If we are at the * last entry, then use the filename generated (if there is one) * anyway, in the hope that some handler might handle it. This can be * used, for example, to run a CGI script for the user. */ if (filename && (!*userdirs || ((rv = apr_stat(&statbuf, filename, APR_FINFO_MIN, r->pool)) == APR_SUCCESS || rv == APR_INCOMPLETE))) { r->filename = apr_pstrcat(r->pool, filename, dname, NULL); ap_set_context_info(r, apr_pstrmemdup(r->pool, r->uri, dname - r->uri), filename); /* XXX: Does this walk us around FollowSymLink rules? * When statbuf contains info on r->filename we can save a syscall * by copying it to r->finfo */ if (*userdirs && dname[0] == 0) r->finfo = statbuf; /* For use in the get_suexec_identity phase */ apr_table_setn(r->notes, "mod_userdir_user", user); return OK; } } return DECLINED; }
/* deprecated */ APR_DECLARE(apr_status_t) apr_get_home_directory(char **dirname, const char *username, apr_pool_t *p) { return apr_uid_homepath_get(dirname, username, p); }