From: Sander Striker Date: Tue, 11 Jan 2005 08:35:46 +0000 (+0000) Subject: Rewrite Cookies and other headers in mod_proxy_ajp as configured with X-Git-Tag: 2.1.3~161 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46ba14216d31e7c9f29d506c799396ecc15576a3;p=thirdparty%2Fapache%2Fhttpd.git Rewrite Cookies and other headers in mod_proxy_ajp as configured with ProxyPassReverse and ProxyPassReverseCookiePath. * modules/proxy/proxy_ajp.c (ap_proxy_ajp_request): Update call to ajp_parse_header(). * modules/proxy/ajp.h (ajp_msg_get_string): constify argument. (ajp_parse_header): Add conf argument. * modules/proxy/proxy_util.c (ap_proxy_location_reverse_map): Promoted from mod_proxy_http. (ap_proxy_cookie_reverse_map): Promoted from mod_proxy_http; renamed from proxy_cookie_reverse_map. * modules/proxy/ajp_msg.c (ajp_msg_get_string): constify argument. * modules/proxy/proxy_http.c (ap_proxy_location_reverse_map, proxy_cookie_reverse_map: Removed. (process_proxy_header): Update header mapping table to reference the now public functions. * modules/proxy/ajp_header.c (ajp_unmarshal_response): And conf argument. Reverse map cookies and other headers. (ajp_parse_header): Update call to ajp_unmarshal_response(). * modules/proxy/mod_proxy.h (ap_proxy_location_reverse_map, ap_proxy_cookie_reverse_map): Declare functions that have been promoted to be public. (ap_proxy_header_reverse_map_fn): Typedef for the signature of the above two functions (currently used in mod_proxy_http). git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@124901 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/ajp.h b/modules/proxy/ajp.h index c7978b8bb13..dd5ccf12721 100644 --- a/modules/proxy/ajp.h +++ b/modules/proxy/ajp.h @@ -79,6 +79,8 @@ #include "http_log.h" #endif +#include "mod_proxy.h" + /** AJP Specific error codes */ @@ -296,7 +298,7 @@ apr_status_t ajp_msg_peek_uint8(ajp_msg_t *msg, apr_byte_t *rvalue); * @param rvalue Pointer where value will be returned * @return APR_SUCCESS or error */ -apr_status_t ajp_msg_get_string(ajp_msg_t *msg, char **rvalue); +apr_status_t ajp_msg_get_string(ajp_msg_t *msg, const char **rvalue); /** @@ -436,7 +438,8 @@ int ajp_parse_type(request_rec *r, ajp_msg_t *msg); * @param msg AJP message * @return APR_SUCCESS or error */ -apr_status_t ajp_parse_header(request_rec *r, ajp_msg_t *msg); +apr_status_t ajp_parse_header(request_rec *r, proxy_server_conf *conf, + ajp_msg_t *msg); /** * Parse the message body and return data address and length diff --git a/modules/proxy/ajp_header.c b/modules/proxy/ajp_header.c index 30110e523f7..b41f0cc8edb 100644 --- a/modules/proxy/ajp_header.c +++ b/modules/proxy/ajp_header.c @@ -446,8 +446,9 @@ body_chunk := */ -static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg, - request_rec *r) +static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg, + request_rec *r, + proxy_server_conf *conf) { apr_uint16_t status; apr_status_t rc; @@ -491,8 +492,8 @@ static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg, for(i = 0 ; i < (int) num_headers ; i++) { apr_uint16_t name; - char *stringname; - char *value; + const char *stringname; + const char *value; rc = ajp_msg_peek_uint16(msg, &name); if (rc != APR_SUCCESS) { return APR_EGENERAL; @@ -500,7 +501,7 @@ static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg, if ((name & 0XFF00) == 0XA000) { ajp_msg_peek_uint16(msg, &name); - stringname = (char *)long_res_header_for_sc(name); + stringname = long_res_header_for_sc(name); if (stringname == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "Error ajp_unmarshal_response - " @@ -530,12 +531,25 @@ static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg, return APR_EGENERAL; } + /* Set-Cookie need additional processing */ + if (!strcasecmp(stringname, "Set-Cookie")) { + value = ap_proxy_cookie_reverse_map(r, conf, value); + } + /* Location, Content-Location and URI need additional processing */ + else if (!strcasecmp(stringname, "Location") + || !strcasecmp(stringname, "Content-Location") + || !strcasecmp(stringname, "URI")) + { + value = ap_proxy_location_reverse_map(r, conf, value); + } + #if defined(AS400) || defined(_OSD_POSIX) ap_xlate_proto_from_ascii(value, strlen(value)); #endif ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "ajp_unmarshal_response: Header[%d] [%s] = [%s]", i, stringname, value); + apr_table_add(r->headers_out, stringname, value); /* Content-type needs an additional handling */ @@ -624,7 +638,8 @@ int ajp_parse_type(request_rec *r, ajp_msg_t *msg) } /* parse the header */ -apr_status_t ajp_parse_header(request_rec *r, ajp_msg_t *msg) +apr_status_t ajp_parse_header(request_rec *r, proxy_server_conf *conf, + ajp_msg_t *msg) { apr_byte_t result; apr_status_t rc; @@ -640,7 +655,7 @@ apr_status_t ajp_parse_header(request_rec *r, ajp_msg_t *msg) "ajp_parse_headers: wrong type %02x expecting 0x04", result); return APR_EGENERAL; } - return ajp_unmarshal_response(msg, r); + return ajp_unmarshal_response(msg, r, conf); } /* parse the body and return data address and length */ diff --git a/modules/proxy/ajp_msg.c b/modules/proxy/ajp_msg.c index 19c07efea49..dec58502f49 100644 --- a/modules/proxy/ajp_msg.c +++ b/modules/proxy/ajp_msg.c @@ -417,7 +417,7 @@ apr_status_t ajp_msg_get_uint8(ajp_msg_t *msg, apr_byte_t *rvalue) * @param rvalue Pointer where value will be returned * @return APR_SUCCESS or error */ -apr_status_t ajp_msg_get_string(ajp_msg_t *msg, char **rvalue) +apr_status_t ajp_msg_get_string(ajp_msg_t *msg, const char **rvalue) { apr_uint16_t size; apr_size_t start; @@ -433,7 +433,7 @@ apr_status_t ajp_msg_get_string(ajp_msg_t *msg, char **rvalue) msg->pos += (apr_size_t)size; msg->pos++; /* a String in AJP is NULL terminated */ - *rvalue = (char *)(msg->buf + start); + *rvalue = (const char *)(msg->buf + start); return APR_SUCCESS; } diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index b26265f4724..db403d104f3 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -399,6 +399,27 @@ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, ap PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c); PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c); +/* Header mapping functions, and a typedef of their signature */ +PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url); +PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_server_conf *conf, const char *str); + +#if !defined(WIN32) +typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *, + proxy_server_conf *, const char *); +#elif defined(PROXY_DECLARE_STATIC) +typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *, + proxy_server_conf *, const char *); +#elif defined(PROXY_DECLARE_EXPORT) +typedef __declspec(dllexport) const char * + (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *, + proxy_server_conf *, const char *); +#else +typedef __declspec(dllimport) const char * + (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *, + proxy_server_conf *, const char *); +#endif + + /* Connection pool API */ /** * Get the worker from proxy configuration diff --git a/modules/proxy/proxy_ajp.c b/modules/proxy/proxy_ajp.c index 03903edaf36..7eec49b179c 100644 --- a/modules/proxy/proxy_ajp.c +++ b/modules/proxy/proxy_ajp.c @@ -261,7 +261,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, break; case CMD_AJP13_SEND_HEADERS: /* AJP13_SEND_HEADERS: process them */ - status = ajp_parse_header(r, conn->data); + status = ajp_parse_header(r, conf, conn->data); if (status != APR_SUCCESS) { isok=0; } diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c index 062dad1026a..57cfd6367de 100644 --- a/modules/proxy/proxy_http.c +++ b/modules/proxy/proxy_http.c @@ -95,121 +95,6 @@ static int proxy_http_canon(request_rec *r, char *url) "/", path, (search) ? "?" : "", (search) ? search : "", NULL); return OK; } - -static const char *ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url) -{ - struct proxy_alias *ent; - int i, l1, l2; - char *u; - - /* XXX FIXME: Make sure this handled the ambiguous case of the :80 - * after the hostname */ - - l1 = strlen(url); - ent = (struct proxy_alias *)conf->raliases->elts; - for (i = 0; i < conf->raliases->nelts; i++) { - l2 = strlen(ent[i].real); - if (l1 >= l2 && strncasecmp(ent[i].real, url, l2) == 0) { - u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL); - return ap_construct_url(r->pool, u, r); - } - } - return url; -} -/* cookies are a bit trickier to match: we've got two substrings to worry - * about, and we can't just find them with strstr 'cos of case. Regexp - * matching would be an easy fix, but for better consistency with all the - * other matches we'll refrain and use apr_strmatch to find path=/domain= - * and stick to plain strings for the config values. - */ -static const char *proxy_cookie_reverse_map(request_rec *r, - proxy_server_conf *conf, const char *str) -{ - struct proxy_alias *ent; - size_t len = strlen(str); - const char* newpath = NULL ; - const char* newdomain = NULL ; - const char* pathp ; - const char* domainp ; - const char* pathe = NULL; - const char* domaine = NULL; - size_t l1, l2, poffs = 0, doffs = 0 ; - int i; - int ddiff = 0 ; - int pdiff = 0 ; - char* ret ; - -/* find the match and replacement, but save replacing until we've done - both path and domain so we know the new strlen -*/ - if ( pathp = apr_strmatch(conf->cookie_path_str, str, len) , pathp ) { - pathp += 5 ; - poffs = pathp - str ; - pathe = ap_strchr_c(pathp, ';') ; - l1 = pathe ? (pathe-pathp) : strlen(pathp) ; - pathe = pathp + l1 ; - ent = (struct proxy_alias *)conf->cookie_paths->elts; - for (i = 0; i < conf->cookie_paths->nelts; i++) { - l2 = strlen(ent[i].fake); - if (l1 >= l2 && strncmp(ent[i].fake, pathp, l2) == 0) { - newpath = ent[i].real ; - pdiff = strlen(newpath) - l1 ; - break ; - } - } - } - if ( domainp = apr_strmatch(conf->cookie_domain_str, str, len) , domainp ) { - domainp += 7 ; - doffs = domainp - str ; - domaine = ap_strchr_c(domainp, ';') ; - l1 = domaine ? (domaine-domainp) : strlen(domainp) ; - domaine = domainp + l1 ; - ent = (struct proxy_alias *)conf->cookie_domains->elts; - for (i = 0; i < conf->cookie_domains->nelts; i++) { - l2 = strlen(ent[i].fake); - if (l1 >= l2 && strncasecmp(ent[i].fake, domainp, l2) == 0) { - newdomain = ent[i].real ; - ddiff = strlen(newdomain) - l1 ; - break ; - } - } - } - if ( newpath ) { - ret = apr_palloc(r->pool, len+pdiff+ddiff+1) ; - l1 = strlen(newpath) ; - if ( newdomain ) { - l2 = strlen(newdomain) ; - if ( doffs > poffs ) { - memcpy(ret, str, poffs) ; - memcpy(ret+poffs, newpath, l1) ; - memcpy(ret+poffs+l1, pathe, domainp-pathe) ; - memcpy(ret+doffs+pdiff, newdomain, l2) ; - strcpy(ret+doffs+pdiff+l2, domaine) ; - } else { - memcpy(ret, str, doffs) ; - memcpy(ret+doffs, newdomain, l2) ; - memcpy(ret+doffs+l2, domaine, pathp-domaine) ; - memcpy(ret+poffs+ddiff, newpath, l1) ; - strcpy(ret+poffs+ddiff+l1, pathe) ; - } - } else { - memcpy(ret, str, poffs) ; - memcpy(ret+poffs, newpath, l1) ; - strcpy(ret+poffs+l1, pathe) ; - } - } else { - if ( newdomain ) { - ret = apr_palloc(r->pool, len+pdiff+ddiff+1) ; - l2 = strlen(newdomain) ; - memcpy(ret, str, doffs) ; - memcpy(ret+doffs, newdomain, l2) ; - strcpy(ret+doffs+l2, domaine) ; - } else { - ret = (char*) str ; /* no change */ - } - } - return ret ; -} /* Clear all connection-based headers from the incoming headers table */ static void ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers) @@ -643,19 +528,20 @@ apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r, apr_brigade_cleanup(body_brigade); return APR_SUCCESS; } + static void process_proxy_header(request_rec* r, proxy_server_conf* c, const char* key, const char* value) { static const char* date_hdrs[] = { "Date", "Expires", "Last-Modified", NULL } ; static const struct { - const char* name ; - const char* (*func)(request_rec*, proxy_server_conf*, const char*) ; + const char* name; + ap_proxy_header_reverse_map_fn func; } transform_hdrs[] = { { "Location", ap_proxy_location_reverse_map } , { "Content-Location", ap_proxy_location_reverse_map } , { "URI", ap_proxy_location_reverse_map } , - { "Set-Cookie", proxy_cookie_reverse_map } , + { "Set-Cookie", ap_proxy_cookie_reverse_map } , { NULL, NULL } } ; int i ; diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 5defd0c7ded..5c43fdee85e 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -997,6 +997,131 @@ PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char * apr_table_add(t, key, value + offset); } +PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, + proxy_server_conf *conf, const char *url) +{ + struct proxy_alias *ent; + int i, l1, l2; + char *u; + + /* XXX FIXME: Make sure this handled the ambiguous case of the : + * after the hostname */ + + l1 = strlen(url); + ent = (struct proxy_alias *)conf->raliases->elts; + for (i = 0; i < conf->raliases->nelts; i++) { + l2 = strlen(ent[i].real); + if (l1 >= l2 && strncasecmp(ent[i].real, url, l2) == 0) { + u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL); + return ap_construct_url(r->pool, u, r); + } + } + + return url; +} + +/* Cookies are a bit trickier to match: we've got two substrings to worry + * about, and we can't just find them with strstr 'cos of case. Regexp + * matching would be an easy fix, but for better consistency with all the + * other matches we'll refrain and use apr_strmatch to find path=/domain= + * and stick to plain strings for the config values. + */ +PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, + proxy_server_conf *conf, const char *str) +{ + struct proxy_alias *ent; + size_t len = strlen(str); + const char *newpath = NULL; + const char *newdomain = NULL; + const char *pathp; + const char *domainp; + const char *pathe = NULL; + const char *domaine = NULL; + size_t l1, l2, poffs = 0, doffs = 0; + int i; + int ddiff = 0; + int pdiff = 0; + char *ret; + + /* Find the match and replacement, but save replacing until we've done + * both path and domain so we know the new strlen + */ + if (pathp = apr_strmatch(conf->cookie_path_str, str, len) ,pathp) { + pathp += 5 ; + poffs = pathp - str; + pathe = ap_strchr_c(pathp, ';'); + l1 = pathe ? (pathe - pathp) : strlen(pathp); + pathe = pathp + l1 ; + ent = (struct proxy_alias *)conf->cookie_paths->elts; + for (i = 0; i < conf->cookie_paths->nelts; i++) { + l2 = strlen(ent[i].fake); + if (l1 >= l2 && strncmp(ent[i].fake, pathp, l2) == 0) { + newpath = ent[i].real; + pdiff = strlen(newpath) - l1; + break; + } + } + } + + if (domainp = apr_strmatch(conf->cookie_domain_str, str, len), domainp) { + domainp += 7; + doffs = domainp - str; + domaine = ap_strchr_c(domainp, ';'); + l1 = domaine ? (domaine - domainp) : strlen(domainp); + domaine = domainp + l1; + ent = (struct proxy_alias *)conf->cookie_domains->elts; + for (i = 0; i < conf->cookie_domains->nelts; i++) { + l2 = strlen(ent[i].fake); + if (l1 >= l2 && strncasecmp(ent[i].fake, domainp, l2) == 0) { + newdomain = ent[i].real; + ddiff = strlen(newdomain) - l1; + break; + } + } + } + + if (newpath) { + ret = apr_palloc(r->pool, len + pdiff + ddiff + 1); + l1 = strlen(newpath); + if (newdomain) { + l2 = strlen(newdomain); + if (doffs > poffs) { + memcpy(ret, str, poffs); + memcpy(ret + poffs, newpath, l1); + memcpy(ret + poffs + l1, pathe, domainp - pathe); + memcpy(ret + doffs + pdiff, newdomain, l2); + strcpy(ret + doffs + pdiff + l2, domaine); + } + else { + memcpy(ret, str, doffs) ; + memcpy(ret + doffs, newdomain, l2); + memcpy(ret + doffs + l2, domaine, pathp - domaine); + memcpy(ret + poffs + ddiff, newpath, l1); + strcpy(ret + poffs + ddiff + l1, pathe); + } + } + else { + memcpy(ret, str, poffs); + memcpy(ret + poffs, newpath, l1); + strcpy(ret + poffs + l1, pathe); + } + } + else { + if (newdomain) { + ret = apr_palloc(r->pool, len + pdiff + ddiff + 1); + l2 = strlen(newdomain); + memcpy(ret, str, doffs); + memcpy(ret + doffs, newdomain, l2); + strcpy(ret + doffs+l2, domaine); + } + else { + ret = (char *)str; /* no change */ + } + } + + return ret; +} + PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p, proxy_server_conf *conf, const char *url)