cvs commit: apache-1.3/src/modules/standard mod_cern_meta.c
dgaudet 98/08/13 19:49:57 Modified:src CHANGES src/include alloc.h src/main alloc.c http_protocol.c util_script.c src/modules/standard mod_cern_meta.c Log: Add ap_overlap_tables. Fix various O(n^2) attacks using it. Revision ChangesPath 1.1024+3 -1 apache-1.3/src/CHANGES Index: CHANGES === RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.1023 retrieving revision 1.1024 diff -u -r1.1023 -r1.1024 --- CHANGES 1998/08/13 01:54:59 1.1023 +++ CHANGES 1998/08/14 02:49:42 1.1024 @@ -22,7 +22,9 @@ [Jim Jagielski] *) SECURITY: Eliminate O(n^2) space DoS attacks (and other O(n^2) - cpu time attacks) in header parsing. [Dean Gaudet] + cpu time attacks) in header parsing. Add ap_overlap_tables(), + a function which can be used to perform bulk update operations + on tables in a more efficient manner. [Dean Gaudet] *) SECURITY: Added compile-time and configurable limits for various aspects of reading a client request to avoid some simple 1.63 +4 -2 apache-1.3/src/include/alloc.h Index: alloc.h === RCS file: /export/home/cvs/apache-1.3/src/include/alloc.h,v retrieving revision 1.62 retrieving revision 1.63 diff -u -r1.62 -r1.63 --- alloc.h 1998/08/09 17:36:24 1.62 +++ alloc.h 1998/08/14 02:49:45 1.63 @@ -199,7 +199,7 @@ int i; for (i = 0; i < barr->nelts; ++i) { - if (merge) { + if (flags & AP_OVERLAP_TABLES_MERGE) { ap_table_mergen(a, belt[i].key, belt[i].val); } else { @@ -214,7 +214,9 @@ in an ancestor of a's pool. In practice b and a are usually from the same pool. */ -API_EXPORT(void) ap_overlap_tables(table *a, const table *b, int merge); +#define AP_OVERLAP_TABLES_SET(0) +#define AP_OVERLAP_TABLES_MERGE (1) +API_EXPORT(void) ap_overlap_tables(table *a, const table *b, unsigned flags); /* XXX: these know about the definition of struct table in alloc.c. That * definition is not here because it is supposed to be private, and by not 1.99 +157 -0apache-1.3/src/main/alloc.c Index: alloc.c === RCS file: /export/home/cvs/apache-1.3/src/main/alloc.c,v retrieving revision 1.98 retrieving revision 1.99 diff -u -r1.98 -r1.99 --- alloc.c 1998/08/03 09:14:51 1.98 +++ alloc.c 1998/08/14 02:49:47 1.99 @@ -1386,6 +1386,163 @@ va_end(vp); } +/* Curse libc and the fact that it doesn't guarantee a stable sort. We + * have to enforce stability ourselves by using the order field. If it + * provided a stable sort then we wouldn't even need temporary storage to + * do the work below. -djg + * + * ("stable sort" means that equal keys retain their original relative + * ordering in the output.) + */ +typedef struct { +char *key; +char *val; +int order; +} overlap_key; + +static int sort_overlap(const void *va, const void *vb) +{ +const overlap_key *a = va; +const overlap_key *b = vb; +int r; + +r = strcasecmp(a->key, b->key); +if (r) { + return r; +} +return a->order - b->order; +} + +/* prefer to use the stack for temp storage for overlaps smaller than this */ +#ifndef AP_OVERLAP_TABLES_ON_STACK +#define AP_OVERLAP_TABLES_ON_STACK (512) +#endif + +API_EXPORT(void) ap_overlap_tables(table *a, const table *b, unsigned flags) +{ +overlap_key cat_keys_buf[AP_OVERLAP_TABLES_ON_STACK]; +overlap_key *cat_keys; +int nkeys; +table_entry *e; +table_entry *last_e; +overlap_key *left; +overlap_key *right; +overlap_key *last; + +nkeys = a->a.nelts + b->a.nelts; +if (nkeys < AP_OVERLAP_TABLES_ON_STACK) { + cat_keys = cat_keys_buf; +} +else { + /* XXX: could use scratch free space in a or b's pool instead... + * which could save an allocation in b's pool. + */ + cat_keys = ap_palloc(b->a.pool, sizeof(overlap_key) * nkeys); +} + +nkeys = 0; + +/* Create a list of the entries from a concatenated with the entries + * from b. + */ +e = (table_entry *)a->a.elts; +last_e = e + a->a.nelts; +while (e < last_e) { + cat_keys[nkeys].key = e->key; + cat_keys[nkeys].val = e->val; + cat_keys[nkeys].order = nkeys; + ++nkeys; + ++e; +} + +e = (table_entry *)b->a.elts; +last_e = e + b->a.nelts; +while (e < last_e) { + cat_keys[nkeys].key = e->key; + cat_keys[nkeys].val = e->val; + cat_keys[nkeys].order = nkeys;
cvs commit: apache-1.3/src/modules/standard mod_cern_meta.c mod_include.c
dgaudet 98/08/09 10:36:30 Modified:src/include alloc.h src/main http_protocol.c util_script.c src/modules/proxy proxy_http.c proxy_util.c src/modules/standard mod_cern_meta.c mod_include.c Log: Just some comments. Including a proposed ap_overlap_tables function which generalizes my new code in get_mime_headers(). Revision ChangesPath 1.62 +24 -0 apache-1.3/src/include/alloc.h Index: alloc.h === RCS file: /export/home/cvs/apache-1.3/src/include/alloc.h,v retrieving revision 1.61 retrieving revision 1.62 diff -u -r1.61 -r1.62 --- alloc.h 1998/06/27 18:09:28 1.61 +++ alloc.h 1998/08/09 17:36:24 1.62 @@ -192,6 +192,30 @@ API_EXPORT(table *) ap_overlay_tables(pool *p, const table *overlay, const table *base); +/* Conceptually, ap_overlap_tables does this: + +array_header *barr = ap_table_elts(b); +table_entry *belt = (table_entry *)barr->elts; +int i; + +for (i = 0; i < barr->nelts; ++i) { + if (merge) { + ap_table_mergen(a, belt[i].key, belt[i].val); + } + else { + ap_table_setn(a, belt[i].key, belt[i].val); + } +} + +Except that it is more efficient (less space and cpu-time) especially +when b has many elements. + +Notice the assumptions on the keys and values in b -- they must be +in an ancestor of a's pool. In practice b and a are usually from +the same pool. +*/ +API_EXPORT(void) ap_overlap_tables(table *a, const table *b, int merge); + /* XXX: these know about the definition of struct table in alloc.c. That * definition is not here because it is supposed to be private, and by not * placing it here we are able to get compile-time diagnostics from modules 1.235 +1 -0 apache-1.3/src/main/http_protocol.c Index: http_protocol.c === RCS file: /export/home/cvs/apache-1.3/src/main/http_protocol.c,v retrieving revision 1.234 retrieving revision 1.235 diff -u -r1.234 -r1.235 --- http_protocol.c 1998/08/09 16:57:29 1.234 +++ http_protocol.c 1998/08/09 17:36:26 1.235 @@ -739,6 +739,7 @@ return (signed)a->order - (signed)b->order; } +/* XXX: could use ap_overlap_tables here... which generalizes this code */ static void get_mime_headers(request_rec *r) { conn_rec *c = r->connection; 1.128 +2 -0 apache-1.3/src/main/util_script.c Index: util_script.c === RCS file: /export/home/cvs/apache-1.3/src/main/util_script.c,v retrieving revision 1.127 retrieving revision 1.128 diff -u -r1.127 -r1.128 --- util_script.c 1998/08/06 18:58:21 1.127 +++ util_script.c 1998/08/09 17:36:26 1.128 @@ -188,6 +188,7 @@ return env; } +/* XXX: this could use ap_overlap_tables */ API_EXPORT(void) ap_add_common_vars(request_rec *r) { table *e = r->subprocess_env; @@ -546,6 +547,7 @@ ap_table_add(r->err_headers_out, w, l); } else { + /* XXX: there is an O(n^2) space attack possible here */ ap_table_merge(r->err_headers_out, w, l); } } 1.55 +1 -0 apache-1.3/src/modules/proxy/proxy_http.c Index: proxy_http.c === RCS file: /export/home/cvs/apache-1.3/src/modules/proxy/proxy_http.c,v retrieving revision 1.54 retrieving revision 1.55 diff -u -r1.54 -r1.55 --- proxy_http.c 1998/08/06 17:30:43 1.54 +++ proxy_http.c 1998/08/09 17:36:27 1.55 @@ -425,6 +425,7 @@ continue; if (!r->assbackwards) { ap_rvputs(r, hdr[i].field, ": ", hdr[i].value, CRLF, NULL); + /* XXX: can't this be ap_table_setn? -djg */ ap_table_set(r->headers_out, hdr[i].field, hdr[i].value); } if (cache != NULL) 1.67 +1 -0 apache-1.3/src/modules/proxy/proxy_util.c Index: proxy_util.c === RCS file: /export/home/cvs/apache-1.3/src/modules/proxy/proxy_util.c,v retrieving revision 1.66 retrieving revision 1.67 diff -u -r1.66 -r1.67 --- proxy_util.c 1998/08/06 17:30:44 1.66 +++ proxy_util.c 1998/08/09 17:36:28 1.67 @@ -641,6 +641,7 @@ if (hdrs[i].field == NULL) continue; ap_bvputs(fp, hdrs[i].field, ": ", hdrs[i].value, CRLF, NULL); + /* XXX: can't this be ap_table_setn? -djg */ ap_table_set(r->headers_out, hdrs[i].field, hdrs[i].value); } 1.34 +1 -0 apache-1.3/src/modules/standard/mod_cern_meta.c Index: mod_cern_meta.c ==
cvs commit: apache-1.3/src/modules/standard mod_cern_meta.c mod_mime_magic.c
dgaudet 98/06/10 02:02:15 Modified:src CHANGES src/include httpd.h src/main util.c util_script.c src/modules/standard mod_cern_meta.c mod_mime_magic.c Log: My "all content-types must be lowercase" change neglected param=value pairs... and would downcase the value, which is a case-sensitive thing. But, to be honest, the code prior to my changes neglected param=value pairs. Another case where we really should have some core parsing routines that understand HTTP rather than the hodge-podge we have now. PR: 2394 Revision ChangesPath 1.906 +5 -0 apache-1.3/src/CHANGES Index: CHANGES === RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.905 retrieving revision 1.906 diff -u -r1.905 -r1.906 --- CHANGES 1998/06/10 08:15:09 1.905 +++ CHANGES 1998/06/10 09:01:58 1.906 @@ -1,5 +1,10 @@ Changes with Apache 1.3.1 + *) Apache would incorrectly downcase the entire Content-Type passed from + CGIs. This affected server-push scripts and such which use + multipart/x-mixed-replace;boundary=ThisRandomString. + [Dean Gaudet] PR#2394 + *) PORT: QNX update to properly guess 32-bit systems. [Sean Boudreau <[EMAIL PROTECTED]>] PR#2390 1.223 +1 -0 apache-1.3/src/include/httpd.h Index: httpd.h === RCS file: /export/home/cvs/apache-1.3/src/include/httpd.h,v retrieving revision 1.222 retrieving revision 1.223 diff -u -r1.222 -r1.223 --- httpd.h 1998/06/07 01:22:36 1.222 +++ httpd.h 1998/06/10 09:02:02 1.223 @@ -896,6 +896,7 @@ API_EXPORT(char *) ap_pregsub(pool *p, const char *input, const char *source, size_t nmatch, regmatch_t pmatch[]); +API_EXPORT(void) ap_content_type_tolower(char *); API_EXPORT(void) ap_str_tolower(char *); API_EXPORT(int) ap_ind(const char *, char); /* Sigh... */ API_EXPORT(int) ap_rind(const char *, char); 1.120 +24 -0 apache-1.3/src/main/util.c Index: util.c === RCS file: /export/home/cvs/apache-1.3/src/main/util.c,v retrieving revision 1.119 retrieving revision 1.120 diff -u -r1.119 -r1.120 --- util.c1998/06/06 19:30:48 1.119 +++ util.c1998/06/10 09:02:09 1.120 @@ -1781,3 +1781,27 @@ return (time1 - time0); } #endif + +/* we want to downcase the type/subtype for comparison purposes + * but nothing else because ;parameter=foo values are case sensitive. + * XXX: in truth we want to downcase parameter names... but really, + * apache has never handled parameters and such correctly. You + * also need to compress spaces and such to be able to compare + * properly. -djg + */ +API_EXPORT(void) ap_content_type_tolower(char *str) +{ +char *semi; + +semi = strchr(str, ';'); +if (semi) { + *semi = '\0'; +} +while (*str) { + *str = tolower(*str); + ++str; +} +if (semi) { + *semi = ';'; +} +} 1.116 +1 -1 apache-1.3/src/main/util_script.c Index: util_script.c === RCS file: /export/home/cvs/apache-1.3/src/main/util_script.c,v retrieving revision 1.115 retrieving revision 1.116 diff -u -r1.115 -r1.116 --- util_script.c 1998/05/28 23:26:41 1.115 +++ util_script.c 1998/06/10 09:02:09 1.116 @@ -466,7 +466,7 @@ *endp-- = '\0'; r->content_type = ap_pstrdup(r->pool, l); - ap_str_tolower(r->content_type); + ap_content_type_tolower(r->content_type); } /* * If the script returned a specific status, that's what 1.30 +1 -1 apache-1.3/src/modules/standard/mod_cern_meta.c Index: mod_cern_meta.c === RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_cern_meta.c,v retrieving revision 1.29 retrieving revision 1.30 diff -u -r1.29 -r1.30 --- mod_cern_meta.c 1998/06/09 05:22:11 1.29 +++ mod_cern_meta.c 1998/06/10 09:02:12 1.30 @@ -269,7 +269,7 @@ *endp-- = '\0'; r->content_type = ap_pstrdup(r->pool, l); - ap_str_tolower(r->content_type); + ap_content_type_tolower(r->content_type); } else if (!strcasecmp(w, "Status")) { sscanf(l, "%d", &r->status); 1.34 +1 -1 apache-1.3/src/modules/standard/mod_mime_magic.c Index: mod_mime_magic.c === RCS file: /export/home/cvs/apache-1.3/src/modules/standard
cvs commit: apache-1.3/src/modules/standard mod_cern_meta.c
dgaudet 98/06/08 22:22:12 Modified:src CHANGES src/modules/standard mod_cern_meta.c Log: Missing usage for MetaFiles directive. PR: 2384 Submitted by: David MacKenzie <[EMAIL PROTECTED]> Revision ChangesPath 1.900 +3 -0 apache-1.3/src/CHANGES Index: CHANGES === RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.899 retrieving revision 1.900 diff -u -r1.899 -r1.900 --- CHANGES 1998/06/09 04:41:26 1.899 +++ CHANGES 1998/06/09 05:22:10 1.900 @@ -1,5 +1,8 @@ Changes with Apache 1.3.1 + *) Fix missing usage description for MetaFiles directive. + [David MacKenzie <[EMAIL PROTECTED]>] PR#2384 + *) mod_log_config wouldn't let vhosts use log formats defined in the main server. [Christof Damian <[EMAIL PROTECTED]>] PR#2090 1.29 +2 -1 apache-1.3/src/modules/standard/mod_cern_meta.c Index: mod_cern_meta.c === RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_cern_meta.c,v retrieving revision 1.28 retrieving revision 1.29 diff -u -r1.28 -r1.29 --- mod_cern_meta.c 1998/04/11 12:00:45 1.28 +++ mod_cern_meta.c 1998/06/09 05:22:11 1.29 @@ -217,7 +217,8 @@ static const command_rec cern_meta_cmds[] = { -{"MetaFiles", set_metafiles, NULL, DIR_CMD_PERMS, FLAG, NULL}, +{"MetaFiles", set_metafiles, NULL, DIR_CMD_PERMS, FLAG, +"Limited to 'on' or 'off'"}, {"MetaDir", set_metadir, NULL, DIR_CMD_PERMS, TAKE1, "the name of the directory containing meta files"}, {"MetaSuffix", set_metasuffix, NULL, DIR_CMD_PERMS, TAKE1,