/******************************************************************************* * Return absolute path to file in either "regular" FCGI socket directory or * the dynamic directory. Result is allocated in pool p. */ const char * fcgi_util_socket_make_path_absolute(pool * const p, const char *const file, const int dynamic) { #ifdef APACHE2 if (ap_os_is_path_absolute(p, (char *) file)) #else if (ap_os_is_path_absolute(file)) #endif { return file; } else { const char * parent_dir = dynamic ? fcgi_dynamic_dir : fcgi_socket_dir; return (const char *) make_full_path(p, parent_dir, file); } }
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; }
static const char *vhost_alias_set(cmd_parms *cmd, void *dummy, const char *map) { mva_sconf_t *conf; mva_mode_e mode, *pmode; const char **pmap; const char *p; conf = (mva_sconf_t *) ap_get_module_config(cmd->server->module_config, &vhost_alias_module); /* there ought to be a better way of doing this */ if (&vhost_alias_set_doc_root_ip == cmd->info) { mode = VHOST_ALIAS_IP; pmap = &conf->doc_root; pmode = &conf->doc_root_mode; } else if (&vhost_alias_set_cgi_root_ip == cmd->info) { mode = VHOST_ALIAS_IP; pmap = &conf->cgi_root; pmode = &conf->cgi_root_mode; } else if (&vhost_alias_set_doc_root_name == cmd->info) { mode = VHOST_ALIAS_NAME; pmap = &conf->doc_root; pmode = &conf->doc_root_mode; } else if (&vhost_alias_set_cgi_root_name == cmd->info) { mode = VHOST_ALIAS_NAME; pmap = &conf->cgi_root; pmode = &conf->cgi_root_mode; } else { return "INTERNAL ERROR: unknown command info"; } if (!ap_os_is_path_absolute(cmd->pool, map)) { if (strcasecmp(map, "none")) { return "format string must be an absolute path, or 'none'"; } *pmap = NULL; *pmode = VHOST_ALIAS_NONE; return NULL; } /* sanity check */ p = map; while (*p != '\0') { if (*p++ != '%') { continue; } /* we just found a '%' */ if (*p == 'p' || *p == '%') { ++p; continue; } /* optional dash */ if (*p == '-') { ++p; } /* digit N */ if (apr_isdigit(*p)) { ++p; } else { return "syntax error in format string"; } /* optional plus */ if (*p == '+') { ++p; } /* do we end here? */ if (*p != '.') { continue; } ++p; /* optional dash */ if (*p == '-') { ++p; } /* digit M */ if (apr_isdigit(*p)) { ++p; } else { return "syntax error in format string"; } /* optional plus */ if (*p == '+') { ++p; } } *pmap = map; *pmode = mode; return NULL; }
static const char *set_user_dir(cmd_parms *cmd, void *dummy, char *arg) { userdir_config *s_cfg; char *username; const char *usernames = arg; char *kw = ap_getword_conf(cmd->pool, &usernames); table *usertable; s_cfg = (userdir_config *) ap_get_module_config(cmd->server->module_config, &userdir_module); /* * Let's do the comparisons once. */ if ((!strcasecmp(kw, "disable")) || (!strcasecmp(kw, "disabled"))) { /* * If there are no usernames specified, this is a global disable - we * need do no more at this point than record the fact. */ if (strlen(usernames) == 0) { s_cfg->globally_disabled = 1; return NULL; } usertable = s_cfg->disabled_users; } else if ((!strcasecmp(kw, "enable")) || (!strcasecmp(kw, "enabled"))) { /* * The "disable" keyword can stand alone or take a list of names, but * the "enable" keyword requires the list. Whinge if it doesn't have * it. */ if (strlen(usernames) == 0) { return "UserDir \"enable\" keyword requires a list of usernames"; } usertable = s_cfg->enabled_users; } else { /* * If the first (only?) value isn't one of our keywords, look at each * config 'word' for validity and copy the entire arg to the userdir * if all paths are valid. */ const char *userdirs = arg; while (*userdirs) { char *thisdir = ap_getword_conf(cmd->pool, &userdirs); if (!ap_os_is_path_absolute(thisdir) && !strchr(thisdir, ':')) { #if defined(WIN32) || defined(NETWARE) return "UserDir must specify an absolute redirect " "or absolute file path"; #else if (strchr(thisdir, '*')) { return "UserDir cannot specify '*' substitution within " "a relative path"; } #endif } } s_cfg->userdir = ap_pstrdup(cmd->pool, arg); #if defined(WIN32) || defined(OS2) || defined(NETWARE) /* These are incomplete paths, so we cannot canonicalize them yet. * but any backslashes will confuse the parser, later, so simply * change them to slash form. */ arg = s_cfg->userdir; while (arg = strchr(arg, '\\')) { *(arg++) = '/'; } #endif return NULL; } /* * Now we just take each word in turn from the command line and add it to * the appropriate table. */ while (*usernames) { username = ap_getword_conf(cmd->pool, &usernames); ap_table_setn(usertable, username, kw); } return NULL; }
static int translate_userdir(request_rec *r) { void *server_conf = r->server->module_config; const userdir_config *s_cfg = (userdir_config *) ap_get_module_config(server_conf, &userdir_module); char *name = r->uri; const char *userdirs = s_cfg->userdir; const char *w, *dname; char *redirect; struct stat statbuf; /* * If the URI doesn't match our basic pattern, we've nothing to do with * it. */ if ((s_cfg->userdir == NULL) || (name[0] != '/') || (name[1] != '~')) { return DECLINED; } dname = name + 2; w = 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 ((w[0] == '\0') || ((w[1] == '.') && ((w[2] == '\0') || ((w[2] == '.') && (w[3] == '\0'))))) { return DECLINED; } /* * Nor if there's an username but it's in the disabled list. */ if (ap_table_get(s_cfg->disabled_users, w) != 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 && (ap_table_get(s_cfg->enabled_users, w) == 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; int is_absolute = ap_os_is_path_absolute(userdir); if (strchr(userdir, '*')) { /* token '*' embedded: */ char *x = ap_getword(r->pool, &userdir, '*'); if (is_absolute) { /* token '*' within absolute path * serves [UserDir arg-pre*][user][UserDir arg-post*] * /somepath/ * /somedir + /~smith -> /somepath/smith/somedir */ filename = ap_pstrcat(r->pool, x, w, userdir, NULL); } else if (strchr(x, ':')) { /* token '*' within a redirect path * serves [UserDir arg-pre*][user][UserDir arg-post*] * http://server/user/ * + /~smith/foo -> * http://server/user/smith/foo */ redirect = ap_pstrcat(r->pool, x, w, userdir, dname, NULL); ap_table_setn(r->headers_out, "Location", redirect); return REDIRECT; } else { /* Not a redirect, not an absolute path, '*' token: * serves [homedir]/[UserDir arg] * something/ * /public_html * Shouldn't happen, we trap for this in set_user_dir */ return DECLINED; } } else if (is_absolute) { /* An absolute path, no * token: * serves [UserDir arg]/[user] * /home + /~smith -> /home/smith */ if (userdir[strlen(userdir) - 1] == '/') filename = ap_pstrcat(r->pool, userdir, w, NULL); else filename = ap_pstrcat(r->pool, userdir, "/", w, NULL); } else if (strchr(userdir, ':')) { /* A redirect, not an absolute path, no * token: * serves [UserDir arg]/[user][dname] * http://server/ + /~smith/foo -> http://server/smith/foo */ if (userdir[strlen(userdir) - 1] == '/') { redirect = ap_pstrcat(r->pool, userdir, w, dname, NULL); } else { redirect = ap_pstrcat(r->pool, userdir, "/", w, dname, NULL); } ap_table_setn(r->headers_out, "Location", redirect); return REDIRECT; } else { /* Not a redirect, not an absolute path, no * token: * serves [homedir]/[UserDir arg] * e.g. /~smith -> /home/smith/public_html */ #if defined(WIN32) || defined(NETWARE) /* Need to figure out home dirs on NT and NetWare * Shouldn't happen here, though, we trap for this in set_user_dir */ return DECLINED; #else /* WIN32 & NetWare */ struct passwd *pw; if ((pw = getpwnam(w))) { #ifdef OS2 /* Need to manually add user name for OS/2 */ filename = ap_pstrcat(r->pool, pw->pw_dir, w, "/", userdir, NULL); #else filename = ap_pstrcat(r->pool, pw->pw_dir, "/", userdir, NULL); #endif } #endif /* WIN32 & NetWare */ } /* * 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 || stat(filename, &statbuf) != -1)) { r->filename = ap_pstrcat(r->pool, filename, dname, NULL); /* 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; } return OK; } } return DECLINED; }
static int sqlalias_redir(request_rec *r) { MYSQL *dblink = NULL; server_rec *s = r->server; sqlalias_conf_t *s_cfg = (sqlalias_conf_t *) ap_get_module_config(s->module_config, &sqlalias_module); if (r->uri[0] != '/' && r->uri[0] != '\0') { return DECLINED; } else if(!s_cfg->enable || sqlalias_filter(r, s_cfg->filters) == FILTERED_URI || !(dblink = sqlalias_dbconnect(r->server, s_cfg))) { return DECLINED; } else { MYSQL_RES *result = NULL; MYSQL_ROW row; char *query = NULL; int found = 0; int response = 0; const char *ccp; int uri_length = strlen(r->uri); char *uri = (char *) malloc(sizeof(char) * (uri_length * 2 + 1)); strcpy(uri, r->uri); #ifndef SQLALIAS_PERFECT_MATCH if (uri_length > 1 && uri[uri_length-1] == '/') { uri[uri_length-1] = '\0'; uri_length--; } #endif /* SQLALIAS_PERFECT_MATCH */ mysql_real_escape_string(dblink, uri, uri, uri_length); query = apr_psprintf(r->pool, s_cfg->db_query, uri); free(uri); if(mysql_real_query(dblink, query, strlen(query))) { ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r->server, "sqlalias: %s.", mysql_error(dblink)); #ifdef SQLALIAS_USE_PCONNECT apr_thread_mutex_unlock(sqlalias_mutex); #else DEBUG_MSG(r->server, "sqlalias: Database connection closed. (pid:%d)", getpid()); mysql_close(dblink); #endif /* SQLALIAS_USE_PCONNECT */ return DECLINED; } if (!(result = mysql_store_result(dblink))) { ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r->server, "sqlalias: %s.", mysql_error(dblink)); #ifdef SQLALIAS_USE_PCONNECT apr_thread_mutex_unlock(sqlalias_mutex); #else DEBUG_MSG(r->server, "sqlalias: Database connection closed. (pid:%d)", getpid()); mysql_close(dblink); #endif /* SQLALIAS_USE_PCONNECT */ return DECLINED; } if((row = mysql_fetch_row(result))) { found = 1; response = (mysql_num_fields(result) > 1) ? atoi(row[1]) : DECLINED ; if(ap_is_HTTP_REDIRECT(response) || (is_absolute_uri(row[0]) && (response = HTTP_MOVED_TEMPORARILY))) { char *destination = apr_pstrdup(r->pool, row[0]); DEBUG_MSG(r->server, "sqlalias: %s redirect to %s (R=%d)", r->uri, destination, response?response:HTTP_OK); apr_table_setn(r->headers_out, "Location", destination); } else { DEBUG_MSG(r->server, "sqlalias: rewrite %s -> %s", r->uri, row[0]); /* the filename must be either an absolute local path or an * absolute local URL. */ if (*row[0] != '/' && !ap_os_is_path_absolute(r->pool, row[0])) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "sqlalias: Bad redirection for %s (%s)", r->uri, row[0]); response = HTTP_BAD_REQUEST; } else if ((ccp = ap_document_root(r)) != NULL) { char *q = NULL; r->uri = apr_pstrdup(r->pool, row[0]); q = strchr(r->uri, '?'); if (q != NULL) { char *olduri = NULL; olduri = apr_pstrdup(r->pool, r->uri); *q++ = '\0'; if(r->args) r->args = apr_pstrcat(r->pool, q, "&", r->args, NULL); else r->args = apr_pstrdup(r->pool, q); if(strlen(r->args) == 0) r->args = NULL; } } } #ifdef SQLALIAS_DEBUG } else { DEBUG_MSG(r->server, "sqlalias: No entry for %s", r->uri); #endif /* SQLALIAS_DEBUG */ } mysql_free_result(result); #ifdef SQLALIAS_USE_PCONNECT apr_thread_mutex_unlock(sqlalias_mutex); #else DEBUG_MSG(r->server, "sqlalias: Database connection closed. (pid:%d)", getpid()); mysql_close(dblink); #endif /* SQLALIAS_USE_PCONNECT */ if(found && response != 200) return response; } return DECLINED; }