Package: lighttpd Version: 1.4.31-1 Severity: important Tags: upstream patch Forwarded: http://redmine.lighttpd.net/issues/2434
Hi folks, unless I missed some docs, there's no way of forwarding environment variables such as the SSL_* ones (which are set when one uses a client certificate), through mod_proxy. I've just submitted a patch upstream to add support for forwarding environment variables (but not just those): http://redmine.lighttpd.net/issues/2434 http://redmine.lighttpd.net/attachments/download/1379/0001-mod_proxy-Make-it-possible-to-forward-environment-va.patch It looks to me like an important misssing feature in lighttpd, and might be worth trying to get into wheezy (even if I won't be the one reviewing the patch on the release team side, for obvious reasons). Thanks for considering. Mraw, KiBi.
>From 88ba376bec3503daf06bb3129b0b89177169f6b9 Mon Sep 17 00:00:00 2001 From: Cyril Brulebois <k...@debian.org> Date: Mon, 13 Aug 2012 22:20:07 +0200 Subject: [PATCH] [mod_proxy] Make it possible to forward environment variables. Even if the original goal was to forward X509/SSL-related variables, it was easy to generalize that to any environment variable. This adds a proxy.forward-env-vars config string, which is a list of comma-separated variables to be forwarded. Signed-off-by: Cyril Brulebois <k...@debian.org> --- doc/config/conf.d/proxy.conf | 7 ++++++ src/mod_proxy.c | 51 ++++++++++++++++++++++++++++++++++++++++++ tests/proxy.conf | 2 ++ 3 files changed, 60 insertions(+) diff --git a/doc/config/conf.d/proxy.conf b/doc/config/conf.d/proxy.conf index f0552c2..df1eb92 100644 --- a/doc/config/conf.d/proxy.conf +++ b/doc/config/conf.d/proxy.conf @@ -18,6 +18,13 @@ server.modules += ( "mod_proxy" ) ## might be one of 'hash', 'round-robin' or 'fair' (default). ## #proxy.balance = "fair" + + +## +## a comma-separated string with the variables to be forwarded through +## X-... headers +## +#proxy.forward-env-vars = "SSL_CLIENT_S_DN_x500UniqueIdentifier,SSL_CLIENT_S_DN_emailAddress" ## ## Handle all jsp requests via 192.168.0.101 diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 06fe3db..1295b37 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -73,6 +73,7 @@ typedef struct { buffer *parse_response; buffer *balance_buf; + char **forward_env_vars; plugin_config **config_storage; @@ -149,6 +150,7 @@ INIT_FUNC(mod_proxy_init) { p->parse_response = buffer_init(); p->balance_buf = buffer_init(); + p->forward_env_vars = NULL; return p; } @@ -162,6 +164,13 @@ FREE_FUNC(mod_proxy_free) { buffer_free(p->parse_response); buffer_free(p->balance_buf); + /* walk the array of environment variables to free them, if any */ + char **forward_env_vars_ptr = p->forward_env_vars; + while (forward_env_vars_ptr && *forward_env_vars_ptr) { + free(*forward_env_vars_ptr++); + } + free(p->forward_env_vars); + if (p->config_storage) { size_t i; for (i = 0; i < srv->config_context->used; i++) { @@ -191,6 +200,7 @@ SETDEFAULTS_FUNC(mod_proxy_set_defaults) { { "proxy.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "proxy.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "proxy.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ + { "proxy.forward-env-vars", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -231,6 +241,36 @@ SETDEFAULTS_FUNC(mod_proxy_set_defaults) { return HANDLER_ERROR; } + if (NULL != (du = array_get_element(ca, "proxy.forward-env-vars"))) { + data_string *ds = (data_string *)du; + if (ds != NULL) { + char *ptr, *prev; + int parts = 1; + /* count the parts */ + for (ptr = ds->value->ptr; *ptr; ptr++) + if (*ptr == ',') + parts++; + /* cheat a bit to ease with strchr() */ + *ptr = ','; + /* do the real split work */ + p->forward_env_vars = (char **)malloc((parts+1) * sizeof(char*)); + prev = ds->value->ptr; + for (int j=0; j<parts; j++) { + ptr = strchr(prev+1, ','); + p->forward_env_vars[j] = (char *)malloc(ptr-prev+1); + strncpy(p->forward_env_vars[j], prev, ptr-prev+1); + p->forward_env_vars[j][ptr-prev] = '\0'; + prev = ptr+1; + } + /* NULL-terminate the array to ease walking it */ + p->forward_env_vars[parts] = NULL; + } else { + log_error_write(srv, __FILE__, __LINE__, "sb", + "proxy.forward-env-vars has to be a string"); + return HANDLER_ERROR; + } + } + if (NULL != (du = array_get_element(ca, "proxy.server"))) { size_t j; data_array *da = (data_array *)du; @@ -441,6 +481,7 @@ static void proxy_append_header(connection *con, const char *key, const char *va static int proxy_create_env(server *srv, handler_ctx *hctx) { size_t i; + char **forward_env_vars_ptr = hctx->plugin_data->forward_env_vars; connection *con = hctx->remote_conn; buffer *b; @@ -456,6 +497,16 @@ static int proxy_create_env(server *srv, handler_ctx *hctx) { buffer_append_string_buffer(b, con->request.uri); buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.0\r\n")); + /* walk the array of environment variables to forward, if any */ + while (forward_env_vars_ptr && *forward_env_vars_ptr) { + char forward_env_header[4096]; + snprintf(forward_env_header, sizeof(forward_env_header), "X-%s", *forward_env_vars_ptr); + data_string *key_ds = (data_string *)array_get_element(hctx->remote_conn->environment, *forward_env_vars_ptr); + if (key_ds != NULL) + proxy_set_header(con, forward_env_header, key_ds->value->ptr); + forward_env_vars_ptr++; + } + proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr))); /* http_host is NOT is just a pointer to a buffer * which is NULL if it is not set */ diff --git a/tests/proxy.conf b/tests/proxy.conf index 2e959ac..fd8b148 100644 --- a/tests/proxy.conf +++ b/tests/proxy.conf @@ -76,6 +76,8 @@ proxy.server = ( "" => ( ) ) +proxy.forward-env-vars = "SSL_CLIENT_S_DN_x500UniqueIdentifier,SSL_CLIENT_S_DN_emailAddress" + cgi.assign = ( ".pl" => "/usr/bin/perl", ".cgi" => "/usr/bin/perl", -- 1.7.10.4