diff options
author | Stefan Fritsch <sf@sfritsch.de> | 2015-12-19 09:17:42 +0100 |
---|---|---|
committer | Stefan Fritsch <sf@sfritsch.de> | 2015-12-19 09:17:42 +0100 |
commit | d5325781b38052fbdf4cc28a6c6d3052b9424b51 (patch) | |
tree | 0dd970f541f3d816f3b2217a9cd7a77f1733cbc9 /server | |
parent | f775596dea7222b55efc18005acf1919609c3602 (diff) | |
download | apache2-d5325781b38052fbdf4cc28a6c6d3052b9424b51.tar.gz |
Imported Upstream version 2.4.18
Diffstat (limited to 'server')
-rw-r--r-- | server/core.c | 46 | ||||
-rw-r--r-- | server/protocol.c | 83 | ||||
-rw-r--r-- | server/scoreboard.c | 25 | ||||
-rw-r--r-- | server/util_script.c | 31 |
4 files changed, 149 insertions, 36 deletions
diff --git a/server/core.c b/server/core.c index 37484b66..7ed6d9cc 100644 --- a/server/core.c +++ b/server/core.c @@ -191,6 +191,7 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir) conf->max_reversals = AP_MAXRANGES_UNSET; conf->cgi_pass_auth = AP_CGI_PASS_AUTH_UNSET; + conf->qualify_redirect_url = AP_CORE_CONFIG_UNSET; return (void *)conf; } @@ -405,6 +406,8 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv) conf->cgi_pass_auth = new->cgi_pass_auth != AP_CGI_PASS_AUTH_UNSET ? new->cgi_pass_auth : base->cgi_pass_auth; + AP_CORE_MERGE_FLAG(qualify_redirect_url, conf, base, new); + return (void*)conf; } @@ -1707,6 +1710,15 @@ static const char *set_cgi_pass_auth(cmd_parms *cmd, void *d_, int flag) return NULL; } +static const char *set_qualify_redirect_url(cmd_parms *cmd, void *d_, int flag) +{ + core_dir_config *d = d_; + + d->qualify_redirect_url = flag ? AP_CORE_CONFIG_ON : AP_CORE_CONFIG_OFF; + + return NULL; +} + static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[]) { core_dir_config *d = d_; @@ -1724,7 +1736,7 @@ static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *c d->override_list = apr_table_make(cmd->pool, argc); - for (i=0;i<argc;i++){ + for (i = 0; i < argc; i++) { if (!strcasecmp(argv[i], "None")) { if (argc != 1) { return "'None' not allowed with other directives in " @@ -1735,6 +1747,7 @@ static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *c else { const command_rec *result = NULL; module *mod = ap_top_module; + result = ap_find_command_in_modules(argv[i], &mod); if (result == NULL) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, @@ -1753,7 +1766,7 @@ static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *c continue; } else { - apr_table_set(d->override_list, argv[i], "1"); + apr_table_setn(d->override_list, argv[i], "1"); } } } @@ -4206,6 +4219,10 @@ AP_INIT_TAKE12("LimitInternalRecursion", set_recursion_limit, NULL, RSRC_CONF, AP_INIT_FLAG("CGIPassAuth", set_cgi_pass_auth, NULL, OR_AUTHCFG, "Controls whether HTTP authorization headers, normally hidden, will " "be passed to scripts"), +AP_INIT_FLAG("QualifyRedirectURL", set_qualify_redirect_url, NULL, OR_FILEINFO, + "Controls whether HTTP authorization headers, normally hidden, will " + "be passed to scripts"), + AP_INIT_TAKE1("ForceType", ap_set_string_slot_lower, (void *)APR_OFFSETOF(core_dir_config, mime_type), OR_FILEINFO, "a mime type that overrides other configured type"), @@ -4995,8 +5012,15 @@ static void core_dump_config(apr_pool_t *p, server_rec *s) static int core_upgrade_handler(request_rec *r) { conn_rec *c = r->connection; - const char *upgrade = apr_table_get(r->headers_in, "Upgrade"); + const char *upgrade; + if (c->master) { + /* Not possible to perform an HTTP/1.1 upgrade from a slave + * connection. */ + return DECLINED; + } + + upgrade = apr_table_get(r->headers_in, "Upgrade"); if (upgrade && *upgrade) { const char *conn = apr_table_get(r->headers_in, "Connection"); if (ap_find_token(r->pool, conn, "upgrade")) { @@ -5011,8 +5035,7 @@ static int core_upgrade_handler(request_rec *r) } if (offers && offers->nelts > 0) { - const char *protocol = ap_select_protocol(c, r, r->server, - offers); + const char *protocol = ap_select_protocol(c, r, NULL, offers); if (protocol && strcmp(protocol, ap_get_protocol(c))) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02909) "Upgrade selects '%s'", protocol); @@ -5034,6 +5057,19 @@ static int core_upgrade_handler(request_rec *r) } } } + else if (!c->keepalives) { + /* first request on a master connection, if we have protocols other + * than the current one enabled here, announce them to the + * client. If the client is already talking a protocol with requests + * on slave connections, leave it be. */ + const apr_array_header_t *upgrades; + ap_get_protocol_upgrades(c, r, NULL, 0, &upgrades); + if (upgrades && upgrades->nelts > 0) { + char *protocols = apr_array_pstrcat(r->pool, upgrades, ','); + apr_table_setn(r->headers_out, "Upgrade", protocols); + apr_table_setn(r->headers_out, "Connection", "Upgrade"); + } + } return DECLINED; } diff --git a/server/protocol.c b/server/protocol.c index fc507fa0..7fc5b096 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -561,12 +561,7 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) unsigned int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */ char http[5]; apr_size_t len; - int num_blank_lines = 0; - int max_blank_lines = r->server->limit_req_fields; - - if (max_blank_lines <= 0) { - max_blank_lines = DEFAULT_LIMIT_REQUEST_FIELDS; - } + int num_blank_lines = DEFAULT_LIMIT_BLANK_LINES; /* Read past empty lines until we get a real request line, * a read error, the connection closes (EOF), or we timeout. @@ -613,7 +608,7 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) r->protocol = apr_pstrdup(r->pool, "HTTP/1.0"); return 0; } - } while ((len <= 0) && (++num_blank_lines < max_blank_lines)); + } while ((len <= 0) && (--num_blank_lines >= 0)); if (APLOGrtrace5(r)) { ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, @@ -627,6 +622,13 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) uri = ap_getword_white(r->pool, &ll); + if (!*r->method || !*uri) { + r->status = HTTP_BAD_REQUEST; + r->proto_num = HTTP_VERSION(1,0); + r->protocol = apr_pstrdup(r->pool, "HTTP/1.0"); + return 0; + } + /* Provide quick information about the request method as soon as known */ r->method_number = ap_method_number_of(r->method); @@ -635,6 +637,9 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) } ap_parse_uri(r, uri); + if (r->status != HTTP_OK) { + return 0; + } if (ll[0]) { r->assbackwards = 0; @@ -1823,15 +1828,61 @@ AP_DECLARE(const char *) ap_get_protocol(conn_rec *c) return protocol? protocol : AP_PROTOCOL_HTTP1; } +AP_DECLARE(apr_status_t) ap_get_protocol_upgrades(conn_rec *c, request_rec *r, + server_rec *s, int report_all, + const apr_array_header_t **pupgrades) +{ + apr_pool_t *pool = r? r->pool : c->pool; + core_server_config *conf; + const char *existing; + apr_array_header_t *upgrades = NULL; + + if (!s) { + s = (r? r->server : c->base_server); + } + conf = ap_get_core_module_config(s->module_config); + + if (conf->protocols->nelts > 0) { + existing = ap_get_protocol(c); + if (conf->protocols->nelts > 1 + || !ap_array_str_contains(conf->protocols, existing)) { + int i; + + /* possibly more than one choice or one, but not the + * existing. (TODO: maybe 426 and Upgrade then?) */ + upgrades = apr_array_make(pool, conf->protocols->nelts + 1, + sizeof(char *)); + for (i = 0; i < conf->protocols->nelts; i++) { + const char *p = APR_ARRAY_IDX(conf->protocols, i, char *); + if (strcmp(existing, p)) { + /* not the one we have and possible, add in this order */ + APR_ARRAY_PUSH(upgrades, const char*) = p; + } + else if (!report_all) { + break; + } + } + } + } + + *pupgrades = upgrades; + return APR_SUCCESS; +} + AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r, server_rec *s, const apr_array_header_t *choices) { apr_pool_t *pool = r? r->pool : c->pool; - core_server_config *conf = ap_get_core_module_config(s->module_config); + core_server_config *conf; const char *protocol = NULL, *existing; apr_array_header_t *proposals; + if (!s) { + s = (r? r->server : c->base_server); + } + conf = ap_get_core_module_config(s->module_config); + if (APLOGcdebug(c)) { const char *p = apr_array_pstrcat(pool, conf->protocols, ','); ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, @@ -1937,6 +1988,22 @@ AP_DECLARE(apr_status_t) ap_switch_protocol(conn_rec *c, request_rec *r, } } +AP_DECLARE(int) ap_is_allowed_protocol(conn_rec *c, request_rec *r, + server_rec *s, const char *protocol) +{ + core_server_config *conf; + + if (!s) { + s = (r? r->server : c->base_server); + } + conf = ap_get_core_module_config(s->module_config); + + if (conf->protocols->nelts > 0) { + return ap_array_str_contains(conf->protocols, protocol); + } + return !strcmp(AP_PROTOCOL_HTTP1, protocol); +} + AP_IMPLEMENT_HOOK_VOID(pre_read_request, (request_rec *r, conn_rec *c), diff --git a/server/scoreboard.c b/server/scoreboard.c index 9e16a2ae..6d1b3bef 100644 --- a/server/scoreboard.c +++ b/server/scoreboard.c @@ -129,14 +129,19 @@ static apr_status_t ap_cleanup_shared_mem(void *d) return APR_SUCCESS; } +#define SIZE_OF_scoreboard APR_ALIGN_DEFAULT(sizeof(scoreboard)) +#define SIZE_OF_global_score APR_ALIGN_DEFAULT(sizeof(global_score)) +#define SIZE_OF_process_score APR_ALIGN_DEFAULT(sizeof(process_score)) +#define SIZE_OF_worker_score APR_ALIGN_DEFAULT(sizeof(worker_score)) + AP_DECLARE(int) ap_calc_scoreboard_size(void) { ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit); - scoreboard_size = sizeof(global_score); - scoreboard_size += sizeof(process_score) * server_limit; - scoreboard_size += sizeof(worker_score) * server_limit * thread_limit; + scoreboard_size = SIZE_OF_global_score; + scoreboard_size += SIZE_OF_process_score * server_limit; + scoreboard_size += SIZE_OF_worker_score * server_limit * thread_limit; return scoreboard_size; } @@ -153,17 +158,17 @@ AP_DECLARE(void) ap_init_scoreboard(void *shared_score) ap_calc_scoreboard_size(); ap_scoreboard_image = - ap_calloc(1, sizeof(scoreboard) + server_limit * sizeof(worker_score *)); + ap_calloc(1, SIZE_OF_scoreboard + server_limit * sizeof(worker_score *)); more_storage = shared_score; ap_scoreboard_image->global = (global_score *)more_storage; - more_storage += sizeof(global_score); + more_storage += SIZE_OF_global_score; ap_scoreboard_image->parent = (process_score *)more_storage; - more_storage += sizeof(process_score) * server_limit; + more_storage += SIZE_OF_process_score * server_limit; ap_scoreboard_image->servers = - (worker_score **)((char*)ap_scoreboard_image + sizeof(scoreboard)); + (worker_score **)((char*)ap_scoreboard_image + SIZE_OF_scoreboard); for (i = 0; i < server_limit; i++) { ap_scoreboard_image->servers[i] = (worker_score *)more_storage; - more_storage += thread_limit * sizeof(worker_score); + more_storage += thread_limit * SIZE_OF_worker_score; } ap_assert(more_storage == (char*)shared_score + scoreboard_size); ap_scoreboard_image->global->server_limit = server_limit; @@ -305,10 +310,10 @@ int ap_create_scoreboard(apr_pool_t *p, ap_scoreboard_e sb_type) if (ap_scoreboard_image) { ap_scoreboard_image->global->restart_time = apr_time_now(); memset(ap_scoreboard_image->parent, 0, - sizeof(process_score) * server_limit); + SIZE_OF_process_score * server_limit); for (i = 0; i < server_limit; i++) { memset(ap_scoreboard_image->servers[i], 0, - sizeof(worker_score) * thread_limit); + SIZE_OF_worker_score * thread_limit); } ap_init_scoreboard(NULL); return OK; diff --git a/server/util_script.c b/server/util_script.c index 14991cd0..7ac79301 100644 --- a/server/util_script.c +++ b/server/util_script.c @@ -282,21 +282,26 @@ AP_DECLARE(void) ap_add_common_vars(request_rec *r) /* Apache custom error responses. If we have redirected set two new vars */ if (r->prev) { - /* PR#57785: reconstruct full URL here */ - apr_uri_t *uri = &r->prev->parsed_uri; - if (!uri->scheme) { - uri->scheme = (char*)ap_http_scheme(r->prev); - } - if (!uri->port) { - uri->port = ap_get_server_port(r->prev); - uri->port_str = apr_psprintf(r->pool, "%u", uri->port); - } - if (!uri->hostname) { - uri->hostname = (char*)ap_get_server_name_for_url(r->prev); + if (conf->qualify_redirect_url != AP_CORE_CONFIG_ON) { + add_unless_null(e, "REDIRECT_URL", r->prev->uri); + } + else { + /* PR#57785: reconstruct full URL here */ + apr_uri_t *uri = &r->prev->parsed_uri; + if (!uri->scheme) { + uri->scheme = (char*)ap_http_scheme(r->prev); + } + if (!uri->port) { + uri->port = ap_get_server_port(r->prev); + uri->port_str = apr_psprintf(r->pool, "%u", uri->port); + } + if (!uri->hostname) { + uri->hostname = (char*)ap_get_server_name_for_url(r->prev); + } + add_unless_null(e, "REDIRECT_URL", + apr_uri_unparse(r->pool, uri, 0)); } add_unless_null(e, "REDIRECT_QUERY_STRING", r->prev->args); - add_unless_null(e, "REDIRECT_URL", - apr_uri_unparse(r->pool, uri, 0)); } if (e != r->subprocess_env) { |