httpd-apreq-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject cvs commit: httpd-apreq-2/t cookie.c
Date Tue, 27 Jul 2004 16:58:55 GMT
joes        2004/07/27 09:58:55

  Modified:    .        CHANGES
               src      apreq_cookie.c apreq_version.h
               t        cookie.c
  Log:
  Fix cookie parser lockup on non-alnum chars appearing in name/attr component of the incoming
Cookie header.
  
  Revision  Changes    Path
  1.59      +7 -1      httpd-apreq-2/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/CHANGES,v
  retrieving revision 1.58
  retrieving revision 1.59
  diff -u -r1.58 -r1.59
  --- CHANGES	25 Jul 2004 05:25:38 -0000	1.58
  +++ CHANGES	27 Jul 2004 16:58:55 -0000	1.59
  @@ -4,12 +4,18 @@
   
   @section v2_04_dev Changes with libapreq2-2.04-dev
   
  +
  +- C API [rendyk, joes]
  +  Cookie parser was locking up on non-alphanumeric chars in cookie names.
  +  Also RFC Cookie attributes are always checked for quotes during bake(2),
  +  and the quotes are now stripped from incoming RFC cookies during parsing 
  +  (but they are never stripped from the actual cookie value).
  +
   - Perl API [joes]
     Apache::Cookie::Jar->new accepts a VALUE_CLASS argument, which effectively
     blesses all the jar's cookies into that class, which simplifies subclassing
     Apache::Cookie.   Accordingly Apache::Cookie->freeze($value) no longer accepts 
     a freeze()-able object in $value.
  -
   
   - C API [Markus Wichitill, randyk, joes]
     Drop APR_DELONCLOSE from apreq_file_mktemp implementation and install
  
  
  
  1.29      +108 -69   httpd-apreq-2/src/apreq_cookie.c
  
  Index: apreq_cookie.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_cookie.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- apreq_cookie.c	24 Jul 2004 21:09:18 -0000	1.28
  +++ apreq_cookie.c	27 Jul 2004 16:58:55 -0000	1.29
  @@ -181,73 +181,97 @@
   }
   
   APR_INLINE
  -static apr_status_t get_pair(const char **data,
  +static apr_status_t get_pair(apr_pool_t *p, const char **data,
                                const char **n, apr_size_t *nlen,
  -                             const char **v, apr_size_t *vlen)
  +                             const char **v, apr_size_t *vlen, unsigned unquote)
   {
  -    const char *d = *data;
  -    unsigned char in_quotes = 0;
  +    const char *hdr, *key, *val;
   
  -    while(apr_isspace(*d))
  -        ++d;
  +    hdr = *data;
   
  -    *n = d;
  -
  -    while (apr_isalnum(*d))
  -        ++d;
  -
  -    *nlen = d - *n;
  +    while (apr_isspace(*hdr) || *hdr == '=')
  +        ++hdr;
   
  -    while(apr_isspace(*d))
  -        ++d;
  +    key = strchr(hdr, '=');
   
  -    if (*d != '=') {
  -        *data = d;
  -        *v = d;
  -        *vlen = 0;
  +    if (key == NULL)
           return APR_NOTFOUND;
  -    }
   
  +    val = key + 1;
   
  -    do ++d;
  -    while (apr_isspace(*d));
  +    do --key; 
  +    while (key > hdr && apr_isspace(*key));
   
  -    *v = d;
  +    *n = key;
   
  -    for (;;++d) {
  -        switch (*d) {
  -
  -        case ';':
  -        case ',':
  -            if (in_quotes)
  -                break;
  -            /* else fall through */
  -        case 0:
  -            goto pair_result;
  -
  -        case '\\':
  -            if (*++d) {
  +    while (key >= hdr && !apr_isspace(*key))
  +        --key;
  +
  +    *nlen = *n - key;
  +    *n = key + 1;
  +
  +    while (apr_isspace(*val))
  +        ++val;
  +
  +    if (*val == '"') {
  +        unsigned saw_backslash = 0;
  +        for (*v = (unquote) ? ++val : val++; *val; ++val) {
  +            switch (*val) {
  +            case '"':
  +                *data = val + 1;
  +
  +                if (!unquote) {
  +                    *vlen = (val - *v) + 1;
  +                }
  +                else if (!saw_backslash) {
  +                    *vlen = val - *v;
  +                }
  +                else {
  +                    char *dest = apr_palloc(p, val - *v), *d = dest;
  +                    const char *s = *v;
  +                    while (s < val) {
  +                        if (*s == '\\')
  +                            ++s;
  +                        *d++ = *s++;
  +                    }
  +
  +                    *vlen = d - dest;
  +                    *v = dest;
  +                }
  +                
  +                return APR_SUCCESS;
  +            case '\\':
  +                saw_backslash = 1;
  +                if (val[1] != 0)
  +                    ++val;
  +            default:
                   break;
               }
  -            else {  /* shouldn't end on a sour note */
  -                *vlen = d - *v;
  -                *data = d;
  -                return APR_EGENERAL;
  +        }
  +        /* bad attr: no terminating quote found */
  +        return APR_EGENERAL;
  +    }
  +    else {
  +        /* value is not wrapped in quotes */
  +        for (*v = val; *val; ++val) {
  +            switch (*val) {
  +            case ';':
  +            case ',':
  +            case ' ':
  +            case '\t':
  +            case '\r':
  +            case '\n':
  +                *data = val;
  +                *vlen = val - *v;
  +                return APR_SUCCESS;
  +            default:
  +                break;
               }
  -
  -        case '"':
  -            in_quotes = ! in_quotes;
  -
           }
       }
   
  - pair_result:
  -
  -    *vlen = d - *v;
  -    *data = d;
  -
  -    if (in_quotes)
  -        return APR_EGENERAL;
  +    *data = val;
  +    *vlen = val - *v;
   
       return APR_SUCCESS;
   }
  @@ -361,7 +385,7 @@
               }
   
               ++hdr;
  -            status = get_pair(&hdr, &name, &nlen, &value, &vlen);
  +            status = get_pair(p, &hdr, &name, &nlen, &value, &vlen,
1);
               if (status != APR_SUCCESS) {
                   j->status = status;
                   apreq_log(APREQ_ERROR status, env,
  @@ -396,17 +420,16 @@
                   apreq_add_cookie(j, c);
               }
   
  -            status = get_pair(&hdr, &name, &nlen, &value, &vlen);
  +            status = get_pair(p, &hdr, &name, &nlen, &value, &vlen,
0);
   
               if (status == APR_SUCCESS) {
                   c = apreq_make_cookie(p, name, nlen, value, vlen);
                   c->version = version;
               }
               else {
  -                apreq_log(APREQ_WARN status, env, 
  -                          "Skipping bad NAME=VALUE pair: %s", 
  -                           apr_pstrmemdup(p, name, hdr-name));
  -                c = NULL;
  +                if (status == APR_EGENERAL)
  +                    j->status = APR_EGENERAL;
  +                return j;
               }
           }
       }
  @@ -421,8 +444,8 @@
   {
       /*  The format string must be large enough to accomodate all
        *  of the cookie attributes.  The current attributes sum to 
  -     *  ~80 characters (w/ 6 padding chars per attr), so anything 
  -     *  over that should number be fine.
  +     *  ~90 characters (w/ 6-8 padding chars per attr), so anything 
  +     *  over 100 number be fine.
        */
   
       char format[128] = "%s=%s";
  @@ -433,16 +456,22 @@
       if (c->v.name == NULL)
           return -1;
       
  -#define ADD_ATTR(name) do { strcpy(f,c->name ? "; " #name "=%s" : \
  -                                    "%.0s"); f+= strlen(f); } while (0)
   #define NULL2EMPTY(attr) (attr ? attr : "")
   
   
       if (c->version == NETSCAPE) {
           char expires[APR_RFC822_DATE_LEN] = {0};
   
  -        ADD_ATTR(path);
  -        ADD_ATTR(domain);
  +#define ADD_NS_ATTR(name) do {                  \
  +    if (c->name != NULL)                        \
  +        strcpy(f, "; " #name "=%s");            \
  +    else                                        \
  +        strcpy(f, "%0.s");                      \
  +    f += strlen(f);                             \
  +} while (0)
  +
  +        ADD_NS_ATTR(path);
  +        ADD_NS_ATTR(domain);
   
           if (c->max_age != -1) {
               strcpy(f, "; expires=%s");
  @@ -467,13 +496,23 @@
       strcpy(f,"; Version=%d");
       f += strlen(f);
   
  -    ADD_ATTR(path);
  -    ADD_ATTR(domain);
  -    ADD_ATTR(port);
  -    ADD_ATTR(comment);
  -    ADD_ATTR(commentURL);
  -
  -#undef ADD_ATTR
  +/* ensure RFC attributes are always quoted */
  +#define ADD_RFC_ATTR(name) do {                 \
  +    if (c->name != NULL)                        \
  +        if (*c->name == '"')                    \
  +            strcpy(f, "; " #name "=%s");        \
  +        else                                    \
  +            strcpy(f, "; " #name "=\"%s\"");    \
  +    else                                        \
  +        strcpy(f, "%0.s");                      \
  +    f += strlen (f);                            \
  +} while (0)
  +
  +    ADD_RFC_ATTR(path);
  +    ADD_RFC_ATTR(domain);
  +    ADD_RFC_ATTR(port);
  +    ADD_RFC_ATTR(comment);
  +    ADD_RFC_ATTR(commentURL);
   
       strcpy(f, c->max_age != -1 ? "; max-age=%" APR_TIME_T_FMT : "");
   
  
  
  
  1.22      +1 -1      httpd-apreq-2/src/apreq_version.h
  
  Index: apreq_version.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_version.h,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- apreq_version.h	23 Jul 2004 17:22:54 -0000	1.21
  +++ apreq_version.h	27 Jul 2004 16:58:55 -0000	1.22
  @@ -61,7 +61,7 @@
   #define APREQ_MINOR_VERSION       0
   
   /** patch level */
  -#define APREQ_PATCH_VERSION      17
  +#define APREQ_PATCH_VERSION      18
   
   /** 
    *  This symbol is defined for internal, "development" copies of libapreq.
  
  
  
  1.12      +4 -4      httpd-apreq-2/t/cookie.c
  
  Index: cookie.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/t/cookie.c,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- cookie.c	18 Jul 2004 03:54:20 -0000	1.11
  +++ cookie.c	27 Jul 2004 16:58:55 -0000	1.12
  @@ -25,7 +25,7 @@
   static void jar_make(CuTest *tc)
   {
       j = apreq_jar(p,"a=1; foo=bar; fl=left; fr=right;bad; ns=foo=1&bar=2,"
  -                  "frl=right-left; flr=left-right; fll=left-left; bad");
  +                  "frl=right-left; flr=left-right; fll=left-left; good_one=1;bad");
       CuAssertPtrNotNull(tc, j);
   }
   
  @@ -93,18 +93,18 @@
   
       CuAssertStrEquals(tc,"rfc=out; Version=1", apreq_cookie_as_string(c,p));
       c->domain = apr_pstrdup(p, "example.com");
  -    CuAssertStrEquals(tc,"rfc=out; Version=1; domain=example.com", 
  +    CuAssertStrEquals(tc,"rfc=out; Version=1; domain=\"example.com\"", 
                         apreq_cookie_as_string(c,p));
   
       c->path = apr_pstrdup(p, "/quux");
       CuAssertStrEquals(tc, 
  -              "rfc=out; Version=1; path=/quux; domain=example.com",
  +              "rfc=out; Version=1; path=\"/quux\"; domain=\"example.com\"",
                         apreq_cookie_as_string(c,p));
   
       apreq_cookie_expires(c, "+3m");
       expires = apreq_atoi64t("+3m");
       CuAssertStrEquals(tc,apr_psprintf(p,
  -         "rfc=out; Version=1; path=/quux; domain=example.com; max-age=%ld",
  +         "rfc=out; Version=1; path=\"/quux\"; domain=\"example.com\"; max-age=%ld",
                  expires), apreq_cookie_as_string(c,p));
   
   }
  
  
  

Mime
View raw message