You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by fi...@hyperreal.org on 1998/08/10 06:16:17 UTC
cvs commit: apache-1.3/src/main http_config.c http_core.c http_protocol.c
fielding 98/08/09 21:16:16
Modified: src CHANGES
src/include http_config.h http_core.h httpd.h
src/main http_config.c http_core.c http_protocol.c
Log:
Fixed request limit change to be more portable. Removed the server_rec
variables since compile-time control of the request-line, fieldsize, and
number of fields is sufficient. Added a per-dir configuration directive
LimitRequestBody for setting a maximum request message body, with the
default of 0 meaning no limit.
Revision Changes Path
1.1015 +3 -2 apache-1.3/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1014
retrieving revision 1.1015
diff -u -r1.1014 -r1.1015
--- CHANGES 1998/08/10 00:10:18 1.1014
+++ CHANGES 1998/08/10 04:16:11 1.1015
@@ -3,10 +3,11 @@
*) SECURITY: Eliminate O(n^2) space DoS attacks (and other O(n^2)
cpu time attacks) in header parsing. [Dean Gaudet]
- *) SECURITY: Added default limits for various aspects of reading a
+ *) SECURITY: Added compile-time limits for various aspects of reading a
client request to avoid some simple denial of service attacks,
including limits on maximum request-line size, number of header
- fields, size of any one header field, and size of the request
+ fields, and size of any one header field. Also added a configurable
+ directive LimitRequestBody for limiting the size of the request
message body. [Roy Fielding]
*) Make status module aware of DNS and logging states, even if
1.93 +1 -1 apache-1.3/src/include/http_config.h
Index: http_config.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/http_config.h,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -r1.92 -r1.93
--- http_config.h 1998/08/09 06:37:15 1.92
+++ http_config.h 1998/08/10 04:16:12 1.93
@@ -275,7 +275,7 @@
* handle it back-compatibly, or at least signal an error).
*/
-#define MODULE_MAGIC_NUMBER 19980808
+#define MODULE_MAGIC_NUMBER 19980809
#define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER, -1, __FILE__, NULL, NULL
/* Generic accessors for other modules to get at their own module-specific
1.47 +2 -0 apache-1.3/src/include/http_core.h
Index: http_core.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/http_core.h,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -r1.46 -r1.47
--- http_core.h 1998/08/06 19:23:43 1.46
+++ http_core.h 1998/08/10 04:16:13 1.47
@@ -131,6 +131,7 @@
API_EXPORT(char *) ap_construct_url(pool *p, const char *uri, const request_rec *r);
API_EXPORT(const char *) ap_get_server_name(const request_rec *r);
API_EXPORT(unsigned) ap_get_server_port(const request_rec *r);
+API_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r);
API_EXPORT(void) ap_custom_response(request_rec *r, int status, char *string);
/* Authentication stuff. This is one of the places where compatibility
@@ -236,6 +237,7 @@
#ifdef RLIMIT_NPROC
struct rlimit *limit_nproc;
#endif
+ unsigned long limit_req_body; /* limit on bytes in request msg body */
/* logging options */
enum { srv_sig_off, srv_sig_on, srv_sig_withmail } server_signature;
1.233 +18 -27 apache-1.3/src/include/httpd.h
Index: httpd.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/httpd.h,v
retrieving revision 1.232
retrieving revision 1.233
diff -u -r1.232 -r1.233
--- httpd.h 1998/08/09 16:57:28 1.232
+++ httpd.h 1998/08/10 04:16:13 1.233
@@ -369,6 +369,24 @@
#define DEFAULT_LISTENBACKLOG 511
#endif
+/* Limits on the size of various request items. These limits primarily
+ * exist to prevent simple denial-of-service attacks on a server based
+ * on misuse of the protocol. The recommended values will depend on the
+ * nature of the server resources -- CGI scripts and database backends
+ * might require large values, but most servers could get by with much
+ * smaller limits than we use below. The request message body size can
+ * be limited by the per-dir config directive LimitRequestBody.
+ */
+#ifndef AP_LIMIT_REQUEST_LINE
+#define AP_LIMIT_REQUEST_LINE 8192
+#endif /* default limit on bytes in Request-Line (Method+URI+HTTP-version) */
+#ifndef AP_LIMIT_REQUEST_FIELDS
+#define AP_LIMIT_REQUEST_FIELDS 100
+#endif /* default limit on number of request header fields */
+#ifndef AP_LIMIT_REQUEST_FIELDSIZE
+#define AP_LIMIT_REQUEST_FIELDSIZE 8192
+#endif /* default limit on bytes in any one header field */
+
/*
* The below defines the base string of the Server: header. Additional
* tokens can be added via the ap_add_version_component() API call.
@@ -541,28 +559,6 @@
#define REQUEST_CHUNKED_DECHUNK 2
#define REQUEST_CHUNKED_PASS 3
-/* Limits on the size of various request items. These limits primarily
- * exist to prevent simple denial-of-service attacks on a server based
- * on misuse of the protocol. The recommended values will depend on the
- * nature of the server resources -- CGI scripts and database backends
- * might require large values, but most servers could get by with much
- * smaller limits than we use below. These limits can be reset on a
- * per-server basis using the LimitRequestLine, LimitRequestFields,
- * LimitRequestFieldSize, and LimitRequestBody configuration directives.
- */
-#ifndef DEFAULT_LIMIT_REQUEST_LINE
-#define DEFAULT_LIMIT_REQUEST_LINE 8192
-#endif /* default limit on bytes in Request-Line (Method+URI+HTTP-version) */
-#ifndef DEFAULT_LIMIT_REQUEST_FIELDS
-#define DEFAULT_LIMIT_REQUEST_FIELDS 100
-#endif /* default limit on number of header fields */
-#ifndef DEFAULT_LIMIT_REQUEST_FIELDSIZE
-#define DEFAULT_LIMIT_REQUEST_FIELDSIZE 8192
-#endif /* default limit on bytes in any one field */
-#ifndef DEFAULT_LIMIT_REQUEST_BODY
-#define DEFAULT_LIMIT_REQUEST_BODY 33554432ul
-#endif /* default limit on bytes in request body */
-
/* Things which may vary per file-lookup WITHIN a request ---
* e.g., state of MIME config. Basically, the name of an object, info
* about the object, and any other info we may ahve which may need to
@@ -846,11 +842,6 @@
uid_t server_uid; /* effective user id when calling exec wrapper */
gid_t server_gid; /* effective group id when calling exec wrapper */
-
- unsigned int limit_req_line; /* limit on bytes in Request-Line */
- unsigned int limit_req_fields; /* limit on number of header fields */
- unsigned long limit_req_fieldsize; /* limit on bytes in any one field */
- unsigned long limit_req_body; /* limit on bytes in request body */
};
/* These are more like real hosts than virtual hosts */
1.121 +0 -4 apache-1.3/src/main/http_config.c
Index: http_config.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_config.c,v
retrieving revision 1.120
retrieving revision 1.121
diff -u -r1.120 -r1.121
--- http_config.c 1998/08/09 06:37:17 1.120
+++ http_config.c 1998/08/10 04:16:14 1.121
@@ -1409,10 +1409,6 @@
s->loglevel = DEFAULT_LOGLEVEL;
s->srm_confname = RESOURCE_CONFIG_FILE;
s->access_confname = ACCESS_CONFIG_FILE;
- s->limit_req_line = DEFAULT_LIMIT_REQUEST_LINE;
- s->limit_req_fields = DEFAULT_LIMIT_REQUEST_FIELDS;
- s->limit_req_fieldsize = DEFAULT_LIMIT_REQUEST_FIELDSIZE;
- s->limit_req_body = DEFAULT_LIMIT_REQUEST_BODY;
s->timeout = DEFAULT_TIMEOUT;
s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
s->keep_alive_max = DEFAULT_KEEPALIVE;
1.219 +26 -0 apache-1.3/src/main/http_core.c
Index: http_core.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_core.c,v
retrieving revision 1.218
retrieving revision 1.219
diff -u -r1.218 -r1.219
--- http_core.c 1998/08/08 13:26:06 1.218
+++ http_core.c 1998/08/10 04:16:14 1.219
@@ -708,6 +708,14 @@
return ap_psprintf(p, "%s://%s:%u%s", ap_http_method(r), host, port, uri);
}
+API_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r)
+{
+ core_dir_config *d =
+ (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
+
+ return d->limit_req_body;
+}
+
/*****************************************************************
*
* Commands... this module handles almost all of the NCSA httpd.conf
@@ -2301,6 +2309,22 @@
return NULL;
}
+static const char *set_limit_req_body(cmd_parms *cmd, core_dir_config *conf,
+ char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+ if (err != NULL) {
+ return err;
+ }
+
+ /* WTF: If strtoul is not portable, then write a replacement.
+ * Instead we have an idiotic define in httpd.h that prevents
+ * it from being used even when it is available. Sheesh.
+ */
+ conf->limit_req_body = (unsigned long)strtol(arg, (char **)NULL, 10);
+ return NULL;
+}
+
/* Note --- ErrorDocument will now work from .htaccess files.
* The AllowOverride of Fileinfo allows webmasters to turn it off
*/
@@ -2503,6 +2527,8 @@
#endif
{ "ServerTokens", set_serv_tokens, NULL, RSRC_CONF, TAKE1,
"Determine tokens displayed in the Server: header - Min(imal), OS or Full" },
+{ "LimitRequestBody", set_limit_req_body, NULL, RSRC_CONF|ACCESS_CONF|OR_ALL,
+ TAKE1, "Limit (in bytes) on maximum size of request message body" },
{ NULL },
};
1.236 +35 -33 apache-1.3/src/main/http_protocol.c
Index: http_protocol.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v
retrieving revision 1.235
retrieving revision 1.236
diff -u -r1.235 -r1.236
--- http_protocol.c 1998/08/09 17:36:26 1.235
+++ http_protocol.c 1998/08/10 04:16:15 1.236
@@ -626,17 +626,12 @@
static int read_request_line(request_rec *r)
{
- char *l;
- const char *ll;
+ char l[AP_LIMIT_REQUEST_LINE + 2]; /* getline needs two extra for \n\0 */
+ const char *ll = l;
const char *uri;
conn_rec *conn = r->connection;
int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */
int len;
- pool *tmp;
-
- tmp = ap_make_sub_pool(r->pool);
- l = ap_palloc(tmp, r->server->limit_req_line);
- ll = l;
/* Read past empty lines until we get a real request line,
* a read error, the connection closes (EOF), or we timeout.
@@ -653,10 +648,9 @@
* have to block during a read.
*/
ap_bsetflag(conn->client, B_SAFEREAD, 1);
- while ((len = getline(l, r->server->limit_req_line, conn->client, 0)) <= 0) {
+ while ((len = getline(l, sizeof(l), conn->client, 0)) <= 0) {
if ((len < 0) || ap_bgetflag(conn->client, B_EOF)) {
ap_bsetflag(conn->client, B_SAFEREAD, 0);
- ap_destroy_pool(tmp);
return 0;
}
}
@@ -696,11 +690,14 @@
ap_parse_uri(r, uri);
- if (len >= r->server->limit_req_line - 1) {
+ /* getline returns (size of max buffer - 1) if it fills up the
+ * buffer before finding the end-of-line. This is only going to
+ * happen if it exceeds the configured limit for a request-line.
+ */
+ if (len >= sizeof(l) - 1) {
r->status = HTTP_REQUEST_URI_TOO_LARGE;
r->proto_num = HTTP_VERSION(1,0);
r->protocol = ap_pstrdup(r->pool, "HTTP/1.0");
- ap_destroy_pool(tmp);
return 0;
}
@@ -713,7 +710,6 @@
else
r->proto_num = HTTP_VERSION(1,0);
- ap_destroy_pool(tmp);
return 1;
}
@@ -742,20 +738,20 @@
/* XXX: could use ap_overlap_tables here... which generalizes this code */
static void get_mime_headers(request_rec *r)
{
+ char field[AP_LIMIT_REQUEST_FIELDSIZE + 2]; /* getline needs two extra */
conn_rec *c = r->connection;
- char *copy;
- int len;
char *value;
- unsigned int fields_read = 0;
- char *field;
- array_header *arr;
+ char *copy;
pool *tmp;
+ array_header *arr;
mime_key *new_key;
- unsigned order;
mime_key *first;
mime_key *last;
mime_key *end;
char *strp;
+ unsigned order;
+ int len;
+ unsigned int fields_read = 0;
/* The array will store the headers in a way that we can merge them
* later in O(n*lg(n))... rather than deal with various O(n^2)
@@ -765,8 +761,6 @@
arr = ap_make_array(tmp, 50, sizeof(mime_key));
order = 0;
- field = ap_palloc(tmp, r->server->limit_req_fieldsize);
-
/* If headers_in is non-empty (i.e. we're parsing a trailer) then
* we have to merge. Have I mentioned that I think this is a lame part
* of the HTTP standard? Anyhow, we'll cheat, and just pre-seed our
@@ -795,22 +789,25 @@
* Read header lines until we get the empty separator line, a read error,
* the connection closes (EOF), reach the server limit, or we timeout.
*/
- while ((len = getline(field, r->server->limit_req_fieldsize,
- c->client, 1)) > 0) {
+ while ((len = getline(field, sizeof(field), c->client, 1)) > 0) {
- if (++fields_read > r->server->limit_req_fields) {
+ if (++fields_read > AP_LIMIT_REQUEST_FIELDS) {
r->status = HTTP_BAD_REQUEST;
ap_table_setn(r->notes, "error-notes",
"Number of request header fields exceeds server limit.<P>\n");
- ap_destroy_pool(tmp);
+ ap_destroy_pool(tmp);
return;
}
- if (len >= r->server->limit_req_fieldsize) {
+ /* getline returns (size of max buffer - 1) if it fills up the
+ * buffer before finding the end-of-line. This is only going to
+ * happen if it exceeds the configured limit for a field size.
+ */
+ if (len >= sizeof(field) - 1) {
r->status = HTTP_BAD_REQUEST;
ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
"Size of a request header field exceeds server limit.<P>\n"
"<PRE>\n", field, "</PRE>\n", NULL));
- ap_destroy_pool(tmp);
+ ap_destroy_pool(tmp);
return;
}
copy = ap_palloc(r->pool, len + 1);
@@ -821,7 +818,7 @@
ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
"Request header field is missing colon separator.<P>\n"
"<PRE>\n", copy, "</PRE>\n", NULL));
- ap_destroy_pool(tmp);
+ ap_destroy_pool(tmp);
return;
}
@@ -830,7 +827,7 @@
while (*value == ' ' || *value == '\t')
++value; /* Skip to start of value */
- /* XXX: should strip trailing whitespace as well */
+ /* XXX: should strip trailing whitespace as well */
/* Notice that key and val are actually in r->pool... this is a slight
* optimization to handle the normal case, where we don't have twits
@@ -1495,6 +1492,7 @@
{
const char *tenc = ap_table_get(r->headers_in, "Transfer-Encoding");
const char *lenp = ap_table_get(r->headers_in, "Content-Length");
+ unsigned long max_body;
r->read_body = read_policy;
r->read_chunked = 0;
@@ -1534,10 +1532,12 @@
"%s with body is not allowed for %s", r->method, r->uri);
return HTTP_REQUEST_ENTITY_TOO_LARGE;
}
- if (r->remaining > r->server->limit_req_body) {
+
+ max_body = ap_get_limit_req_body(r);
+ if (max_body && (r->remaining > max_body)) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
"Request content-length of %s is larger than the configured "
- "server limit of %lu", lenp, r->server->limit_req_body);
+ "limit of %lu", lenp, max_body);
return HTTP_REQUEST_ENTITY_TOO_LARGE;
}
@@ -1601,6 +1601,7 @@
int c;
long len_read, len_to_read;
long chunk_start = 0;
+ unsigned long max_body;
if (!r->read_chunked) { /* Content-length read */
len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
@@ -1630,10 +1631,11 @@
* caller read pass, since the limit exists just to stop infinite
* length requests and nobody cares if it goes over by one buffer.
*/
- if (r->read_length > r->server->limit_req_body) {
+ max_body = ap_get_limit_req_body(r);
+ if (max_body && (r->read_length > max_body)) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
- "Chunked request body is larger than the configured "
- "server limit of %lu", r->server->limit_req_body);
+ "Chunked request body is larger than the configured limit of %lu",
+ max_body);
r->connection->keepalive = -1;
return -1;
}
Re: cvs commit: apache-1.3/src/main http_config.c http_core.c http_protocol.c
Posted by Randy Terbush <ra...@Covalent.NET>.
Rodent of Unusual Size <Ke...@Golux.Com> writes:
> fielding@hyperreal.org wrote:
> >
> > Log:
> > Fixed request limit change to be more portable. Removed the server_rec
> > variables since compile-time control of the request-line, fieldsize, and
> > number of fields is sufficient.
>
> No time to really comment in detail, but I disagree with the above in
> principle. We getting a *lot* of people using prepackaged binaries
> (RedHat, FreeBSD, ...), and making them recompile seems unfriendly.
> I'd much rather see run-time directives available for these.
>
> Just MHO.
I would agree with this.
-Randy
Re: cvs commit: apache-1.3/src/main http_config.c http_core.c
http_protocol.c
Posted by Rodent of Unusual Size <Ke...@Golux.Com>.
fielding@hyperreal.org wrote:
>
> Log:
> Fixed request limit change to be more portable. Removed the server_rec
> variables since compile-time control of the request-line, fieldsize, and
> number of fields is sufficient.
No time to really comment in detail, but I disagree with the above in
principle. We getting a *lot* of people using prepackaged binaries
(RedHat, FreeBSD, ...), and making them recompile seems unfriendly.
I'd much rather see run-time directives available for these.
Just MHO.
#ken P-)}
Ken Coar <http://Web.Golux.Com/coar/>
Apache Group member <http://www.apache.org/>
"Apache Server for Dummies" <http://Web.Golux.Com/coar/ASFD/>