Commit 9ffc73d4 authored by Jim Jagielski's avatar Jim Jagielski
Browse files

Apply the CAN-2004-0940 patch.

PR:
Obtained from:
Submitted by:
Reviewed by:


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@105547 13f79535-47bb-0310-9956-ffa450edef68
parent 1de529d8
Loading
Loading
Loading
Loading
+4 −3
Changes for STATUS: 4 added lines, 3 removed lines.
Original line number Diff line number Diff line
APACHE 1.3 STATUS:						-*-text-*-
  Last modified at [$Date: 2004/10/18 16:40:39 $]
  Last modified at [$Date: 2004/10/22 19:31:06 $]

Release:

   1.3.33-dev: In development
   1.3.32: Tagged October 18, 2004.
   1.3.33-dev: Jim proposes a tag-n-roll around Oct 24
               with a release on the 27th.
   1.3.32: Tagged October 18, 2004. Not released.
   1.3.31: Tagged May 7, 2004. Announced May 11, 2004.
   1.3.30: Tagged April 9, 2004. Not released.
   1.3.29: Tagged October 24, 2003. Announced Oct 29, 2003.
+3 −0
Changes for src/CHANGES: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
Changes with Apache 1.3.33

  *) SECURITY: CAN-2004-0940 (cve.mitre.org)
     mod_include: Fix potential buffer overflow with escaped characters
     in SSI tag string. [Martin Kraemer, Jim Jagielski]

Changes with Apache 1.3.32

+40 −24
Changes for src/modules/standard/mod_include.c: 40 added lines, 24 removed lines.
Original line number Diff line number Diff line
@@ -309,9 +309,10 @@ otilde\365oslash\370ugrave\371uacute\372yacute\375" /* 6 */
 * the tag value is html decoded if dodecode is non-zero
 */

