This patch fixed the following errors in the cookie code in Flood:
(1) Original code only handled a single "set-cookie" header for a given
HTTP message. There can be more than one.
(2) Original code did not handle a replacement for a cookie value already
in the "database". The fix searches through and avoids these duplicates by
replacing.

Please examine the attached diff and apply the changes to the file
flood_round_robin.c to resolve these issues.

-Norman Tuttle, developer, OpenDemand Systems, [EMAIL PROTECTED]
--- flood_round_robin.c 2003-10-20 11:37:20.000000000 -0400
+++ \flood-1.1\flood_round_robin.c      2003-09-07 22:22:32.000000000 -0400
@@ -151,14 +151,14 @@
 

 } round_robin_profile_t;

 

-static char *handle_param_string(round_robin_profile_t *rp, char *template,

+static char *handle_param_string(round_robin_profile_t *rp, char *template, 

                                  expand_param_e set)

 {

     char *cpy, *cur, *prev, *data, *returnValue, *pattern;

     int size, matchsize;

     regex_t re;

     regmatch_t match[2];

-

+         

     prev = template;

     returnValue = NULL;

 

@@ -203,7 +203,7 @@
 

         /* If there is no data, place the original string back. */

         if (!data) {

-            data = apr_psprintf(rp->pool, "${%s}",

+            data = apr_psprintf(rp->pool, "${%s}", 

                                 apr_pstrmemdup(rp->pool, cur+match[1].rm_so,

                                 match[1].rm_eo - match[1].rm_so));

         }

@@ -218,11 +218,11 @@
         else

         {

             if (cpy)

-                returnValue = apr_pstrcat(rp->pool, returnValue, cpy, data,

+                returnValue = apr_pstrcat(rp->pool, returnValue, cpy, data, 

                                           NULL);

             else

                 returnValue = apr_pstrcat(rp->pool, returnValue, data, NULL);

-

+            

         }

 

         /* Skip over the trailing } */

@@ -255,8 +255,8 @@
     char *cookies;

     char *enc_credtls, *credtls, *authz_hdr = NULL;

     cookie_t *cook;

-

-    p = (round_robin_profile_t*)profile;

+   

+    p = (round_robin_profile_t*)profile; 

 

     /* Do we want to save the entire response? */

     r->wantresponse = p->url[p->current_url].responsetemplate ? 1 : 0;

@@ -271,9 +271,9 @@
             if (cook != p->cookie)

                 cookies = apr_pstrcat(p->pool, cookies, ";", NULL);

 

-            cookies = apr_pstrcat(p->pool, cookies, cook->name, "=",

+            cookies = apr_pstrcat(p->pool, cookies, cook->name, "=", 

                                   cook->value, NULL);

-            cook = cook->next;

+            cook = cook->next; 

         }

         cookies = apr_pstrcat(p->pool, cookies, CRLF, NULL);

     }

@@ -302,14 +302,14 @@
     switch (r->method)

     {

     case GET:

-        r->rbuf = apr_psprintf(r->pool,

+        r->rbuf = apr_psprintf(r->pool, 

                                "GET %s%s%s HTTP/1.1" CRLF

                                "User-Agent: Flood/" FLOOD_VERSION CRLF

                                "Connection: %s" CRLF

-                               "Host: %s" CRLF

+                               "Host: %s" CRLF 

                                "%s"

                                "%s" CRLF,

-                               r->parsed_uri->path,

+                               r->parsed_uri->path, 

                                r->parsed_uri->query ? "?" : "",

                                r->parsed_uri->query ? r->parsed_uri->query : 
"",

                                r->keepalive ? "Keep-Alive" : "Close",

@@ -320,14 +320,14 @@
         r->rbufsize = strlen(r->rbuf);

         break;

     case HEAD:

-        r->rbuf = apr_psprintf(r->pool,

+        r->rbuf = apr_psprintf(r->pool, 

                                "HEAD %s%s%s HTTP/1.1" CRLF

                                "User-Agent: Flood/" FLOOD_VERSION CRLF

                                "Connection: %s" CRLF

-                               "Host: %s" CRLF

+                               "Host: %s" CRLF 

                                "%s"

                                "%s" CRLF,

-                               r->parsed_uri->path,

+                               r->parsed_uri->path, 

                                r->parsed_uri->query ? "?" : "",

                                r->parsed_uri->query ? r->parsed_uri->query : 
"",

                                r->keepalive ? "Keep-Alive" : "Close",

@@ -340,17 +340,17 @@
     case POST:

         /* FIXME */

         if (r->payload) {

-            r->rbuf = apr_psprintf(r->pool,

+            r->rbuf = apr_psprintf(r->pool, 

                                    "POST %s%s%s HTTP/1.1" CRLF

                                    "User-Agent: Flood/" FLOOD_VERSION CRLF

                                    "Connection: %s" CRLF

                                    "Host: %s" CRLF

-                                   "Content-Length: %d" CRLF

+                                   "Content-Length: %d" CRLF 

                                    "Content-type: 
application/x-www-form-urlencoded" CRLF

                                    "%s"

                                    "%s" CRLF

                                    "%s",

-                                   r->parsed_uri->path,

+                                   r->parsed_uri->path, 

                                    r->parsed_uri->query ? "?" : "",

                                    r->parsed_uri->query ? r->parsed_uri->query 
: "",

                                    r->keepalive ? "Keep-Alive" : "Close",

@@ -360,7 +360,7 @@
                                    cookies,

                                    (char*)r->payload);

         } else { /* There is no payload, but it's still a POST */

-            r->rbuf = apr_psprintf(r->pool,

+            r->rbuf = apr_psprintf(r->pool, 

                                    "POST %s%s%s HTTP/1.1" CRLF

                                    "User-Agent: Flood/" FLOOD_VERSION CRLF

                                    "Connection: %s" CRLF

@@ -368,7 +368,7 @@
 

                                    "%s"

                                    "%s" CRLF "",

-                                   r->parsed_uri->path,

+                                   r->parsed_uri->path, 

                                    r->parsed_uri->query ? "?" : "",

                                    r->parsed_uri->query ? r->parsed_uri->query 
: "",

                                    r->keepalive ? "Keep-Alive" : "Close",

@@ -393,7 +393,7 @@
         if (e->first_cdata.first->next)

         {

             apr_text *t;

-            t = e->first_cdata.first;

+            t = e->first_cdata.first; 

             url->url = apr_pstrdup(pool, t->text);

             while ((t = t->next))

             {

@@ -411,7 +411,7 @@
         apr_xml_attr *attr = e->attr;

         while (attr)

         {

-            if (strncasecmp(attr->name, XML_URLLIST_METHOD,

+            if (strncasecmp(attr->name, XML_URLLIST_METHOD, 

                             FLOOD_STRLEN_MAX) == 0) {

                 if (strncasecmp(attr->value, XML_URLLIST_METHOD_POST, 4) == 0)

                     url->method = POST;

@@ -428,7 +428,7 @@
                     return APR_EGENERAL;

                 }

             }

-            else if (strncasecmp(attr->name, XML_URLLIST_PAYLOAD,

+            else if (strncasecmp(attr->name, XML_URLLIST_PAYLOAD, 

                                  FLOOD_STRLEN_MAX) == 0) {

                 url->payload = (char*)attr->value;

             }

@@ -438,7 +438,7 @@
                 url->predelay = strtoll(attr->value, &endptr, 10);

                 if (*endptr != '\0')

                 {

-                    apr_file_printf(local_stderr,

+                    apr_file_printf(local_stderr, 

                                     "Attribute %s has invalid value %s.\n",

                                     XML_URLLIST_PREDELAY, attr->value);

                     return APR_EGENERAL;

@@ -464,7 +464,7 @@
                 url->postdelay = strtoll(attr->value, &endptr, 10);

                 if (*endptr != '\0')

                 {

-                    apr_file_printf(local_stderr,

+                    apr_file_printf(local_stderr, 

                                     "Attribute %s has invalid value %s.\n",

                                     XML_URLLIST_POSTDELAY, attr->value);

                     return APR_EGENERAL;

@@ -484,38 +484,38 @@
                 }

                 url->postdelayprecision *= APR_USEC_PER_SEC;

             }

-            else if (strncasecmp(attr->name,

-                                 XML_URLLIST_PAYLOAD_TEMPLATE,

+            else if (strncasecmp(attr->name, 

+                                 XML_URLLIST_PAYLOAD_TEMPLATE, 

                                  FLOOD_STRLEN_MAX) == 0) {

                 url->payloadtemplate = (char*)attr->value;

             }

-            else if (strncasecmp(attr->name,

-                                 XML_URLLIST_REQUEST_TEMPLATE,

+            else if (strncasecmp(attr->name, 

+                                 XML_URLLIST_REQUEST_TEMPLATE, 

                                  FLOOD_STRLEN_MAX) == 0) {

                 url->requesttemplate = (char*)attr->value;

             }

-            else if (strncasecmp(attr->name,

-                                 XML_URLLIST_RESPONSE_TEMPLATE,

+            else if (strncasecmp(attr->name, 

+                                 XML_URLLIST_RESPONSE_TEMPLATE, 

                                  FLOOD_STRLEN_MAX) == 0) {

                 url->responsetemplate = (char*)attr->value;

             }

-            else if (strncasecmp(attr->name,

-                                 XML_URLLIST_RESPONSE_SCRIPT,

+            else if (strncasecmp(attr->name, 

+                                 XML_URLLIST_RESPONSE_SCRIPT, 

                                  FLOOD_STRLEN_MAX) == 0) {

                 url->responsescript = (char*)attr->value;

             }

-            else if (strncasecmp(attr->name,

+            else if (strncasecmp(attr->name, 

                                  XML_URLLIST_RESPONSE_NAME,

                                  FLOOD_STRLEN_MAX) == 0) {

                 url->responsename = (char*)attr->value;

                 url->responselen = strlen((char*)attr->value);

             }

-            else if (strncasecmp(attr->name,

+            else if (strncasecmp(attr->name, 

                                  XML_URLLIST_USER,

                                  FLOOD_STRLEN_MAX) == 0) {

                 url->user = (char*)attr->value;

             }

-            else if (strncasecmp(attr->name,

+            else if (strncasecmp(attr->name, 

                                  XML_URLLIST_PASSWORD,

                                  FLOOD_STRLEN_MAX) == 0) {

                 url->password = (char*)attr->value;

@@ -531,7 +531,7 @@
 

     return APR_SUCCESS;

 }

-

+        

 static apr_status_t parse_xml_seq_info(apr_xml_elem *e,

                                        round_robin_profile_t *p,

                                        apr_pool_t *pool)

@@ -548,8 +548,8 @@
                             FLOOD_STRLEN_MAX) == 0) {

                 seqname = (char*)attr->value;

                 seqnamelen = strlen(seqname);

-            }

-            else if (strncasecmp(attr->name,

+            }             

+            else if (strncasecmp(attr->name, 

                          XML_URLLIST_SEQUENCE_LIST,

                          FLOOD_STRLEN_MAX) == 0) {

                 /* FIXME: ap_getword needs to be in apr-util! */

@@ -559,14 +559,14 @@
                 while (*end && (end = strchr(end, ','))) {

                     count++;

                     end++;

-                }

+                } 

                 seqlist = apr_palloc(pool, sizeof(char*) * count);

                 seqcount = count;

 

                 cur = (char*)attr->value;

                 end = strchr(cur, ',');

                 for (num = 0; num < count; num++) {

-                    while (apr_isspace(*cur)) {

+                    while (apr_isspace(*cur)) { 

                         cur++;

                     }

                     if (end) {

@@ -579,10 +579,10 @@
                         seqlist[num] = apr_pstrdup(pool, cur);

                     }

                 }

-            }

-            attr = attr->next;

+            } 

+            attr = attr->next; 

         }

-    }

+    }             

     for (curseq = 0; curseq < seqcount; curseq++) {

         apr_hash_set(p->state, seqname, seqnamelen, seqlist[curseq]);

         for (child_url_elem = e->first_child; child_url_elem;

@@ -604,19 +604,19 @@
                 }

                 /* Expand them. */

                 if (p->url[p->current_url].payloadtemplate) {

-                    p->url[p->current_url].payloadtemplate =

+                    p->url[p->current_url].payloadtemplate = 

                         handle_param_string(p,

                                         p->url[p->current_url].payloadtemplate,

                                         EPE_PASSTHROUGH);

                 }

                 if (p->url[p->current_url].requesttemplate) {

-                    p->url[p->current_url].requesttemplate =

+                    p->url[p->current_url].requesttemplate = 

                         handle_param_string(p,

                                         p->url[p->current_url].requesttemplate,

                                         EPE_PASSTHROUGH);

                 }

                 if (p->url[p->current_url].responsetemplate) {

-                    p->url[p->current_url].responsetemplate =

+                    p->url[p->current_url].responsetemplate = 

                         handle_param_string(p,

                                         
p->url[p->current_url].responsetemplate,

                                         EPE_PASSTHROUGH);

@@ -640,7 +640,7 @@
             if (e->attr) {

                 apr_xml_attr *attr = e->attr;

                 while (attr) {

-                    if (strncasecmp(attr->name,

+                    if (strncasecmp(attr->name, 

                                     XML_URLLIST_SEQUENCE_LIST,

                                     FLOOD_STRLEN_MAX) == 0) {

                         char *end = (char*)attr->value;

@@ -715,7 +715,7 @@
             apr_file_printf(local_stderr,

                             "Profile '%s' has element <%s> with no value, 
assuming 1.\n",

                             profile_name, XML_PROFILE_COUNT);

-            p->execute_rounds = 1;

+            p->execute_rounds = 1;     

         }

     }

 

@@ -800,16 +800,16 @@
 

     if (rp->url[rp->current_url].requesttemplate)

     {

-        r->uri = parse_param_string(rp,

+        r->uri = parse_param_string(rp, 

                                     rp->url[rp->current_url].requesttemplate);

     }

     else

         r->uri = rp->url[rp->current_url].url;

-

+      

     r->method = rp->url[rp->current_url].method;

 

     /* We're created by calloc, so no need to set payload to be null or

-     * payloadsize to be 0.

+     * payloadsize to be 0. 

      */

     if (rp->url[rp->current_url].payload)

     {

@@ -818,7 +818,7 @@
     }

     else if (rp->url[rp->current_url].payloadtemplate)

     {

-        r->payload = parse_param_string(rp,

+        r->payload = parse_param_string(rp, 

                                     rp->url[rp->current_url].payloadtemplate);

         r->payloadsize = strlen(r->payload);

     }

@@ -877,7 +877,7 @@
     }

     if (!r->parsed_uri->port)

     {

-        r->parsed_uri->port =

+        r->parsed_uri->port = 

                          
apr_uri_default_port_for_scheme(r->parsed_uri->scheme);

     }

     if (!r->parsed_uri->path) /* If / is not there, be nice.  */

@@ -897,70 +897,43 @@
                                      response_t *resp)

 {

     round_robin_profile_t *rp;

-    char *cookieheader, *cookievalue, *cookieend, *respend;

-    unsigned size;

+    char *cookieheader, *cookievalue, *cookieend;

 

     rp = (round_robin_profile_t*)profile;

 

-    cookieend = resp->rbuf; /* sets next search point to beginning of rbuf */

-    respend = cookieend + resp->rbufsize; /* response ends at end of rbuf */

-

-    /*-----------------6/30/2003 0:15AM-----------------

-     * Improved this code a little. Now handles multiple cookies - NT

-     * Also will properly handle case of replacing cookies.

-     * The current search may still find false positives.

-     * --------------------------------------------------*/

-    while ((cookieheader = strstr(cookieend, "Set-Cookie: ")) != NULL)

-    { /* The while handles the poss. of >1 Set-Cookie! */

-      /* Point to the value */

-      cookieheader += 12;

-      cookievalue = (char*) memchr(cookieheader, '=', respend - cookieheader);

-      if (cookievalue)

-      {

-        cookie_t *cookie = NULL, *cook = rp->cookie;

-

-        size = cookievalue - cookieheader;

-        while (cook)

-        {

-          if ((strlen(cook->name)==size)&&

-              (!strncasecmp(cookieheader, cook->name, size)))

-          { /* Size check needed because one name may be subset of other */

-            cookie = cook; /* found cookie, exit loop */

-            break;

-          }

-          cook = cook -> next;

-        }

-        if (!cookie) /* at this point same as saying (!cook) */

-        {

-          cookie = apr_pcalloc(rp->pool, sizeof(cookie_t));

-          cookie->name = apr_palloc(rp->pool, ++size);

-          /* bump up size for null termination */

-          apr_cpystrn(cookie->name, cookieheader, size);

-        }

-

-        cookieheader = cookievalue + 1;

-        cookieend = (char*) memchr(cookieheader, '\r', respend - cookieheader);

-        /* above calculation derives REAL cookieend */

-        if (!cookieend) /* This should not be happening. */

-          break; /* Stop cookie search now! Drop current attempt! */

-        cookievalue = (char*) memchr(cookieheader, ';', cookieend - 
cookieheader);

-        /* First using REAL cookieend! */

-        if (!cookievalue)

-          cookievalue = cookieend;

-        size = cookievalue + 1 - cookieheader;

-        /* !cook: If exited while loop above without finding cookie match,

-         * then value wasn't previously set. */

-        if ((!cook)||(size > strlen(cookie->value)+1))

-        {

-          cookie->value = apr_palloc(rp->pool, size);

-        }

-        apr_cpystrn(cookie->value, cookieheader, size); /* copy in new value */

-        if (!cook) /* if cookie wasn't in linked list, put it in now! */

+    /* FIXME: This algorithm sucks.  I need to be shot for writing such 

+     * atrocious code.  Grr.  */

+    cookieheader = strstr(resp->rbuf, "Set-Cookie: ");

+    if (cookieheader)

+    {

+        /* Point to the value */

+        cookieheader += 12;

+        cookievalue = (char*) memchr(cookieheader, '=', 

+                      resp->rbufsize - (int)(cookieheader - 
(int)(resp->rbuf)));

+        if (cookievalue)

         {

-          cookie->next = rp->cookie;

-          rp->cookie = cookie;

+            cookie_t * cookie = apr_pcalloc(rp->pool, sizeof(cookie_t));

+

+            ++cookievalue;

+            cookie->name = apr_palloc(rp->pool, cookievalue - cookieheader);

+            apr_cpystrn(cookie->name, cookieheader, cookievalue - 
cookieheader);

+

+            cookieheader = cookievalue;

+            cookieend = (char*) memchr(cookieheader, '\r', 

+                      resp->rbufsize - (int)(cookieheader - 
(int)(resp->rbuf)));

+            cookievalue = (char*) memchr(cookieheader, ';', 

+                                  cookieend - cookieheader);

+            if (!cookievalue)

+                cookievalue = cookieend;

+            

+            ++cookievalue;

+            

+            cookie->value = apr_palloc(rp->pool, cookievalue - cookieheader);

+            apr_cpystrn(cookie->value, cookieheader, 

+                        cookievalue - cookieheader);

+            cookie->next = rp->cookie;

+            rp->cookie = cookie;

         }

-      }

     }

     if (rp->url[rp->current_url].responsetemplate)

     {

@@ -969,7 +942,7 @@
         regmatch_t match[10];

         regex_t re;

 

-        expanded = expand_param_string(rp,

+        expanded = expand_param_string(rp, 

                                     rp->url[rp->current_url].responsetemplate);

         regcomp(&re, expanded, REG_EXTENDED);

         status = regexec(&re, resp->rbuf, 10, match, 0);

@@ -1001,7 +974,7 @@
 

         char **args;

         const char *progname;

-

+        

 

         if ((rv = apr_procattr_create(&procattr, rp->pool)) != APR_SUCCESS) {

             apr_file_printf(local_stderr,

@@ -1169,7 +1142,7 @@
     /* Adjust counters for profile */

     if (rp->current_url >= rp->urls) {

         rp->current_url = 0;

-

+        

         /* Loop cond tells us when to stop. */

         rp->current_round++;

     }

@@ -1183,7 +1156,7 @@
     if (rp->current_round >= rp->execute_rounds)

         return 0;

     else { /* we'll continue, so do delay stuff now if necessary */

-

+        

         /* If they want a sleep, do it now. */

         if (rp->url[real_current_url].postdelay) {

             apr_int64_t real_postdelay = rp->url[real_current_url].postdelay;

Reply via email to