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

Reply via email to