static mbox_req_cfg_t *get_req_conf(request_rec *r) { mbox_req_cfg_t *conf = ap_get_module_config(r->request_config, &mbox_module); const char *temp; if (conf) return conf; conf = apr_pcalloc(r->pool, sizeof(*conf)); temp = ap_strstr_c(r->uri, r->path_info); if (temp) conf->base_uri = apr_pstrmemdup(r->pool, r->uri, temp - r->uri); else conf->base_uri = r->uri; temp = ap_strstr_c(conf->base_uri, ".mbox"); /* 7 is length of "/yyyymm" */ if (temp && temp >= conf->base_uri + 7) { conf->base_path = apr_pstrmemdup(r->pool, conf->base_uri, temp - 7 - conf->base_uri); conf->base_name = ap_strrchr_c(conf->base_path, '/') + 1; } ap_set_module_config(r->request_config, &mbox_module, conf); return conf; }
static int req_mime_types(lua_State *L) { request_rec *r = CHECK_REQUEST_OBJECT(1); apr_pool_t *p = r->connection->base_server->process->pool; const char* resource_name = luaL_checkstring(L, 2); int set = lua_isnoneornil(L, 3) ? 0 : lua_toboolean(L, 3); apr_hash_t *mimes = NULL; apr_status_t rc = apr_pool_userdata_get((void**)&mimes, "mod_luaex", p); const char* fn, *ext, *fntmp; const char* type = NULL; if (rc == APR_SUCCESS && mimes) { if ((fn = ap_strrchr_c(resource_name, '/')) == NULL) { fn = resource_name; } else { ++fn; } /* Always drop the path leading up to the file name. */ /* The exception list keeps track of those filename components that * are not associated with extensions indicating metadata. * The base name is always the first exception (i.e., "txt.html" has * a basename of "txt" even though it might look like an extension). * Leading dots are considered to be part of the base name (a file named * ".png" is likely not a png file but just a hidden file called png). */ fntmp = fn; while (*fntmp == '.') fntmp++; fntmp = ap_strchr_c(fntmp, '.'); if (fntmp) { fn = fntmp + 1; ext = apr_pstrdup(r->pool, fn); } else { ext = apr_pstrdup(r->pool, fn); fn += strlen(fn); } if (set && (type = apr_hash_get(mimes, ext, APR_HASH_KEY_STRING)) != NULL) { ap_set_content_type(r, (char*) type); } } if (type) lua_pushstring(L, type); else lua_pushnil(L); return 1; }
static apr_status_t ap_compile_output_filter(ap_filter_t *filter, apr_bucket_brigade *input_brigade) { request_rec *request = filter->r; if ( ! request->filename) { return ap_pass_brigade(filter->next, input_brigade); } const char *resource_name; compile_config_t *directory_config = (compile_config_t*) ap_get_module_config(request->per_dir_config, &compile_module); compile_config_t *server_config = (compile_config_t*) ap_get_module_config(request->server->module_config, &compile_module); compile_config_t *config = compile_merge_config(request->pool, server_config, directory_config); if (config->use_path_info) { resource_name = apr_pstrcat(request->pool, request->filename, request->path_info, NULL); } else { resource_name = request->filename; } const char *filename; char *extension; filename = ap_strrchr_c(resource_name, '/'); if (filename == NULL) { filename = resource_name; } else { ++ filename; } extension = ap_getword(request->pool, &filename, '.'); while (*filename && (extension = ap_getword(request->pool, &filename, '.'))) { if (*extension == '\0') { continue; } ap_str_tolower(extension); if (config->extension_commands != NULL) { const compile_extension_config_t *extension_config = NULL; extension_config = (compile_extension_config_t*) apr_hash_get(config->extension_commands, extension, APR_HASH_KEY_STRING); if (extension_config != NULL && extension_config->command_line) { #ifdef _DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, request->server, "ap_compile_output_filter('%s')", apr_psprintf(request->pool, extension_config->command_line, resource_name)); #endif // TODO: http://svn.apache.org/repos/asf/httpd/httpd/tags/2.2.6/modules/experimental/mod_case_filter.c // Collect buckets, save to disk, run command line and tail-insert result ap_set_content_type(request, "text/html;charset=utf-8"); break; } } } return ap_pass_brigade(filter->next, input_brigade); }
static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, const char *var) { const char *ptr; char *result; X509_NAME_ENTRY *xsne; int i, j, n, idx = 0, raw = 0; apr_size_t varlen; ptr = ap_strrchr_c(var, '_'); if (ptr && ptr > var && strcmp(ptr + 1, "RAW") == 0) { var = apr_pstrmemdup(p, var, ptr - var); raw = 1; } /* if an _N suffix is used, find the Nth attribute of given name */ ptr = ap_strchr_c(var, '_'); if (ptr != NULL && strspn(ptr + 1, "0123456789") == strlen(ptr + 1)) { idx = atoi(ptr + 1); varlen = ptr - var; } else { varlen = strlen(var); } result = NULL; for (i = 0; ssl_var_lookup_ssl_cert_dn_rec[i].name != NULL; i++) { if (strEQn(var, ssl_var_lookup_ssl_cert_dn_rec[i].name, varlen) && strlen(ssl_var_lookup_ssl_cert_dn_rec[i].name) == varlen) { for (j = 0; j < X509_NAME_entry_count(xsname); j++) { xsne = X509_NAME_get_entry(xsname, j); n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); if (n == ssl_var_lookup_ssl_cert_dn_rec[i].nid && idx-- == 0) { result = modssl_X509_NAME_ENTRY_to_string(p, xsne, raw); break; } } break; } } return result; }
static const char *start_if_define_extended(cmd_parms * cmd, void *dummy, const char *arg) { const char *endp; char *expr; int define; int not = 0; endp = ap_strrchr_c(arg, '>'); if (endp == NULL) { return (const char *) apr_pstrcat(cmd->pool, cmd->cmd->name, "> directive missing closing '>'", NULL); } expr = apr_pstrndup(cmd->temp_pool, arg, endp - arg); if (expr[0] == '!') { not = 1; expr++; } define = is_define(cmd, expr); if ((!not && define) || (not && !define)) { ap_directive_t *parent = NULL; ap_directive_t *current = NULL; const char *retval; retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd, ¤t, &parent, "<IfDefineExtended"); *(ap_directive_t **) dummy = current; return retval; } else { *(ap_directive_t **) dummy = NULL; return ap_soak_end_container(cmd, "<IfDefineExtended"); } }
static void log_error_core(const char *file, int line, int level, apr_status_t status, const server_rec *s, const conn_rec *c, const request_rec *r, apr_pool_t *pool, const char *fmt, va_list args) { char errstr[MAX_STRING_LEN]; #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED char scratch[MAX_STRING_LEN]; #endif apr_size_t len, errstrlen; apr_file_t *logf = NULL; const char *referer; int level_and_mask = level & APLOG_LEVELMASK; if (r && r->connection) { c = r->connection; } if (s == NULL) { /* * If we are doing stderr logging (startup), don't log messages that are * above the default server log level unless it is a startup/shutdown * notice */ if ((level_and_mask != APLOG_NOTICE) && (level_and_mask > ap_default_loglevel)) { return; } logf = stderr_log; } else if (s->error_log) { /* * If we are doing normal logging, don't log messages that are * above the server log level unless it is a startup/shutdown notice */ if ((level_and_mask != APLOG_NOTICE) && (level_and_mask > s->loglevel)) { return; } logf = s->error_log; } #ifdef TPF else if (tpf_child) { /* * If we are doing normal logging, don't log messages that are * above the server log level unless it is a startup/shutdown notice */ if ((level_and_mask != APLOG_NOTICE) && (level_and_mask > s->loglevel)) { return; } logf = stderr; } #endif /* TPF */ else { /* * If we are doing syslog logging, don't log messages that are * above the server log level (including a startup/shutdown notice) */ if (level_and_mask > s->loglevel) { return; } } if (logf && ((level & APLOG_STARTUP) != APLOG_STARTUP)) { errstr[0] = '['; ap_recent_ctime(errstr + 1, apr_time_now()); errstr[1 + APR_CTIME_LEN - 1] = ']'; errstr[1 + APR_CTIME_LEN ] = ' '; len = 1 + APR_CTIME_LEN + 1; } else { len = 0; } if ((level & APLOG_STARTUP) != APLOG_STARTUP) { len += apr_snprintf(errstr + len, MAX_STRING_LEN - len, "[%s] ", priorities[level_and_mask].t_name); } #ifndef TPF if (file && level_and_mask == APLOG_DEBUG) { #if defined(_OSD_POSIX) || defined(WIN32) || defined(__MVS__) char tmp[256]; char *e = strrchr(file, '/'); #ifdef WIN32 if (!e) { e = strrchr(file, '\\'); } #endif /* In OSD/POSIX, the compiler returns for __FILE__ * a string like: __FILE__="*POSIX(/usr/include/stdio.h)" * (it even returns an absolute path for sources in * the current directory). Here we try to strip this * down to the basename. */ if (e != NULL && e[1] != '\0') { apr_snprintf(tmp, sizeof(tmp), "%s", &e[1]); e = &tmp[strlen(tmp)-1]; if (*e == ')') { *e = '\0'; } file = tmp; } #else /* _OSD_POSIX || WIN32 */ const char *p; /* On Unix, __FILE__ may be an absolute path in a * VPATH build. */ if (file[0] == '/' && (p = ap_strrchr_c(file, '/')) != NULL) { file = p + 1; } #endif /*_OSD_POSIX || WIN32 */ len += apr_snprintf(errstr + len, MAX_STRING_LEN - len, "%s(%d): ", file, line); } #endif /* TPF */ if (c) { /* XXX: TODO: add a method of selecting whether logged client * addresses are in dotted quad or resolved form... dotted * quad is the most secure, which is why I'm implementing it * first. -djg */ len += apr_snprintf(errstr + len, MAX_STRING_LEN - len, "[client %s] ", c->remote_ip); } if (status != 0) { if (status < APR_OS_START_EAIERR) { len += apr_snprintf(errstr + len, MAX_STRING_LEN - len, "(%d)", status); } else if (status < APR_OS_START_SYSERR) { len += apr_snprintf(errstr + len, MAX_STRING_LEN - len, "(EAI %d)", status - APR_OS_START_EAIERR); } else if (status < 100000 + APR_OS_START_SYSERR) { len += apr_snprintf(errstr + len, MAX_STRING_LEN - len, "(OS %d)", status - APR_OS_START_SYSERR); } else { len += apr_snprintf(errstr + len, MAX_STRING_LEN - len, "(os 0x%08x)", status - APR_OS_START_SYSERR); } apr_strerror(status, errstr + len, MAX_STRING_LEN - len); len += strlen(errstr + len); if (MAX_STRING_LEN - len > 2) { errstr[len++] = ':'; errstr[len++] = ' '; errstr[len] = '\0'; } } errstrlen = len; #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED if (apr_vsnprintf(scratch, MAX_STRING_LEN - len, fmt, args)) { len += ap_escape_errorlog_item(errstr + len, scratch, MAX_STRING_LEN - len); } #else len += apr_vsnprintf(errstr + len, MAX_STRING_LEN - len, fmt, args); #endif if ( r && (referer = apr_table_get(r->headers_in, "Referer")) #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED && ap_escape_errorlog_item(scratch, referer, MAX_STRING_LEN - len) #endif ) { len += apr_snprintf(errstr + len, MAX_STRING_LEN - len, ", referer: %s", #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED scratch #else referer #endif ); } /* NULL if we are logging to syslog */ if (logf) { /* Truncate for the terminator (as apr_snprintf does) */ if (len > MAX_STRING_LEN - sizeof(APR_EOL_STR)) { len = MAX_STRING_LEN - sizeof(APR_EOL_STR); } strcpy(errstr + len, APR_EOL_STR); apr_file_puts(errstr, logf); apr_file_flush(logf); } #ifdef HAVE_SYSLOG else { syslog(level_and_mask, "%s", errstr); } #endif ap_run_error_log(file, line, level, status, s, r, pool, errstr + errstrlen); }
static apr_status_t ap_unix_create_privileged_process( apr_proc_t *newproc, const char *progname, const char * const *args, const char * const *env, apr_procattr_t *attr, ap_unix_identity_t *ugid, apr_pool_t *p) { int i = 0; const char **newargs; char *newprogname; char *execuser, *execgroup; const char *argv0; if (!ap_unixd_config.suexec_enabled) { return apr_proc_create(newproc, progname, args, env, attr, p); } argv0 = ap_strrchr_c(progname, '/'); /* Allow suexec's "/" check to succeed */ if (argv0 != NULL) { argv0++; } else { argv0 = progname; } if (ugid->userdir) { execuser = apr_psprintf(p, "~%ld", (long) ugid->uid); } else { execuser = apr_psprintf(p, "%ld", (long) ugid->uid); } execgroup = apr_psprintf(p, "%ld", (long) ugid->gid); if (!execuser || !execgroup) { return APR_ENOMEM; } i = 0; while (args[i]) i++; /* allocate space for 4 new args, the input args, and a null terminator */ newargs = apr_palloc(p, sizeof(char *) * (i + 4)); newprogname = SUEXEC_BIN; newargs[0] = SUEXEC_BIN; newargs[1] = execuser; newargs[2] = execgroup; newargs[3] = apr_pstrdup(p, argv0); /* ** using a shell to execute suexec makes no sense thus ** we force everything to be APR_PROGRAM, and never ** APR_SHELLCMD */ if (apr_procattr_cmdtype_set(attr, APR_PROGRAM) != APR_SUCCESS) { return APR_EGENERAL; } i = 1; do { newargs[i + 3] = args[i]; } while (args[i++]); return apr_proc_create(newproc, newprogname, newargs, env, attr, p); }
static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p, const char *uri, apr_uri_t *parsed_uri, const char **key) { cache_server_conf *conf; char *port_str, *hn, *lcs; const char *hostname, *scheme; int i; const char *path; char *querystring; if (*key) { /* * We have been here before during the processing of this request. */ return APR_SUCCESS; } /* * Get the module configuration. We need this for the CacheIgnoreQueryString * option below. */ conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, &cache_module); /* * Use the canonical name to improve cache hit rate, but only if this is * not a proxy request or if this is a reverse proxy request. * We need to handle both cases in the same manner as for the reverse proxy * case we have the following situation: * * If a cached entry is looked up by mod_cache's quick handler r->proxyreq * is still unset in the reverse proxy case as it only gets set in the * translate name hook (either by ProxyPass or mod_rewrite) which is run * after the quick handler hook. This is different to the forward proxy * case where it gets set before the quick handler is run (in the * post_read_request hook). * If a cache entry is created by the CACHE_SAVE filter we always have * r->proxyreq set correctly. * So we must ensure that in the reverse proxy case we use the same code * path and using the canonical name seems to be the right thing to do * in the reverse proxy case. */ if (!r->proxyreq || (r->proxyreq == PROXYREQ_REVERSE)) { if (conf->base_uri && conf->base_uri->hostname) { hostname = conf->base_uri->hostname; } else { /* Use _default_ as the hostname if none present, as in mod_vhost */ hostname = ap_get_server_name(r); if (!hostname) { hostname = "_default_"; } } } else if (parsed_uri->hostname) { /* Copy the parsed uri hostname */ hn = apr_pstrdup(p, parsed_uri->hostname); ap_str_tolower(hn); /* const work-around */ hostname = hn; } else { /* We are a proxied request, with no hostname. Unlikely * to get very far - but just in case */ hostname = "_default_"; } /* * Copy the scheme, ensuring that it is lower case. If the parsed uri * contains no string or if this is not a proxy request get the http * scheme for this request. As r->parsed_uri.scheme is not set if this * is a reverse proxy request, it is ensured that the cases * "no proxy request" and "reverse proxy request" are handled in the same * manner (see above why this is needed). */ if (r->proxyreq && parsed_uri->scheme) { /* Copy the scheme and lower-case it */ lcs = apr_pstrdup(p, parsed_uri->scheme); ap_str_tolower(lcs); /* const work-around */ scheme = lcs; } else { if (conf->base_uri && conf->base_uri->scheme) { scheme = conf->base_uri->scheme; } else { scheme = ap_http_scheme(r); } } /* * If this is a proxy request, but not a reverse proxy request (see comment * above why these cases must be handled in the same manner), copy the * URI's port-string (which may be a service name). If the URI contains * no port-string, use apr-util's notion of the default port for that * scheme - if available. Otherwise use the port-number of the current * server. */ if (r->proxyreq && (r->proxyreq != PROXYREQ_REVERSE)) { if (parsed_uri->port_str) { port_str = apr_pcalloc(p, strlen(parsed_uri->port_str) + 2); port_str[0] = ':'; for (i = 0; parsed_uri->port_str[i]; i++) { port_str[i + 1] = apr_tolower(parsed_uri->port_str[i]); } } else if (apr_uri_port_of_scheme(scheme)) { port_str = apr_psprintf(p, ":%u", apr_uri_port_of_scheme(scheme)); } else { /* No port string given in the AbsoluteUri, and we have no * idea what the default port for the scheme is. Leave it * blank and live with the inefficiency of some extra cached * entities. */ port_str = ""; } } else { if (conf->base_uri && conf->base_uri->port_str) { port_str = conf->base_uri->port_str; } else if (conf->base_uri && conf->base_uri->hostname) { port_str = ""; } else { /* Use the server port */ port_str = apr_psprintf(p, ":%u", ap_get_server_port(r)); } } /* * Check if we need to ignore session identifiers in the URL and do so * if needed. */ path = uri; querystring = parsed_uri->query; if (conf->ignore_session_id->nelts) { int i; char **identifier; identifier = (char **) conf->ignore_session_id->elts; for (i = 0; i < conf->ignore_session_id->nelts; i++, identifier++) { int len; const char *param; len = strlen(*identifier); /* * Check that we have a parameter separator in the last segment * of the path and that the parameter matches our identifier */ if ((param = ap_strrchr_c(path, ';')) && !strncmp(param + 1, *identifier, len) && (*(param + len + 1) == '=') && !ap_strchr_c(param + len + 2, '/')) { path = apr_pstrndup(p, path, param - path); continue; } /* * Check if the identifier is in the querystring and cut it out. */ if (querystring) { /* * First check if the identifier is at the beginning of the * querystring and followed by a '=' */ if (!strncmp(querystring, *identifier, len) && (*(querystring + len) == '=')) { param = querystring; } else { char *complete; /* * In order to avoid subkey matching (PR 48401) prepend * identifier with a '&' and append a '=' */ complete = apr_pstrcat(p, "&", *identifier, "=", NULL); param = strstr(querystring, complete); /* If we found something we are sitting on the '&' */ if (param) { param++; } } if (param) { const char *amp; if (querystring != param) { querystring = apr_pstrndup(p, querystring, param - querystring); } else { querystring = ""; } if ((amp = ap_strchr_c(param + len + 1, '&'))) { querystring = apr_pstrcat(p, querystring, amp + 1, NULL); } else { /* * If querystring is not "", then we have the case * that the identifier parameter we removed was the * last one in the original querystring. Hence we have * a trailing '&' which needs to be removed. */ if (*querystring) { querystring[strlen(querystring) - 1] = '\0'; } } } } } } /* Key format is a URI, optionally without the query-string */ if (conf->ignorequerystring) { *key = apr_pstrcat(p, scheme, "://", hostname, port_str, path, "?", NULL); } else { *key = apr_pstrcat(p, scheme, "://", hostname, port_str, path, "?", querystring, NULL); } /* * Store the key in the request_config for the cache as r->parsed_uri * might have changed in the time from our first visit here triggered by the * quick handler and our possible second visit triggered by the CACHE_SAVE * filter (e.g. r->parsed_uri got unescaped). In this case we would save the * resource in the cache under a key where it is never found by the quick * handler during following requests. */ ap_log_rerror( APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(00698) "cache: Key for entity %s?%s is %s", uri, parsed_uri->query, *key); return APR_SUCCESS; }
/* 处理安全策略和规则集的指令 */ static int process_security_rule(server_policy_t *sp, ap_directive_t *current, ap_directive_t *conftree, apr_pool_t *ptemp) { apr_status_t rv; ap_directive_t *newdir; apr_array_header_t *secpolicy_config; int i; char *cmd_name, *bracket; const char *endp; int container_num, closed_container_num; const char **cmd_args; ap_directive_t *curr_parent = conftree; /* 处理安全策略的指令 */ secpolicy_config = apr_array_make(ptemp, 1, sizeof(char *)); rv = convert_sec_policy_query(sp->sec_policy->name, &secpolicy_config); if (rv != OK) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "query security policy %s error", sp->sec_policy->name); return DECLINED; } container_num = 0; closed_container_num = 0; for (i = 0; i < secpolicy_config->nelts; i ++) { cmd_args = (const char **)(secpolicy_config->elts + (secpolicy_config->elt_size * i)); if (cmd_args) { cmd_name = ap_getword_conf(ptemp, cmd_args); switch (get_command_type(cmd_name)) { case CONTAINER_COMMAND: container_num = container_num + 1; newdir = (ap_directive_t *)apr_pcalloc(ptemp, sizeof(ap_directive_t)); newdir->filename = sp->name; /* 使用服务器策略名字作为指令文件名 */ newdir->line_num = (current == NULL) ? 1 : (current->line_num + 1); newdir->directive = apr_pstrdup(ptemp, cmd_name); newdir->args = apr_pstrdup(ptemp, *cmd_args); endp = ap_strrchr_c(newdir->args, '>'); if (endp == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s directive missing closing '>'", cmd_name); return DECLINED; } current = ap_add_node(&curr_parent, current, newdir, 1); break; case CLOSED_CONTAINER_COMMAND: if (curr_parent == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "no appear < container"); return DECLINED; } closed_container_num = closed_container_num + 1; bracket = cmd_name + strlen(cmd_name) - 1; if (*bracket != '>') { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s directive missing closing '>'", cmd_name); return DECLINED; } *bracket = '\0'; if (strcasecmp(cmd_name + 2, curr_parent->directive + 1) != 0) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Expected </%s> but saw %s>", curr_parent->directive + 1, cmd_name + 2); return DECLINED; } *bracket = '>'; current = curr_parent; curr_parent = curr_parent->parent; break; case SINGLE_COMMAND: newdir = (ap_directive_t *)apr_pcalloc(ptemp, sizeof(ap_directive_t)); newdir->filename = sp->name; /* 使用服务器策略名字作为指令文件名 */ newdir->line_num = (current == NULL) ? 1 : (current->line_num + 1); newdir->directive = apr_pstrdup(ptemp, cmd_name); newdir->args = apr_pstrdup(ptemp, *cmd_args); current = ap_add_node(&curr_parent, current, newdir, 0); break; default: break; } } } if (container_num != closed_container_num) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "< > container number not equal to </ > container number"); return DECLINED; } return OK; }