static char *get_tag(pool *p, FILE *in, char *tag, int tagbuf_len, int dodecode)
static char *get_tag(request_rec *r, FILE *in, char *tag, int tagbuf_len, int dodecode)
{
    char *t = tag, *tag_val, c, term;
    pool *p = r->pool;

    /* makes code below a little less cluttered */
    --tagbuf_len;
@@ -337,7 +338,7 @@ static char *get_tag(pool *p, FILE *in, char *tag, int tagbuf_len, int dodecode)

    /* find end of tag name */
    while (1) {
        if (t - tag == tagbuf_len) {
        if (t == tag + tagbuf_len) {
            *t = '\0';
            return NULL;
        }
@@ -371,16 +372,30 @@ static char *get_tag(pool *p, FILE *in, char *tag, int tagbuf_len, int dodecode)
    term = c;
    while (1) {
        GET_CHAR(in, c, NULL, p);
        if (t - tag == tagbuf_len) {
        if (t == tag + tagbuf_len) {
            *t = '\0';
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
                          "mod_include: value length exceeds limit"
                          " (%d) in %s", tagbuf_len, r->filename);
            return NULL;
        }
        /* Want to accept \" as a valid character within a string. */
        if (c == '\\') {
            *(t++) = c;         /* Add backslash */
            GET_CHAR(in, c, NULL, p);
            if (c == term) {    /* Only if */
                *(--t) = c;     /* Replace backslash ONLY for terminator */
            /* Insert backslash only if not escaping a terminator char */
            if (c != term) {
                *(t++) = '\\';
                /*
                 * check to make sure that adding in the backslash won't cause
                 * an overflow, since we're now 1 character ahead.
                 */
                if (t == tag + tagbuf_len) {
                    *t = '\0';
                    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
                                  "mod_include: value length exceeds limit"
                                  " (%d) in %s", tagbuf_len, r->filename);
                    return NULL;
                }
            }
        }
        else if (c == term) {
@@ -395,9 +410,10 @@ static char *get_tag(pool *p, FILE *in, char *tag, int tagbuf_len, int dodecode)
    return ap_pstrdup(p, tag_val);
}

static int get_directive(FILE *in, char *dest, size_t len, pool *p)
static int get_directive(FILE *in, char *dest, size_t len, request_rec *r)
{
    char *d = dest;
    pool *p = r->pool;
    char c;

    /* make room for nul terminator */
@@ -413,6 +429,9 @@ static int get_directive(FILE *in, char *dest, size_t len, pool *p)
    /* now get directive */
    while (1) {
	if (d == len + dest) {
            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
                          "mod_include: directive length exceeds limit"
                          " (%d) in %s", len+1, r->filename);
	    return 1;
	}
        *d++ = ap_tolower(c);
@@ -616,7 +635,7 @@ static int handle_include(FILE *in, request_rec *r, const char *error, int noexe
    char *tag_val;

    while (1) {
        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
        if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
            return 1;
        }
        if (!strcmp(tag, "file") || !strcmp(tag, "virtual")) {
@@ -839,7 +858,7 @@ static int handle_exec(FILE *in, request_rec *r, const char *error)
    char parsed_string[MAX_STRING_LEN];

    while (1) {
        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
        if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
            return 1;
        }
        if (!strcmp(tag, "cmd")) {
@@ -890,7 +909,7 @@ static int handle_echo(FILE *in, request_rec *r, const char *error)
    encode = E_ENTITY;

    while (1) {
        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
        if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
            return 1;
        }
        if (!strcmp(tag, "var")) {
@@ -952,7 +971,7 @@ static int handle_perl(FILE *in, request_rec *r, const char *error)
        return DECLINED;
    }
    while (1) {
        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
        if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
            break;
        }
        if (strnEQ(tag, "sub", 3)) {
@@ -985,7 +1004,7 @@ static int handle_config(FILE *in, request_rec *r, char *error, char *tf,
    table *env = r->subprocess_env;

    while (1) {
        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0))) {
        if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 0))) {
            return 1;
        }
        if (!strcmp(tag, "errmsg")) {
@@ -1101,7 +1120,7 @@ static int handle_fsize(FILE *in, request_rec *r, const char *error, int sizefmt
    char parsed_string[MAX_STRING_LEN];

    while (1) {
        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
        if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
            return 1;
        }
        else if (!strcmp(tag, "done")) {
@@ -1141,7 +1160,7 @@ static int handle_flastmod(FILE *in, request_rec *r, const char *error, const ch
    char parsed_string[MAX_STRING_LEN];

    while (1) {
        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
        if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
            return 1;
        }
        else if (!strcmp(tag, "done")) {
@@ -1917,7 +1936,7 @@ static int handle_if(FILE *in, request_rec *r, const char *error,

    expr = NULL;
    while (1) {
        tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0);
        tag_val = get_tag(r, in, tag, sizeof(tag), 0);
        if (!tag_val || *tag == '\0') {
            return 1;
        }
@@ -1960,7 +1979,7 @@ static int handle_elif(FILE *in, request_rec *r, const char *error,

    expr = NULL;
    while (1) {
        tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0);
        tag_val = get_tag(r, in, tag, sizeof(tag), 0);
        if (!tag_val || *tag == '\0') {
            return 1;
        }
@@ -2007,7 +2026,7 @@ static int handle_else(FILE *in, request_rec *r, const char *error,
{
    char tag[MAX_STRING_LEN];

    if (!get_tag(r->pool, in, tag, sizeof(tag), 1)) {
    if (!get_tag(r, in, tag, sizeof(tag), 1)) {
        return 1;
    }
    else if (!strcmp(tag, "done")) {
@@ -2035,7 +2054,7 @@ static int handle_endif(FILE *in, request_rec *r, const char *error,
{
    char tag[MAX_STRING_LEN];

    if (!get_tag(r->pool, in, tag, sizeof(tag), 1)) {
    if (!get_tag(r, in, tag, sizeof(tag), 1)) {
        return 1;
    }
    else if (!strcmp(tag, "done")) {
@@ -2065,7 +2084,7 @@ static int handle_set(FILE *in, request_rec *r, const char *error)

    var = (char *) NULL;
    while (1) {
        if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
        if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
            return 1;
        }
        else if (!strcmp(tag, "done")) {
@@ -2102,7 +2121,7 @@ static int handle_printenv(FILE *in, request_rec *r, const char *error)
    table_entry *elts = (table_entry *) arr->elts;
    int i;

    if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
    if (!(tag_val = get_tag(r, in, tag, sizeof(tag), 1))) {
        return 1;
    }
    else if (!strcmp(tag, "done")) {
@@ -2173,10 +2192,7 @@ static void send_parsed_content(FILE *f, request_rec *r)

    while (1) {
        if (!find_string(f, STARTING_SEQUENCE, r, printing)) {
            if (get_directive(f, directive, sizeof(directive), r->pool)) {
		ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
			    "mod_include: error reading directive in %s",
			    r->filename);
            if (get_directive(f, directive, sizeof(directive), r)) {
		ap_rputs(error, r);
                return;
            }