From 3d3e03a63a54bc389fac77b575044fb417707e30 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Tue, 5 Nov 2019 12:43:29 +0000 Subject: [PATCH] mod_proxy: Add proxy check_trans hook. This allows proxy modules to decline request handling at early stage. Then mod_proxy_wstunnel can implement that hook to verify that an Upgrade is requested, and otherwise hand over to mod_proxy_http. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1869399 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 +++ include/ap_mmn.h | 3 ++- modules/proxy/mod_proxy.c | 13 +++++++++++++ modules/proxy/mod_proxy.h | 2 ++ modules/proxy/mod_proxy_wstunnel.c | 18 ++++++++++++++++++ 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index b28b00a432..c311e82ba8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.1 + *) mod_proxy: Add proxy check_trans hook for proxy modules to possibly + decline request handling at early stage. [Yann Ylavic] + *) mod_proxy: Put mod_proxy_{connect,wstunnel} tunneling code in common in proxy_util. [Yann Ylavic] diff --git a/include/ap_mmn.h b/include/ap_mmn.h index c36e4866ef..2a8a7eef27 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -617,6 +617,7 @@ * AP_VOLATILIZE_T. * 20190312.5 (2.5.1-dev) Add proxy_tunnel_rec, ap_proxy_tunnel_create() * and ap_proxy_tunnel_run() to proxy_util. + * 20190312.6 (2.5.1-dev) Add proxy check_trans hook */ #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */ @@ -624,7 +625,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20190312 #endif -#define MODULE_MAGIC_NUMBER_MINOR 5 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 6 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 93b0a86859..9799e2884a 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -764,6 +764,15 @@ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent, } if (found) { + /* A proxy module is assigned this URL, check whether it's interested + * in the request itself (e.g. proxy_wstunnel cares about Upgrade + * requests only, and could hand over to proxy_http otherwise). + */ + int rc = proxy_run_check_trans(r, found + 6); + if (rc != OK && rc != DECLINED) { + return DONE; + } + r->filename = found; r->handler = "proxy-server"; r->proxyreq = PROXYREQ_REVERSE; @@ -3120,6 +3129,7 @@ APR_HOOK_STRUCT( APR_HOOK_LINK(pre_request) APR_HOOK_LINK(post_request) APR_HOOK_LINK(request_status) + APR_HOOK_LINK(check_trans) ) APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, scheme_handler, @@ -3128,6 +3138,9 @@ APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, scheme_handler, char *url, const char *proxyhost, apr_port_t proxyport),(r,worker,conf, url,proxyhost,proxyport),DECLINED) +APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, check_trans, + (request_rec *r, const char *url), + (r, url), DECLINED) APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, canon_handler, (request_rec *r, char *url),(r, url),DECLINED) diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 3769b30619..c75992a60b 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -623,6 +623,8 @@ APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r, proxy_worker *worker, proxy_server_conf *conf, char *url, const char *proxyhost, apr_port_t proxyport)) +APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, check_trans, + (request_rec *r, const char *url)) APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r, char *url)) diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c index 9c66ef8c73..794397b30d 100644 --- a/modules/proxy/mod_proxy_wstunnel.c +++ b/modules/proxy/mod_proxy_wstunnel.c @@ -92,6 +92,23 @@ static void proxy_wstunnel_callback(void *b) } } +static int proxy_wstunnel_check_trans(request_rec *r, const char *url) +{ + if (ap_cstr_casecmpn(url, "ws:", 3) != 0 + && ap_cstr_casecmpn(url, "wss:", 4) != 0) { + return DECLINED; + } + + if (!apr_table_get(r->headers_in, "Upgrade")) { + /* No Upgrade, let mod_proxy_http handle it (for instance). + * Note: anything but OK/DECLINED will do (i.e. bypass wstunnel w/o + * aborting the request), HTTP_UPGRADE_REQUIRED is documentary... + */ + return HTTP_UPGRADE_REQUIRED; + } + + return OK; +} /* * Canonicalise http-like URLs. @@ -414,6 +431,7 @@ static void ap_proxy_http_register_hook(apr_pool_t *p) { static const char * const aszSucc[] = { "mod_proxy_http.c", NULL}; proxy_hook_scheme_handler(proxy_wstunnel_handler, NULL, aszSucc, APR_HOOK_FIRST); + proxy_hook_check_trans(proxy_wstunnel_check_trans, NULL, aszSucc, APR_HOOK_MIDDLE); proxy_hook_canon_handler(proxy_wstunnel_canon, NULL, aszSucc, APR_HOOK_FIRST); }