From a68ed4380a434341c404486cf29db405548652d3 Mon Sep 17 00:00:00 2001 From: Alex/AT <85214814+AlexAT@users.noreply.github.com> Date: Wed, 2 Jun 2021 13:29:28 +0300 Subject: [PATCH 01/12] Reimplementation of remoteip-rpaf for 2.4.48 Changes to 2.4.41-46 version: - No more obscure hacks of SSL module and internal metadata for HTTPS simulation handling and port alteration, rely fully on existing Apache hooks (including new 2.4.48 ssl_conn_is_ssl() hook) - Use apr_table_nset() for connection annotation and header changes, we strdup() anyways - RemoteHTTPSEnableProto option omitted now means setting HTTPS mode simulation on any RemoteProtoHeader header presence, without verifying header contents, for compatibility with the previous default "RemoteHTTPSEnableProto https" needs to be used --- modules/metadata/mod_remoteip.c | 215 ++++++++++++++++++++++++++++++-- 1 file changed, 204 insertions(+), 11 deletions(-) diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c index e88c9c9ee6e..b1c56ea5ea1 100644 --- a/modules/metadata/mod_remoteip.c +++ b/modules/metadata/mod_remoteip.c @@ -25,6 +25,9 @@ #include "http_connection.h" #include "http_protocol.h" #include "http_log.h" +#include "http_request.h" +#include "http_ssl.h" +#include "http_vhost.h" #include "http_main.h" #include "apr_strings.h" #include "apr_lib.h" @@ -61,6 +64,12 @@ typedef struct { */ apr_array_header_t *proxymatch_ip; + const char *host_header_name; + const char *port_header_name; + const char *proto_header_name; + const char *proto_https_enable; + int forbid_direct; + remoteip_addr_info *proxy_protocol_enabled; remoteip_addr_info *proxy_protocol_disabled; @@ -179,6 +188,21 @@ static void *merge_remoteip_server_config(apr_pool_t *p, void *globalv, config->proxymatch_ip = server->proxymatch_ip ? server->proxymatch_ip : global->proxymatch_ip; + config->host_header_name = server->host_header_name + ? server->host_header_name + : global->host_header_name; + config->port_header_name = server->port_header_name + ? server->port_header_name + : global->port_header_name; + config->proto_header_name = server->proto_header_name + ? server->proto_header_name + : global->proto_header_name; + config->proto_https_enable = server->proto_https_enable + ? server->proto_https_enable + : global->proto_https_enable; + config->forbid_direct = server->forbid_direct + ? server->forbid_direct + : global->forbid_direct; return config; } @@ -540,14 +564,15 @@ static int remoteip_modify_request(request_rec *r) */ void *internal = NULL; - /* No header defined or results from our input filter */ - if (!config->header_name && !conn_config) { + /* No headers defined or results from our input filter */ + if (!conn_config && !config->header_name + && !config->host_header_name && !config->port_header_name + && !config->proto_header_name && !config->forbid_direct) { return DECLINED; } - - /* Easy parsing case - just position the data we already have from PROXY - protocol handling allowing it to take precedence and return - */ + + /* Position the remote IP data we may already have from PROXY protocol handling + */ if (conn_config) { if (!conn_config->client_addr) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(03496) @@ -560,7 +585,8 @@ static int remoteip_modify_request(request_rec *r) ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Using %s as client's IP from PROXY protocol", r->useragent_ip); - return OK; + /* We do not return here as we may still have specific remote parameters headers set by proxy + */ } if (config->proxymatch_ip) { @@ -571,14 +597,94 @@ static int remoteip_modify_request(request_rec *r) internal = (void *) 1; } + temp_sa = r->useragent_addr ? r->useragent_addr : c->client_addr; + + if (internal && (config->host_header_name || config->port_header_name || config->proto_header_name || config->forbid_direct)) { + /* The trusted proxy (or list of) is configured, honor the option to forbid direct connections (allowing only trusted internal proxies) + Also, if the connecting host is trusted internal proxy and some request modification headers are set, we honor these headers there + */ + int i; + void *first_internal = NULL; + remoteip_proxymatch_t *match; + match = (remoteip_proxymatch_t *)config->proxymatch_ip->elts; + for (i = 0; i < config->proxymatch_ip->nelts; ++i) { + if (apr_ipsubnet_test(match[i].ip, temp_sa)) { + first_internal = match[i].internal; + break; + } + } + if ((i && i >= config->proxymatch_ip->nelts) || !first_internal) { + if (config->forbid_direct) { + /* Whoops, trusted internal proxy was not detected and direct requests are forbidden, deny the request + */ + return HTTP_FORBIDDEN; + } + } else { + /* Internal trusted proxy is connecting, perform request modification if any options for it are set + */ + char *val; + + /* Remote host option, applied directly to the request host header + */ + if (config->host_header_name) { + const char *host; + if ( (host = apr_table_get(r->headers_in, config->host_header_name)) ) { + /* Propagate host header value from the header set by proxy and update virtual host chosen (the primary purpose of it) + */ + apr_array_header_t *hdrs = apr_array_make(r->pool, 0, sizeof(char*)); + while (*host && (val = ap_get_token(r->pool, &host, 1))) { + *(char **)apr_array_push(hdrs) = apr_pstrdup(r->pool, val); + if (*host != '\0') + ++host; + } + apr_table_setn(r->headers_in, "Host", apr_pstrdup(r->pool, ((char **)hdrs->elts)[((hdrs->nelts)-1)])); + r->hostname = apr_pstrdup(r->pool, ((char **)hdrs->elts)[((hdrs->nelts)-1)]); + ap_update_vhost_from_headers(r); + } + } + + /* Remote port option, due to the transient nature of subrequests we have to annotate the connection itself for ap_default_port() hook + */ + if (config->port_header_name) { + const char *port; + if ( (port = apr_table_get(r->headers_in, config->port_header_name) )) { + r->parsed_uri.port = r->server->port; + apr_table_setn(r->connection->notes, "remoteip_port", apr_pstrdup(r->connection->pool, port)); + } else { + /* Subsequent requests inside a single connection need to have the annotation reset if they do not have the header set + */ + apr_table_unset(r->connection->notes, "remoteip_port"); + } + } + + /* Remote HTTPS protocol option, due to transient nature of subrequests we have to annotate the connection itself for ap_conn_is_ssl() hook + */ + if (config->proto_header_name) { + const char *proto; + if ( (proto = apr_table_get(r->headers_in, config->proto_header_name)) ) { + /* Exact HTTPS protocol ID option not set means just the header presence is enough, otherwise check for a match + */ + if (!config->proto_https_enable || !strcmp(proto, config->proto_https_enable)) + apr_table_setn(r->connection->notes, "remoteip_https", "on"); + } else { + /* Subsequent requests inside a single connection need to have the annotation reset if they do not have the header set + */ + apr_table_unset(r->connection->notes, "remoteip_https"); + } + } + } + } + + /* No need to proceed further if we have no remote IP header set + */ + if (!config->header_name) return OK; + remote = (char *) apr_table_get(r->headers_in, config->header_name); if (!remote) { return OK; } remote = apr_pstrdup(r->pool, remote); - temp_sa = r->useragent_addr ? r->useragent_addr : c->client_addr; - while (remote) { /* verify user agent IP against the trusted proxy list @@ -749,6 +855,74 @@ static int remoteip_modify_request(request_rec *r) return OK; } +static int remoteip_hook_ssl_conn_is_ssl(conn_rec *c) +{ + if (apr_table_get(c->notes, "remoteip_https")) + return OK; + + return DECLINED; +} + +static const char *remoteip_hook_http_scheme(const request_rec *r) +{ + if (apr_table_get(r->connection->notes, "remoteip_https")) + return "https"; + + return NULL; +} + +static apr_port_t remoteip_hook_default_port(const request_rec *r) +{ + const char *port; + if ( (port = apr_table_get(r->connection->notes, "remoteip_port")) ) + return atoi(port); + + return 0; +} + +int remoteip_hook_fixups(request_rec *r) +{ + if (apr_table_get(r->connection->notes, "remoteip_https")) + apr_table_setn(r->subprocess_env, "HTTPS", "on"); + + return DECLINED; +} + +static const char *host_header_name_set(cmd_parms *cmd, void *dummy, const char *arg) +{ + remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, &remoteip_module); + config->host_header_name = arg; + return NULL; +} + +static const char *port_header_name_set(cmd_parms *cmd, void *dummy, const char *arg) +{ + remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, &remoteip_module); + config->port_header_name = arg; + return NULL; +} + +static const char *proto_header_name_set(cmd_parms *cmd, void *dummy, const char *arg) +{ + remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, &remoteip_module); + config->proto_header_name = arg; + return NULL; +} + +static const char *proto_https_enable_set(cmd_parms *cmd, void *dummy, const char *arg) +{ + remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, &remoteip_module); + config->proto_https_enable = arg; + return NULL; +} + +static const char *forbid_direct_set(cmd_parms *cmd, void *dummy, int flag) +{ + remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, &remoteip_module); + config->forbid_direct = flag; + return NULL; +} + static int remoteip_is_server_port(apr_port_t port) { ap_listen_rec *lr; @@ -1226,7 +1400,7 @@ static const command_rec remoteip_cmds[] = "e.g. X-Forwarded-By; if not given then do not record"), AP_INIT_ITERATE("RemoteIPTrustedProxy", proxies_set, 0, RSRC_CONF, "Specifies one or more proxies which are trusted " - "to present IP headers"), + "to present IP and request modification headers"), AP_INIT_ITERATE("RemoteIPInternalProxy", proxies_set, (void*)1, RSRC_CONF, "Specifies one or more internal (transparent) proxies " "which are trusted to present IP headers"), @@ -1243,6 +1417,21 @@ static const command_rec remoteip_cmds[] = AP_INIT_TAKE_ARGV("RemoteIPProxyProtocolExceptions", remoteip_disable_networks, NULL, RSRC_CONF, "Disable PROXY " "protocol handling for this list of networks in CIDR format"), + AP_INIT_TAKE1("RemoteHostHeader", host_header_name_set, NULL, RSRC_CONF, + "Specifies a request header to trust as the original Host header, " + "e.g. X-Forwarded-Host, valid only if direct client is internal proxy"), + AP_INIT_TAKE1("RemotePortHeader", port_header_name_set, NULL, RSRC_CONF, + "Specifies a request header to trust as the original Port header, " + "e.g. X-Forwarded-Port, valid only if direct client is internal proxy"), + AP_INIT_TAKE1("RemoteProtoHeader", proto_header_name_set, NULL, RSRC_CONF, + "Specifies a request header to trust as the original protocol header, " + "e.g. X-Forwarded-Proto, valid only if direct client is internal proxy"), + AP_INIT_TAKE1("RemoteHTTPSEnableProto", proto_https_enable_set, NULL, RSRC_CONF, + "Specifies a value in the header specified by RemoteProtoHeaderrequest " + "that will set HTTPS flag enabled, just the presence of RemoteProtoHeader " + "header will enable HTTPS flag if RemoteHTTPSEnableProto is not set"), + AP_INIT_FLAG("RemoteAllowOnlyInternalProxies", forbid_direct_set, NULL, RSRC_CONF, + "Deny access from any hosts besides trusted internal proxies"), { NULL } }; @@ -1250,13 +1439,17 @@ static void register_hooks(apr_pool_t *p) { /* mod_ssl is CONNECTION + 5, so we want something higher (earlier); * mod_reqtimeout is CONNECTION + 8, so we want something lower (later) */ - remoteip_filter = + remoteip_filter = ap_register_input_filter("REMOTEIP_INPUT", remoteip_input_filter, NULL, AP_FTYPE_CONNECTION + 7); ap_hook_post_config(remoteip_hook_post_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_pre_connection(remoteip_hook_pre_connection, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_read_request(remoteip_modify_request, NULL, NULL, APR_HOOK_FIRST); + ap_hook_ssl_conn_is_ssl(remoteip_hook_ssl_conn_is_ssl, NULL, NULL, APR_HOOK_LAST); + ap_hook_http_scheme(remoteip_hook_http_scheme, NULL, NULL, APR_HOOK_LAST); + ap_hook_fixups(remoteip_hook_fixups, NULL, NULL, APR_HOOK_LAST); + ap_hook_default_port(remoteip_hook_default_port, NULL, NULL, APR_HOOK_FIRST); } AP_DECLARE_MODULE(remoteip) = { From 0e79fd210ad8b4dd341cdf6a3f99bb62da96c26c Mon Sep 17 00:00:00 2001 From: Alex/AT <85214814+AlexAT@users.noreply.github.com> Date: Wed, 2 Jun 2021 20:23:12 +0300 Subject: [PATCH 02/12] Update mod_remoteip.c --- modules/metadata/mod_remoteip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c index b1c56ea5ea1..8088c83221f 100644 --- a/modules/metadata/mod_remoteip.c +++ b/modules/metadata/mod_remoteip.c @@ -880,7 +880,7 @@ static apr_port_t remoteip_hook_default_port(const request_rec *r) return 0; } -int remoteip_hook_fixups(request_rec *r) +static int remoteip_hook_fixups(request_rec *r) { if (apr_table_get(r->connection->notes, "remoteip_https")) apr_table_setn(r->subprocess_env, "HTTPS", "on"); From ade2cc72be7d25a44a23fe14a1705cad96bc250e Mon Sep 17 00:00:00 2001 From: Alex/AT <85214814+AlexAT@users.noreply.github.com> Date: Thu, 23 Mar 2023 18:20:35 +0300 Subject: [PATCH 03/12] Reset HTTPS flag connection note when there is no header content match Thanks to @tomsommer for reporting that bug On keepalive connections when using specific RemoteIP "HTTPS" header content matching, connection note of remote_https is not reset when there is no match and so "HTTPS on" flag leaks between subsequent requests inside single connection in this case. Reproduce: RemoteHTTPSEnableProto option used, single keepalive connection, virtual "HTTP" connection follows virtual "HTTPS" one Fix: unset connection note on no header content match path. --- modules/metadata/mod_remoteip.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c index 8088c83221f..7fec8462cee 100644 --- a/modules/metadata/mod_remoteip.c +++ b/modules/metadata/mod_remoteip.c @@ -664,8 +664,13 @@ static int remoteip_modify_request(request_rec *r) if ( (proto = apr_table_get(r->headers_in, config->proto_header_name)) ) { /* Exact HTTPS protocol ID option not set means just the header presence is enough, otherwise check for a match */ - if (!config->proto_https_enable || !strcmp(proto, config->proto_https_enable)) + if (!config->proto_https_enable || !strcmp(proto, config->proto_https_enable)) { apr_table_setn(r->connection->notes, "remoteip_https", "on"); + } else { + /* Subsequent requests inside a single connection need to have the annotation reset if they do not have the content match + */ + apr_table_unset(r->connection->notes, "remoteip_https"); + } } else { /* Subsequent requests inside a single connection need to have the annotation reset if they do not have the header set */ From d091bee2c4e0420152e4961e5cd20a508d3ecb66 Mon Sep 17 00:00:00 2001 From: Alex/AT Date: Sat, 25 Mar 2023 09:39:03 +0100 Subject: [PATCH 04/12] Update code based on reviews, part 1 - Use APR_ARRAY_PUSH() / APR_ARRAY_IDX() in remotely forwarded host header handling (@notroj) - Move remote port and SSL flags to conn_config structure instead of annotating the connection (@ylavic) - Default RemoteHTTPSEnableProto to 'https', use '*' to enable virtual HTTPS flag just on header presence (@ylavic) [BEHAVIORAL CHANGE] - Make RemoteHTTPSEnableProto header content check case-insensitive (@ylavic) [BEHAVIORAL CHANGE] - Move out pre-request PROXY protocol check from into its own separate function - Create conn_config structure on both either PROXY protocol data presence or when we need to store remote port / SSL flag information - Add has_client_addr flag to indicate PROXY protocol client address info presence to conn_config structure and use it as we may have only port/SSL flags there - Introduce config->proto_https_enable_any flag to indicate '*' in RemoteHTTPSEnableProto and avoid string comparisons in connection handling - Introduce conn_config->has_remote_is_ssl flag to indicate we have remote SSL flag received and so need to fixup the request data - HTTP scheme hook: hook FIRST as remote SSL information takes priority, return final https or http scheme if we have remote SSL flag set - Fixup hook: hook LAST as we need to override every other hook on our action, set or unset HTTPS envvar accordingly if we have remote SSL flag set - Update help for configuration options --- modules/metadata/mod_remoteip.c | 228 +++++++++++++++++++++++--------- 1 file changed, 164 insertions(+), 64 deletions(-) diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c index 7fec8462cee..93ac8758ccc 100644 --- a/modules/metadata/mod_remoteip.c +++ b/modules/metadata/mod_remoteip.c @@ -68,6 +68,7 @@ typedef struct { const char *port_header_name; const char *proto_header_name; const char *proto_https_enable; + int proto_https_enable_any; int forbid_direct; remoteip_addr_info *proxy_protocol_enabled; @@ -150,10 +151,18 @@ typedef struct { configurable parameters */ typedef struct { + /** Indicates presence of client address info in the structure **/ + int has_client_addr; /** The parsed client address in native format */ apr_sockaddr_t *client_addr; /** Character representation of the client */ char *client_ip; + /** Remote port */ + int remote_port; + /** Indicates presence of SSL flag */ + int has_remote_is_ssl; + /** Remote SSL flag */ + int remote_is_ssl; } remoteip_conn_config_t; typedef enum { HDR_DONE, HDR_ERROR, HDR_NEED_MORE } remoteip_parse_status_t; @@ -166,6 +175,11 @@ static void *create_remoteip_server_config(apr_pool_t *p, server_rec *s) * config->proxies_header_name = NULL; * config->proxy_protocol_enabled = NULL; * config->proxy_protocol_disabled = NULL; + * config->host_header_name = NULL; + * config->port_header_name = NULL; + * config->proto_header_name = NULL; + * config->proto_https_enable = NULL; + * config->proto_https_enable_any = 0; */ config->pool = p; return config; @@ -189,20 +203,22 @@ static void *merge_remoteip_server_config(apr_pool_t *p, void *globalv, ? server->proxymatch_ip : global->proxymatch_ip; config->host_header_name = server->host_header_name - ? server->host_header_name - : global->host_header_name; + ? server->host_header_name + : global->host_header_name; config->port_header_name = server->port_header_name - ? server->port_header_name - : global->port_header_name; + ? server->port_header_name + : global->port_header_name; config->proto_header_name = server->proto_header_name - ? server->proto_header_name - : global->proto_header_name; + ? server->proto_header_name + : global->proto_header_name; config->proto_https_enable = server->proto_https_enable - ? server->proto_https_enable - : global->proto_https_enable; + ? server->proto_https_enable + : global->proto_https_enable; + config->proto_https_enable_any = (config->proto_https_enable && !strcmp("*", config->proto_https_enable)); config->forbid_direct = server->forbid_direct ? server->forbid_direct : global->forbid_direct; + return config; } @@ -573,7 +589,7 @@ static int remoteip_modify_request(request_rec *r) /* Position the remote IP data we may already have from PROXY protocol handling */ - if (conn_config) { + if (conn_config && conn_config->has_client_addr) { if (!conn_config->client_addr) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(03496) "RemoteIPProxyProtocol data is missing, but required! Aborting request."); @@ -633,48 +649,66 @@ static int remoteip_modify_request(request_rec *r) */ apr_array_header_t *hdrs = apr_array_make(r->pool, 0, sizeof(char*)); while (*host && (val = ap_get_token(r->pool, &host, 1))) { - *(char **)apr_array_push(hdrs) = apr_pstrdup(r->pool, val); + APR_ARRAY_PUSH(hdrs, char *) = apr_pstrdup(r->pool, val); if (*host != '\0') ++host; } - apr_table_setn(r->headers_in, "Host", apr_pstrdup(r->pool, ((char **)hdrs->elts)[((hdrs->nelts)-1)])); - r->hostname = apr_pstrdup(r->pool, ((char **)hdrs->elts)[((hdrs->nelts)-1)]); + apr_table_setn(r->headers_in, "Host", apr_pstrdup(r->pool, APR_ARRAY_IDX(hdrs, hdrs->nelts - 1, char *))); + r->hostname = apr_pstrdup(r->pool, APR_ARRAY_IDX(hdrs, hdrs->nelts - 1, char *)); ap_update_vhost_from_headers(r); } } - /* Remote port option, due to the transient nature of subrequests we have to annotate the connection itself for ap_default_port() hook + /* Remote port option, due to the transient nature of subrequests we have to store the port number for entire connection for ap_default_port() hook */ if (config->port_header_name) { const char *port; + + if (!conn_config) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10413) + "Remote IP per-connection data is missing, but required for RemotePortHeader! Aborting request."); + return HTTP_BAD_REQUEST; + } + if ( (port = apr_table_get(r->headers_in, config->port_header_name) )) { r->parsed_uri.port = r->server->port; - apr_table_setn(r->connection->notes, "remoteip_port", apr_pstrdup(r->connection->pool, port)); + conn_config->remote_port = atoi(port); } else { - /* Subsequent requests inside a single connection need to have the annotation reset if they do not have the header set + /* Subsequent requests inside a single connection need to have the port number reset if they do not have the header set */ - apr_table_unset(r->connection->notes, "remoteip_port"); + conn_config->remote_port = 0; } } - /* Remote HTTPS protocol option, due to transient nature of subrequests we have to annotate the connection itself for ap_conn_is_ssl() hook + /* Remote HTTPS protocol option, due to transient nature of subrequests we have to store the flag for entire connection for ap_remote_is_ssl() and fixup hooks */ if (config->proto_header_name) { const char *proto; + + if (!conn_config) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10414) + "Remote IP per-connection data is missing, but required for RemoteProtoHeader! Aborting request."); + return HTTP_BAD_REQUEST; + } + + /* Indicate we have set the remote_is_ssl flag + */ + conn_config->has_remote_is_ssl = 1; + if ( (proto = apr_table_get(r->headers_in, config->proto_header_name)) ) { - /* Exact HTTPS protocol ID option not set means just the header presence is enough, otherwise check for a match + /* Check HTTPS protocol ID, defaulting to 'https' if not set, proto_https_enable_any is set in config option/merge for empty string or '*' */ - if (!config->proto_https_enable || !strcmp(proto, config->proto_https_enable)) { - apr_table_setn(r->connection->notes, "remoteip_https", "on"); + if (config->proto_https_enable_any || !ap_cstr_casecmp(proto, config->proto_https_enable ? config->proto_https_enable : "https")) { + conn_config->remote_is_ssl = 1; } else { - /* Subsequent requests inside a single connection need to have the annotation reset if they do not have the content match + /* Subsequent requests inside a single connection need to have the flag reset if they do not have the content match */ - apr_table_unset(r->connection->notes, "remoteip_https"); + conn_config->remote_is_ssl = 0; } } else { - /* Subsequent requests inside a single connection need to have the annotation reset if they do not have the header set + /* Subsequent requests inside a single connection need to have the flag reset if they do not have the header found */ - apr_table_unset(r->connection->notes, "remoteip_https"); + conn_config->remote_is_ssl = 0; } } } @@ -862,33 +896,62 @@ static int remoteip_modify_request(request_rec *r) static int remoteip_hook_ssl_conn_is_ssl(conn_rec *c) { - if (apr_table_get(c->notes, "remoteip_https")) + remoteip_conn_config_t *conn_config = (remoteip_conn_config_t *) + ap_get_module_config(c->conn_config, &remoteip_module); + + if (conn_config && conn_config->has_remote_is_ssl && conn_config->remote_is_ssl) { return OK; + } return DECLINED; } static const char *remoteip_hook_http_scheme(const request_rec *r) { - if (apr_table_get(r->connection->notes, "remoteip_https")) - return "https"; + remoteip_conn_config_t *conn_config = (remoteip_conn_config_t *) + ap_get_module_config(r->connection->conn_config, &remoteip_module); - return NULL; + if (!conn_config) { + return NULL; + } + + if (!conn_config->has_remote_is_ssl) { + return NULL; + } + + return (conn_config->remote_is_ssl) ? "https" : "http"; } static apr_port_t remoteip_hook_default_port(const request_rec *r) { - const char *port; - if ( (port = apr_table_get(r->connection->notes, "remoteip_port")) ) - return atoi(port); + remoteip_conn_config_t *conn_config = (remoteip_conn_config_t *) + ap_get_module_config(r->connection->conn_config, &remoteip_module); - return 0; + if (!conn_config) { + return 0; + } + + return conn_config->remote_port; } static int remoteip_hook_fixups(request_rec *r) { - if (apr_table_get(r->connection->notes, "remoteip_https")) + remoteip_conn_config_t *conn_config = (remoteip_conn_config_t *) + ap_get_module_config(r->connection->conn_config, &remoteip_module); + + if (!conn_config) { + return DECLINED; + } + + if (!conn_config->has_remote_is_ssl) { + return DECLINED; + } + + if (conn_config->remote_is_ssl) { apr_table_setn(r->subprocess_env, "HTTPS", "on"); + } else { + apr_table_unset(r->subprocess_env, "HTTPS"); + } return DECLINED; } @@ -918,6 +981,7 @@ static const char *proto_https_enable_set(cmd_parms *cmd, void *dummy, const cha { remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, &remoteip_module); config->proto_https_enable = arg; + config->proto_https_enable_any = (config->proto_https_enable && !strcmp("*", config->proto_https_enable)); return NULL; } @@ -1047,35 +1111,22 @@ static remoteip_parse_status_t remoteip_process_v1_header(conn_rec *c, conn_conf->client_ip = apr_pstrdup(c->pool, host); + conn_conf->has_client_addr = 1; + return HDR_DONE; } -/** Add our filter to the connection if it is requested +/* Add our filter to the connection if it is requested */ -static int remoteip_hook_pre_connection(conn_rec *c, void *csd) +static int remoteip_pre_check_for_proxy_protocol(conn_rec *c, remoteip_config_t *conf) { - remoteip_config_t *conf; - remoteip_conn_config_t *conn_conf; int i; - /* Establish master config in slave connections, so that request processing - * finds it. */ - if (c->master != NULL) { - conn_conf = ap_get_module_config(c->master->conn_config, &remoteip_module); - if (conn_conf) { - ap_set_module_config(c->conn_config, &remoteip_module, conn_conf); - } - return DECLINED; - } - - conf = ap_get_module_config(ap_server_conf->module_config, - &remoteip_module); - /* check if we're enabled for this connection */ if (!remoteip_addr_in_list(conf->proxy_protocol_enabled, c->local_addr) || remoteip_addr_in_list(conf->proxy_protocol_disabled, c->local_addr)) { - return DECLINED; + return 0; } /* We are enabled for this IP/port, but check that we aren't @@ -1084,27 +1135,70 @@ static int remoteip_hook_pre_connection(conn_rec *c, void *csd) apr_ipsubnet_t *ip = ((apr_ipsubnet_t**)conf->disabled_subnets->elts)[i]; if (ip && apr_ipsubnet_test(ip, c->client_addr)) - return DECLINED; + return 0; } /* mod_proxy creates outgoing connections - we don't want those */ if (!remoteip_is_server_port(c->local_addr->port)) { - return DECLINED; + return 0; } /* add our filter */ if (!ap_add_input_filter_handle(remoteip_filter, NULL, NULL, c)) { /* XXX: Shouldn't this WARN in log? */ - return DECLINED; + return 0; } ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03503) "RemoteIPProxyProtocol: enabled on connection to %s:%hu", c->local_ip, c->local_addr->port); - /* this holds the resolved proxy info for this connection */ - conn_conf = apr_pcalloc(c->pool, sizeof(*conn_conf)); + return 1; +} +/* Pre-connection check for PROXY protocol and other conditions requiring + * per-connection configuration to be created + */ +static int remoteip_hook_pre_connection(conn_rec *c, void *csd) +{ + remoteip_config_t *conf; + remoteip_conn_config_t *conn_conf; + int need_conf; + + /* Establish master config in slave connections, so that request processing + * finds it. */ + if (c->master != NULL) { + conn_conf = ap_get_module_config(c->master->conn_config, &remoteip_module); + if (conn_conf) { + ap_set_module_config(c->conn_config, &remoteip_module, conn_conf); + } + return DECLINED; + } + + conf = ap_get_module_config(ap_server_conf->module_config, + &remoteip_module); + + /* Check if we have PROXY protocol enabled, this goes first as it needs to install the filter + */ + if (remoteip_pre_check_for_proxy_protocol(c, conf)) { + need_conf = 1; + } + + /* Check if we need to store remote port or SSL information, not joined with previous check for clarity + */ + if (conf->port_header_name || conf->proto_header_name) { + need_conf = 1; + } + + /* Bail out if we do not need the configuration structure + */ + if (!need_conf) { + return DECLINED; + } + + /* This holds the resolved proxy info and/or remote SSL info for this connection + */ + conn_conf = apr_pcalloc(c->pool, sizeof(*conn_conf)); ap_set_module_config(c->conn_config, &remoteip_module, conn_conf); return OK; @@ -1193,6 +1287,8 @@ static remoteip_parse_status_t remoteip_process_v2_header(conn_rec *c, return HDR_ERROR; } + conn_conf->has_client_addr = 1; + return HDR_DONE; } @@ -1424,17 +1520,21 @@ static const command_rec remoteip_cmds[] = "protocol handling for this list of networks in CIDR format"), AP_INIT_TAKE1("RemoteHostHeader", host_header_name_set, NULL, RSRC_CONF, "Specifies a request header to trust as the original Host header, " - "e.g. X-Forwarded-Host, valid only if direct client is internal proxy"), + "e.g. X-Forwarded-Host, valid only if direct client is internal proxy, " + "defaults to disabled"), AP_INIT_TAKE1("RemotePortHeader", port_header_name_set, NULL, RSRC_CONF, "Specifies a request header to trust as the original Port header, " - "e.g. X-Forwarded-Port, valid only if direct client is internal proxy"), + "e.g. X-Forwarded-Port, valid only if direct client is internal proxy, " + "defaults to disabled"), AP_INIT_TAKE1("RemoteProtoHeader", proto_header_name_set, NULL, RSRC_CONF, "Specifies a request header to trust as the original protocol header, " - "e.g. X-Forwarded-Proto, valid only if direct client is internal proxy"), + "e.g. X-Forwarded-Proto, valid only if direct client is internal proxy, " + "defaults to disabled"), AP_INIT_TAKE1("RemoteHTTPSEnableProto", proto_https_enable_set, NULL, RSRC_CONF, - "Specifies a value in the header specified by RemoteProtoHeaderrequest " - "that will set HTTPS flag enabled, just the presence of RemoteProtoHeader " - "header will enable HTTPS flag if RemoteHTTPSEnableProto is not set"), + "Specifies a value in the header specified by RemoteProtoHeader that " + "is required to set HTTPS flag enabled, setting this to '*' will enable " + "HTTPS flag just on header presence, disregarding the header value, the " + "comparison is case-insensitive, defaults to 'https'"), AP_INIT_FLAG("RemoteAllowOnlyInternalProxies", forbid_direct_set, NULL, RSRC_CONF, "Deny access from any hosts besides trusted internal proxies"), { NULL } @@ -1452,9 +1552,9 @@ static void register_hooks(apr_pool_t *p) ap_hook_pre_connection(remoteip_hook_pre_connection, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_read_request(remoteip_modify_request, NULL, NULL, APR_HOOK_FIRST); ap_hook_ssl_conn_is_ssl(remoteip_hook_ssl_conn_is_ssl, NULL, NULL, APR_HOOK_LAST); - ap_hook_http_scheme(remoteip_hook_http_scheme, NULL, NULL, APR_HOOK_LAST); - ap_hook_fixups(remoteip_hook_fixups, NULL, NULL, APR_HOOK_LAST); + ap_hook_http_scheme(remoteip_hook_http_scheme, NULL, NULL, APR_HOOK_FIRST); ap_hook_default_port(remoteip_hook_default_port, NULL, NULL, APR_HOOK_FIRST); + ap_hook_fixups(remoteip_hook_fixups, NULL, NULL, APR_HOOK_LAST); } AP_DECLARE_MODULE(remoteip) = { From 56c3cd42a42761b01996494502e0a942d28f2892 Mon Sep 17 00:00:00 2001 From: Alex/AT Date: Sat, 25 Mar 2023 09:44:41 +0100 Subject: [PATCH 05/12] As two new error message numbers were used, update the next error message number --- docs/log-message-tags/next-number | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/log-message-tags/next-number b/docs/log-message-tags/next-number index efba5f21902..727121476f5 100644 --- a/docs/log-message-tags/next-number +++ b/docs/log-message-tags/next-number @@ -1 +1 @@ -10413 +10415 From 4b9e4f2a4815d713837e640f50beacf54a3f43f7 Mon Sep 17 00:00:00 2001 From: Alex/AT Date: Sun, 26 Mar 2023 11:58:04 +0200 Subject: [PATCH 06/12] Update code based on reviews, part 2 - Introduce ap_remote_is_ssl() and corresponding remote_is_ssl remote SSL state hook (@ylavic) - Increase module magic number - Change mod_rewrite to use ap_remote_is_ssl() instead of ap_ssl_conn_is_ssl() for HTTPS variable - Introduce distinct HTTPS_LOCAL and HTTPS_REMOTE variables to mod_rewrite - Change mod_remoteip.c remote SSL state code to use MIDDLE remote_is_ssl hook and return OK(yes)/DONE(no) in case the flag is set properly - Change expression evaluator connection state HTTPS variable to HTTPS_LOCAL, introduce request state HTTPS and HTTPS_REMOTE variables --- include/ap_mmn.h | 3 ++- include/http_request.h | 19 +++++++++++++++++++ modules/mappers/mod_rewrite.c | 16 +++++++++++++++- modules/metadata/mod_remoteip.c | 14 +++++++------- server/request.c | 13 +++++++++++++ server/util_expr_eval.c | 10 +++++++++- 6 files changed, 65 insertions(+), 10 deletions(-) diff --git a/include/ap_mmn.h b/include/ap_mmn.h index c0e31163162..591995b6680 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -714,6 +714,7 @@ * 20211221.9 (2.5.1-dev) Add additional hcmethod_t enums and PROXY_WORKER_IS_ERROR * 20211221.10 (2.5.1-dev) Add ap_proxy_canonenc_ex * 20211221.11 (2.5.1-dev) Add AP_CTIME_OPTION_GMTOFF to util_time.h + * 20211221.12 (2.5.1-dev) Add ap_remote_is_ssl() and hooks */ #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */ @@ -721,7 +722,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20211221 #endif -#define MODULE_MAGIC_NUMBER_MINOR 11 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 12 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_request.h b/include/http_request.h index 93defac2854..5960c4ac7c2 100644 --- a/include/http_request.h +++ b/include/http_request.h @@ -591,6 +591,25 @@ AP_DECLARE_HOOK(int,force_authn,(request_rec *r)) */ AP_DECLARE_HOOK(apr_status_t,dirwalk_stat,(apr_finfo_t *finfo, request_rec *r, apr_int32_t wanted)) +/** + * This hook allows modules that virtualize SSL state (i.e. mod_remoteip) + * based on the data from remote frontend to register their inquiry function + * for checking if a remote frontend connection is using SSL for the request. + * @param r The current request + * @return OK iff the frontend connection is using SSL, DONE if not, + * DECLINED iff the state is undefined (let later modules decide). + * @ingroup hooks + */ +AP_DECLARE_HOOK(int,remote_is_ssl,(request_rec *r)) + +/** + * Return != 0 iff the frontend connection for the request is encrypted with SSL. + * If there is no data from the hook (DECLINED), falls back to ap_ssl_conn_is_ssl() + * and so corresponds to the local connection security state (we are the frontend). + * @param r The current request + */ +AP_DECLARE(int) ap_remote_is_ssl(request_rec *r); + AP_DECLARE(int) ap_location_walk(request_rec *r); AP_DECLARE(int) ap_directory_walk(request_rec *r); AP_DECLARE(int) ap_file_walk(request_rec *r); diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index af77e58eebe..fba2e431803 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -2030,7 +2030,7 @@ static char *lookup_variable(char *var, rewrite_ctx *ctx) case 5: if (!strcmp(var, "HTTPS")) { - int flag = ap_ssl_conn_is_ssl(r->connection); + int flag = ap_remote_is_ssl(r); return apr_pstrdup(r->pool, flag ? "on" : "off"); } break; @@ -2139,6 +2139,13 @@ static char *lookup_variable(char *var, rewrite_ctx *ctx) } break; + case 'H': + if (!strcmp(var, "HTTPS_LOCAL")) { + int flag = ap_ssl_conn_is_ssl(r->connection); + return apr_pstrdup(r->pool, flag ? "on" : "off"); + } + break; + case 'I': if (!strcmp(var, "API_VERSION")) { return apr_psprintf(r->pool, "%d:%d", @@ -2188,6 +2195,13 @@ static char *lookup_variable(char *var, rewrite_ctx *ctx) case 12: switch (var[3]) { + case 'H': + if (!strcmp(var, "HTTPS_REMOTE")) { + int flag = ap_remote_is_ssl(r); + return apr_pstrdup(r->pool, flag ? "on" : "off"); + } + break; + case 'I': if (!strcmp(var, "SCRIPT_GROUP")) { result = ""; diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c index 93ac8758ccc..ca014006766 100644 --- a/modules/metadata/mod_remoteip.c +++ b/modules/metadata/mod_remoteip.c @@ -665,7 +665,7 @@ static int remoteip_modify_request(request_rec *r) const char *port; if (!conn_config) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10413) + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10413) /* FIXME: how to properly set LOGNO in trunk patch? */ "Remote IP per-connection data is missing, but required for RemotePortHeader! Aborting request."); return HTTP_BAD_REQUEST; } @@ -686,7 +686,7 @@ static int remoteip_modify_request(request_rec *r) const char *proto; if (!conn_config) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10414) + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10414) /* FIXME: how to properly set LOGNO in trunk patch? */ "Remote IP per-connection data is missing, but required for RemoteProtoHeader! Aborting request."); return HTTP_BAD_REQUEST; } @@ -894,13 +894,13 @@ static int remoteip_modify_request(request_rec *r) return OK; } -static int remoteip_hook_ssl_conn_is_ssl(conn_rec *c) +static int remoteip_hook_remote_is_ssl(request_rec *r) { remoteip_conn_config_t *conn_config = (remoteip_conn_config_t *) - ap_get_module_config(c->conn_config, &remoteip_module); + ap_get_module_config(r->connection->conn_config, &remoteip_module); - if (conn_config && conn_config->has_remote_is_ssl && conn_config->remote_is_ssl) { - return OK; + if (conn_config && conn_config->has_remote_is_ssl) { + return conn_config->remote_is_ssl ? OK : DONE; } return DECLINED; @@ -1551,7 +1551,7 @@ static void register_hooks(apr_pool_t *p) ap_hook_post_config(remoteip_hook_post_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_pre_connection(remoteip_hook_pre_connection, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_read_request(remoteip_modify_request, NULL, NULL, APR_HOOK_FIRST); - ap_hook_ssl_conn_is_ssl(remoteip_hook_ssl_conn_is_ssl, NULL, NULL, APR_HOOK_LAST); + ap_hook_remote_is_ssl(remoteip_hook_remote_is_ssl, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_http_scheme(remoteip_hook_http_scheme, NULL, NULL, APR_HOOK_FIRST); ap_hook_default_port(remoteip_hook_default_port, NULL, NULL, APR_HOOK_FIRST); ap_hook_fixups(remoteip_hook_fixups, NULL, NULL, APR_HOOK_LAST); diff --git a/server/request.c b/server/request.c index cd2908da5d1..cbafd0c4e4d 100644 --- a/server/request.c +++ b/server/request.c @@ -41,6 +41,7 @@ #include "http_protocol.h" #include "http_log.h" #include "http_main.h" +#include "http_ssl.h" #include "util_filter.h" #include "util_charset.h" #include "util_script.h" @@ -73,6 +74,7 @@ APR_HOOK_STRUCT( APR_HOOK_LINK(post_perdir_config) APR_HOOK_LINK(dirwalk_stat) APR_HOOK_LINK(force_authn) + APR_HOOK_LINK(remote_is_ssl) ) AP_IMPLEMENT_HOOK_RUN_FIRST(int,pre_translate_name, @@ -103,6 +105,8 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t,dirwalk_stat, (finfo, r, wanted), AP_DECLINED) AP_IMPLEMENT_HOOK_RUN_FIRST(int,force_authn, (request_rec *r), (r), DECLINED) +AP_IMPLEMENT_HOOK_RUN_FIRST(int, remote_is_ssl, + (request_rec *r), (r), DECLINED) static int auth_internal_per_conf = 0; static int auth_internal_per_conf_hooks = 0; @@ -2574,3 +2578,12 @@ AP_DECLARE(int) ap_is_initial_req(request_rec *r) && (r->prev == NULL); /* otherwise, this is an internal redirect */ } +/* + * Is remote frontend connection SSL? Hooks return OK if yes, DONE if no + * If hook sequence returns DECLINED, we fall back to ap_ssl_conn_is_ssl() +*/ +AP_DECLARE(int) ap_remote_is_ssl(request_rec *r) +{ + int result = ap_run_remote_is_ssl(r); + return (result == DECLINED) ? ap_ssl_conn_is_ssl(r->connection) : (result == OK); +} diff --git a/server/util_expr_eval.c b/server/util_expr_eval.c index 9c71e865b0f..7281c4cc63e 100644 --- a/server/util_expr_eval.c +++ b/server/util_expr_eval.c @@ -1655,7 +1655,7 @@ APR_DECLARE_OPTIONAL_FN(int, http2_is_h2, (conn_rec *)); static APR_OPTIONAL_FN_TYPE(http2_is_h2) *is_http2 = NULL; static const char *const conn_var_names[] = { - "HTTPS", /* 0 */ + "HTTPS_LOCAL", /* 0 */ "IPV6", /* 1 */ "CONN_LOG_ID", /* 2 */ "CONN_REMOTE_ADDR", /* 3 */ @@ -1738,6 +1738,8 @@ static const char *const request_var_names[] = { "SERVER_PROTOCOL_VERSION_MAJOR", /* 30 */ "SERVER_PROTOCOL_VERSION_MINOR", /* 31 */ "REMOTE_PORT", /* 32 */ + "HTTPS", /* 33 */ + "HTTPS_REMOTE", /* 34 */ NULL }; @@ -1849,6 +1851,12 @@ static const char *request_var_fn(ap_expr_eval_ctx_t *ctx, const void *data) return apr_psprintf(ctx->p, "%d", HTTP_VERSION_MINOR(r->proto_num)); case 32: return apr_psprintf(ctx->p, "%u", ctx->c->client_addr->port); + case 33: + case 34: + if (ap_remote_is_ssl(r)) + return "on"; + else + return "off"; default: ap_assert(0); return NULL; From 21d6bd33b0246b1166f0e918ad8609e6b9a261d6 Mon Sep 17 00:00:00 2001 From: Alex/AT <85214814+AlexAT@users.noreply.github.com> Date: Mon, 27 Mar 2023 01:36:42 +0300 Subject: [PATCH 07/12] Avoid doing any work on internal subrequests or redirects --- modules/metadata/mod_remoteip.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c index ca014006766..0fee4f6b01b 100644 --- a/modules/metadata/mod_remoteip.c +++ b/modules/metadata/mod_remoteip.c @@ -580,6 +580,11 @@ static int remoteip_modify_request(request_rec *r) */ void *internal = NULL; + /* Avoid doing any work on internal subrequests or redirects */ + if (r->main || r->prev) { + return DECLINED; + } + /* No headers defined or results from our input filter */ if (!conn_config && !config->header_name && !config->host_header_name && !config->port_header_name From 0f968f9fe43827c039c94d1ef27eea1bd3807bee Mon Sep 17 00:00:00 2001 From: Alex/AT <85214814+AlexAT@users.noreply.github.com> Date: Mon, 27 Mar 2023 01:44:29 +0300 Subject: [PATCH 08/12] Remove FIXME --- modules/metadata/mod_remoteip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c index 0fee4f6b01b..a6b6a0bebf6 100644 --- a/modules/metadata/mod_remoteip.c +++ b/modules/metadata/mod_remoteip.c @@ -670,7 +670,7 @@ static int remoteip_modify_request(request_rec *r) const char *port; if (!conn_config) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10413) /* FIXME: how to properly set LOGNO in trunk patch? */ + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10413) "Remote IP per-connection data is missing, but required for RemotePortHeader! Aborting request."); return HTTP_BAD_REQUEST; } @@ -691,7 +691,7 @@ static int remoteip_modify_request(request_rec *r) const char *proto; if (!conn_config) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10414) /* FIXME: how to properly set LOGNO in trunk patch? */ + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10414) "Remote IP per-connection data is missing, but required for RemoteProtoHeader! Aborting request."); return HTTP_BAD_REQUEST; } From 1ac4c4fd1fe929e84ae91d42fe3c8f3842de67f4 Mon Sep 17 00:00:00 2001 From: Alex/AT Date: Mon, 27 Mar 2023 07:34:16 +0200 Subject: [PATCH 09/12] Introduce remote_is_https, local_is_https to mod_lua, alias is_https to remote_is_https --- docs/manual/mod/mod_lua.html.en.utf8 | 14 +++++++++++++- docs/manual/mod/mod_lua.xml | 14 +++++++++++++- modules/lua/lua_request.c | 9 +++++++++ modules/lua/mod_lua.c | 5 +++++ modules/lua/mod_lua.h | 1 + 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/docs/manual/mod/mod_lua.html.en.utf8 b/docs/manual/mod/mod_lua.html.en.utf8 index 3d3b4876bd7..019b6edbbb4 100644 --- a/docs/manual/mod/mod_lua.html.en.utf8 +++ b/docs/manual/mod/mod_lua.html.en.utf8 @@ -519,7 +519,19 @@ end is_https boolean no - Whether or not this request is done via HTTPS + Whether or not this request is done via HTTPS (alias to remote_is_https) + + + remote_is_https + boolean + no + Whether or not this request is done via HTTPS locally or on frontend + + + local_is_https + boolean + no + Whether or not the local connection is done via HTTPS is_initial_req diff --git a/docs/manual/mod/mod_lua.xml b/docs/manual/mod/mod_lua.xml index 3a85d6ec8c9..d40ef64ca29 100644 --- a/docs/manual/mod/mod_lua.xml +++ b/docs/manual/mod/mod_lua.xml @@ -484,7 +484,19 @@ end is_https boolean no - Whether or not this request is done via HTTPS + Whether or not this request is done via HTTPS (alias to remote_is_https) + + + remote_is_https + boolean + no + Whether or not this request is done via HTTPS locally or on frontend + + + local_is_https + boolean + no + Whether or not the local connection is done via HTTPS is_initial_req diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c index 35a21a9b376..36a2744835f 100644 --- a/modules/lua/lua_request.c +++ b/modules/lua/lua_request.c @@ -754,6 +754,11 @@ static int req_ssl_is_https_field(request_rec *r) return ap_lua_ssl_is_https(r->connection); } +static int req_remote_is_https_field(request_rec *r) +{ + return ap_lua_remote_is_https(r); +} + static int req_ap_get_server_port(request_rec *r) { return (int) ap_get_server_port(r); @@ -2772,7 +2777,11 @@ void ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p) apr_hash_set(dispatch, "ssl_var_lookup", APR_HASH_KEY_STRING, makefun(&req_ssl_var_lookup, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "is_https", APR_HASH_KEY_STRING, + makefun(&req_remote_is_https_field, APL_REQ_FUNTYPE_BOOLEAN, p)); + apr_hash_set(dispatch, "local_is_https", APR_HASH_KEY_STRING, makefun(&req_ssl_is_https_field, APL_REQ_FUNTYPE_BOOLEAN, p)); + apr_hash_set(dispatch, "remote_is_https", APR_HASH_KEY_STRING, + makefun(&req_remote_is_https_field, APL_REQ_FUNTYPE_BOOLEAN, p)); apr_hash_set(dispatch, "assbackwards", APR_HASH_KEY_STRING, makefun(&req_assbackwards_field, APL_REQ_FUNTYPE_BOOLEAN, p)); apr_hash_set(dispatch, "status", APR_HASH_KEY_STRING, diff --git a/modules/lua/mod_lua.c b/modules/lua/mod_lua.c index 82523dffbc7..36879790f80 100644 --- a/modules/lua/mod_lua.c +++ b/modules/lua/mod_lua.c @@ -1712,6 +1712,11 @@ int ap_lua_ssl_is_https(conn_rec *c) return ap_ssl_conn_is_ssl(c); } +int ap_lua_remote_is_https(request_rec *r) +{ + return ap_remote_is_ssl(r); +} + /*******************************/ static const char *lua_authz_parse(cmd_parms *cmd, const char *require_line, diff --git a/modules/lua/mod_lua.h b/modules/lua/mod_lua.h index 33807fbdb56..c3738f878af 100644 --- a/modules/lua/mod_lua.h +++ b/modules/lua/mod_lua.h @@ -183,5 +183,6 @@ const char *ap_lua_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var); int ap_lua_ssl_is_https(conn_rec *c); +int ap_lua_remote_is_https(request_rec *r); #endif /* !_MOD_LUA_H_ */ From 04e11d226f06accca4830950dc62386aff871cd9 Mon Sep 17 00:00:00 2001 From: Alex/AT <85214814+AlexAT@users.noreply.github.com> Date: Mon, 27 Mar 2023 19:48:34 +0300 Subject: [PATCH 10/12] Increment new error numbers as trunk has been changed --- modules/metadata/mod_remoteip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c index a6b6a0bebf6..d3091de61aa 100644 --- a/modules/metadata/mod_remoteip.c +++ b/modules/metadata/mod_remoteip.c @@ -670,7 +670,7 @@ static int remoteip_modify_request(request_rec *r) const char *port; if (!conn_config) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10413) + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10414) "Remote IP per-connection data is missing, but required for RemotePortHeader! Aborting request."); return HTTP_BAD_REQUEST; } @@ -691,7 +691,7 @@ static int remoteip_modify_request(request_rec *r) const char *proto; if (!conn_config) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10414) + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10415) "Remote IP per-connection data is missing, but required for RemoteProtoHeader! Aborting request."); return HTTP_BAD_REQUEST; } From 3dd1e9e9a43387e852ecea5e5307f3a39cd77371 Mon Sep 17 00:00:00 2001 From: Alex/AT <85214814+AlexAT@users.noreply.github.com> Date: Sun, 2 Apr 2023 12:18:00 +0300 Subject: [PATCH 11/12] Use empty APLOGNO() for new error messages --- modules/metadata/mod_remoteip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c index d3091de61aa..6acafee5e2a 100644 --- a/modules/metadata/mod_remoteip.c +++ b/modules/metadata/mod_remoteip.c @@ -670,7 +670,7 @@ static int remoteip_modify_request(request_rec *r) const char *port; if (!conn_config) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10414) + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO() "Remote IP per-connection data is missing, but required for RemotePortHeader! Aborting request."); return HTTP_BAD_REQUEST; } @@ -691,7 +691,7 @@ static int remoteip_modify_request(request_rec *r) const char *proto; if (!conn_config) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10415) + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO() "Remote IP per-connection data is missing, but required for RemoteProtoHeader! Aborting request."); return HTTP_BAD_REQUEST; } From b6f00fb55b2983e2cf013260960f3bd126d3418e Mon Sep 17 00:00:00 2001 From: Alex/AT <85214814+AlexAT@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:42:40 +0300 Subject: [PATCH 12/12] Lost comment close in previous commit --- include/ap_mmn.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 659e97255dc..c4d53d9e027 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -726,6 +726,7 @@ * 20211221.20 (2.5.1-dev) Add CONN_STATE_KEEPALIVE and CONN_STATE_PROCESSING * 20211221.21 (2.5.1-dev) Add processing field struct process_score * 20211221.22 (2.5.1-dev) Add ap_remote_is_ssl() and hooks +*/ #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */