Nico Golde wrote:
Hi,
I can confirm this the lighttpd developers are right.
The vulnerable code is still present in -etch3.
Kind regards
Nico
Minimal patch included, I'll test it.
I wonder if we can just use mod_fastcgi.c from unstable, additional
changes (after this minimal patch) are very small.
eloy
--
[EMAIL PROTECTED]
jak to dobrze, że są oceany - bez nich byłoby jeszcze smutniej
--- mod_fastcgi.c.orig 2007-09-12 15:48:49.000000000 +0200
+++ mod_fastcgi.c 2007-09-12 16:21:16.000000000 +0200
@@ -54,6 +54,12 @@
#include <sys/wait.h>
#endif
+#define FCGI_ENV_ADD_CHECK(ret, con) \
+ if (ret == -1) { \
+ con->http_status = 400; \
+ con->file_finished = 1; \
+ return -1; \
+ };
/*
*
@@ -1568,6 +1574,22 @@
len += key_len > 127 ? 4 : 1;
len += val_len > 127 ? 4 : 1;
+ if (env->used + len >= FCGI_MAX_LENGTH) {
+ /**
+ * we can't append more headers, ignore it
+ */
+ return -1;
+ }
+
+ /**
+ * field length can be 31bit max
+ *
+ * HINT: this can't happen as FCGI_MAX_LENGTH is only 16bit
+ */
+ if (key_len > 0x7fffffff) key_len = 0x7fffffff;
+ if (val_len > 0x7fffffff) val_len = 0x7fffffff;
+
+
buffer_prepare_append(env, len);
if (key_len > 127) {
@@ -1597,6 +1619,9 @@
}
static int fcgi_header(FCGI_Header * header, unsigned char type, size_t request_id, int contentLength, unsigned char paddingLength) {
+
+ assert(contentLength <= FCGI_MAX_LENGTH);
+
header->version = FCGI_VERSION_1;
header->type = type;
header->requestIdB0 = request_id & 0xff;
@@ -1751,7 +1776,7 @@
}
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
- fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value)), con);
}
}
@@ -1777,8 +1802,8 @@
srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
}
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
-
- fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
+
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value)), con);
}
}
@@ -1822,10 +1847,10 @@
buffer_prepare_copy(p->fcgi_env, 1024);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION)),con)
if (con->server_name->used) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name)),con)
} else {
#ifdef HAVE_IPV6
s = inet_ntop(srv_sock->addr.plain.sa_family,
@@ -1836,10 +1861,10 @@
#else
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
#endif
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s)),con)
}
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1")),con)
ltostr(buf,
#ifdef HAVE_IPV6
@@ -1849,7 +1874,7 @@
#endif
);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf)),con)
/* get the server-side of the connection to the client */
our_addr_len = sizeof(our_addr);
@@ -1859,7 +1884,7 @@
} else {
s = inet_ntop_cache_get_ip(srv, &(our_addr));
}
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s)),con)
ltostr(buf,
#ifdef HAVE_IPV6
@@ -1869,14 +1894,13 @@
#endif
);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf)),con)
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)),con)
if (!buffer_is_empty(con->authed_user)) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
- CONST_BUF_LEN(con->authed_user));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"), CONST_BUF_LEN(con->authed_user)),con)
}
if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
@@ -1884,7 +1908,7 @@
/* request.content_length < SSIZE_MAX, see request.c */
ltostr(buf, con->request.content_length);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf)),con)
}
if (host->mode != FCGI_AUTHORIZER) {
@@ -1895,10 +1919,10 @@
* For AUTHORIZER mode these headers should be omitted.
*/
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path)),con)
if (!buffer_is_empty(con->request.pathinfo)) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo)),con)
/* PATH_TRANSLATED is only defined if PATH_INFO is set */
@@ -1908,9 +1932,9 @@
buffer_copy_string_buffer(p->path, con->physical.doc_root);
}
buffer_append_string_buffer(p->path, con->request.pathinfo);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_TRANSLATED"), CONST_BUF_LEN(p->path));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_TRANSLATED"), CONST_BUF_LEN(p->path)),con)
} else {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_STR_LEN(""));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_STR_LEN("")),con)
}
}
@@ -1931,8 +1955,8 @@
buffer_copy_string_buffer(p->path, host->docroot);
buffer_append_string_buffer(p->path, con->uri.path);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path)),con)
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot)),con)
} else {
buffer_copy_string_buffer(p->path, con->physical.path);
@@ -1944,8 +1968,8 @@
buffer_append_string_buffer(p->path, con->request.pathinfo);
}
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path)),con)
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root)),con)
}
if (host->strip_request_uri->used > 1) {
@@ -1967,38 +1991,38 @@
0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
/* the left is the same */
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
- con->request.orig_uri->used - (host->strip_request_uri->used - 2));
+ con->request.orig_uri->used - (host->strip_request_uri->used - 2)),con)
} else {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri)),con)
}
} else {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri)),con)
}
if (!buffer_is_equal(con->request.uri, con->request.orig_uri)) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_URI"), CONST_BUF_LEN(con->request.uri));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_URI"), CONST_BUF_LEN(con->request.uri)),con)
}
if (!buffer_is_empty(con->uri.query)) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query)),con)
} else {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN("")),con)
}
s = get_http_method_name(con->request.http_method);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s)),con)
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")),con) /* if php is compiled with --force-redirect */
s = get_http_version_name(con->request.http_version);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)),con)
#ifdef USE_OPENSSL
if (srv_sock->is_ssl) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on")),con)
}
#endif
- fcgi_env_add_request_headers(srv, con, p);
+ FCGI_ENV_ADD_CHECK(fcgi_env_add_request_headers(srv, con, p), con);
fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
buffer_append_memory(b, (const char *)&header, sizeof(header));
@@ -2880,8 +2904,7 @@
}
/* fall through */
- fcgi_create_env(srv, hctx, hctx->request_id);
-
+ if (-1 == fcgi_create_env(srv, hctx, hctx->request_id)) return HANDLER_ERROR;
fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
/* fall through */
@@ -3058,7 +3081,7 @@
buffer_reset(con->physical.path);
con->mode = DIRECT;
- con->http_status = 503;
+ if (con->http_status != 400) con->http_status = 503;
joblist_append(srv, con); /* really ? */
return HANDLER_FINISHED;