From 31c4a9e21ebf55a7252a6e9363e671264e281425 Mon Sep 17 00:00:00 2001
From: Jim Jagielski <jim@apache.org>
Date: Thu, 13 Jan 2011 15:59:22 +0000
Subject: [PATCH] Move nonce to balancer struct and add logic for nonce and
 growth. Adjust mmn and update doccos

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1058629 13f79535-47bb-0310-9956-ffa450edef68
---
 docs/manual/mod/mod_proxy.xml          | 19 ++++++++
 docs/manual/mod/mod_proxy_balancer.xml | 33 +------------
 include/ap_mmn.h                       |  5 ++
 modules/proxy/mod_proxy.c              | 19 ++++++++
 modules/proxy/mod_proxy.h              |  8 ++--
 modules/proxy/mod_proxy_balancer.c     | 64 ++++++--------------------
 modules/proxy/proxy_util.c             |  5 ++
 7 files changed, 70 insertions(+), 83 deletions(-)

diff --git a/docs/manual/mod/mod_proxy.xml b/docs/manual/mod/mod_proxy.xml
index bcc0b7744f..8c127f6bdb 100644
--- a/docs/manual/mod/mod_proxy.xml
+++ b/docs/manual/mod/mod_proxy.xml
@@ -837,6 +837,7 @@ expressions</description>
         ProxyPass /example http://backend.example.com max=20 ttl=120 retry=300
     </example>
 
+    <table border="2"><tr><th>BalancerMember parameters</th></tr></table>
     <table>
     <tr><th>Parameter</th>
         <th>Default</th>
@@ -1009,6 +1010,7 @@ expressions</description>
     parameters can be add to this virtual worker. See <module>mod_proxy_balancer</module>
     for more information about how the balancer works.
     </p>
+    <table border="2"><tr><th>Balancer parameters</th></tr></table>
     <table>
     <tr><th>Parameter</th>
         <th>Default</th>
@@ -1058,6 +1060,23 @@ expressions</description>
         force the worker into error state when the backend returns any status code
         in the list. Worker recovery behaves the same as other worker errors.
     </td></tr>
+    <tr><td>nonce</td>
+        <td>&lt;auto&gt;</td>
+        <td>The protective nonce used in the <code>balancer-manager</code> application page.
+        The default is to use an automatically determined UUID-based
+        nonce, to provide for further protection for the page. If set,
+        then the nonce is set to that value. A setting of <code>None</code>
+        disables all nonce checking.
+    <note><title>Note</title>
+      <p>In addition to the nonce, the <code>balancer-manager</code> page
+      should be protected via an ACL.</p>
+    </note>
+     </td></tr>
+    <tr><td>growth</td>
+        <td>0</td>
+        <td>Number of additional BalancerMembers to allow to be added
+        to this balancer in addition to those defined at configuration. 
+    </td></tr>
     
     </table>
     <p>A sample balancer setup</p>
diff --git a/docs/manual/mod/mod_proxy_balancer.xml b/docs/manual/mod/mod_proxy_balancer.xml
index 1878faa66f..90eef4500f 100644
--- a/docs/manual/mod/mod_proxy_balancer.xml
+++ b/docs/manual/mod/mod_proxy_balancer.xml
@@ -62,7 +62,8 @@
     for use: Request Counting, Weighted Traffic Counting and Pending Request
     Counting. These are controlled via the <code>lbmethod</code> value of
     the Balancer definition. See the <directive module="mod_proxy">ProxyPass</directive> 
-    directive for more information.</p>
+    directive for more information, especially regarding how to
+    configure the Balancer and BalancerMembers.</p>
 </section>
 
 <section id="stickyness">
@@ -300,34 +301,4 @@
     be to high for production servers under high load.</p>
 </section>
 
-<directivesynopsis>
-<name>BalancerNonce</name>
-<description>Set the nonce used in the balancer-manager application</description>
-<syntax>BalancerNonce Default|None|Set "value"</syntax>
-<default>ProxyStatus Default</default>
-<contextlist><context>server config</context>
-<context>virtual host</context>
-</contextlist>
-<compatibility>Available in version 2.4 and later</compatibility>
-
-<usage>
-    <p>This directive specifies the protective nonce used in the
-    <code>balancer-manager</code> application page.</p>
-    <p>The default is to use an automatically determined UUID-based
-    nonce, to provide for further protection for the page. If set
-    to <code>Set</code>, then the next argument sets the nonce to that
-    value. A setting of <code>None</code> disables all nonce checking.</p>
-    
-    <example>
-    BalancerNonce Set "RealGudSharedSecret"
-    </example>
-
-    <note><title>Note</title>
-      <p>In addition to the nonce, the <code>balancer-manager</code> page
-      should be protected via an ACL.</p>
-    </note>
-
-</usage>
-</directivesynopsis>
-
 </modulesynopsis>
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index 9cf3d41a0e..db3bfa1c5e 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -289,6 +289,11 @@
  * 20101113.2 (2.3.9-dev)  Add ap_expr_exec_re()
  * 20101204.0 (2.3.10-dev) Add _t to ap_expr's typedef names
  * 20101223.0 (2.3.11-dev) Remove cleaned from proxy_conn_rec.
+ * 20101223.1 (2.3.11-dev) Rework mod_proxy, et.al. Remove proxy_worker_stat
+ *                         and replace w/ proxy_worker_shared; remove worker
+ *                         info from scoreboard and use slotmem; Allow
+ *                         dynamic growth of balancer members; Remove
+ *                         BalancerNonce in favor of 'nonce' parameter.
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index 94c2954b9c..5988ed530f 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -399,6 +399,25 @@ static const char *set_balancer_param(proxy_server_conf *conf,
         }
 
     }
+    else if (!strcasecmp(key, "nonce")) {
+        if (!strcasecmp(val, "None")) {
+            *balancer->nonce = '\0';
+        } 
+        else {
+            if (strlen(val) > sizeof(balancer->nonce)-1) {
+                return "Provided nonce is too large";
+            }
+            else {
+                apr_cpystrn(balancer->nonce, val, sizeof(balancer->nonce));
+            }
+        }
+    }
+    else if (!strcasecmp(key, "growth")) {
+        ival = atoi(val);
+        if (ival < 1 || ival > 100)   /* arbitrary limit here */
+            return "growth must be between 1 and 100";
+        balancer->growth = ival;
+    }
     else {
         return "unknown Balancer parameter";
     }
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index 0c7bdac96d..b66d524e1a 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -42,6 +42,7 @@
 #include "apr_reslist.h"
 #define APR_WANT_STRFUNC
 #include "apr_want.h"
+#include "apr_uuid.h"
 #include "util_mutex.h"
 #include "apr_global_mutex.h"
 #include "apr_thread_mutex.h"
@@ -369,12 +370,13 @@ struct proxy_balancer {
     const char      *sticky;          /* sticky session identifier */
     int             max_attempts;     /* Number of attempts before failing */
 
+    apr_time_t      updated;    /* timestamp of last update */
+    char nonce[APR_UUID_FORMATTED_LENGTH + 1];
+    apr_global_mutex_t  *mutex; /* global lock for updating lb params */
+    void            *context;   /* general purpose storage */
     int             sticky_force:1;   /* Disable failover for sticky sessions */
     int             scolonsep:1;      /* true if ';' seps sticky session paths */
     int             max_attempts_set:1;
-    void            *context;   /* general purpose storage */
-    apr_time_t      updated;    /* timestamp of last update */
-    apr_global_mutex_t  *mutex; /* global lock for updating lb params */
 };
 
 struct proxy_balancer_method {
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index 7990529dd4..e7566051c7 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -21,7 +21,6 @@
 #include "ap_mpm.h"
 #include "apr_version.h"
 #include "apr_hooks.h"
-#include "apr_uuid.h"
 #include "apr_date.h"
 
 static const char *balancer_mutex_type = "proxy-balancer-shm";
@@ -29,8 +28,6 @@ ap_slotmem_provider_t *storage = NULL;
 
 module AP_MODULE_DECLARE_DATA proxy_balancer_module;
 
-static char balancer_nonce[APR_UUID_FORMATTED_LENGTH + 1];
-
 /*
  * Register our mutex type before the config is read so we
  * can adjust the mutex settings using the Mutex directive.
@@ -697,7 +694,6 @@ static apr_status_t lock_remove(void *data)
 static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog,
                          apr_pool_t *ptemp, server_rec *s)
 {
-    apr_uuid_t uuid;
     void *data;
     void *sconf = s->module_config;
     proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
@@ -711,10 +707,6 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog,
                                apr_pool_cleanup_null, s->process->pool);
         return OK;
     }
-    /* Retrieve a UUID and store the nonce for the lifetime of
-     * the process. */
-    apr_uuid_get(&uuid);
-    apr_uuid_format(balancer_nonce, &uuid);
 
     /*
      * Get worker slotmem setup
@@ -849,20 +841,23 @@ static int balancer_handler(request_rec *r)
         }
     }
 
-    /* Check that the supplied nonce matches this server's nonce;
-     * otherwise ignore all parameters, to prevent a CSRF attack. */
-    if (*balancer_nonce &&
-        ((name = apr_table_get(params, "nonce")) == NULL
-        || strcmp(balancer_nonce, name) != 0)) {
-        apr_table_clear(params);
-    }
-
     if ((name = apr_table_get(params, "b")))
         bsel = ap_proxy_get_balancer(r->pool, conf,
             apr_pstrcat(r->pool, BALANCER_PREFIX, name, NULL));
+
     if ((name = apr_table_get(params, "w"))) {
         wsel = ap_proxy_get_worker(r->pool, bsel, conf, name);
     }
+
+#if 0
+    /* Check that the supplied nonce matches this server's nonce;
+     * otherwise ignore all parameters, to prevent a CSRF attack. */
+    if (*balancer_nonce &&
+        ((name = apr_table_get(params, "nonce")) == NULL
+         || strcmp(balancer_nonce, name) != 0)) {
+        apr_table_clear(params);
+    }
+#endif
     /* First set the params */
     /*
      * Note that it is not possible set the proxy_balancer because it is not
@@ -984,7 +979,7 @@ static int balancer_handler(request_rec *r)
                 ap_rvputs(r, "<tr>\n<td><a href=\"", r->uri, "?b=",
                           balancer->name + sizeof(BALANCER_PREFIX) - 1, "&w=",
                           ap_escape_uri(r->pool, worker->s->name),
-                          "&nonce=", balancer_nonce,
+                          "&nonce=", balancer->nonce,
                           "\">", NULL);
                 ap_rvputs(r, worker->s->name, "</a></td>", NULL);
                 ap_rvputs(r, "<td>", ap_escape_html(r->pool, worker->s->route),
@@ -1049,7 +1044,7 @@ static int balancer_handler(request_rec *r)
             ap_rvputs(r, "value=\"", bsel->name + sizeof(BALANCER_PREFIX) - 1,
                       "\">\n", NULL);
             ap_rvputs(r, "<input type=hidden name=\"nonce\" value=\"",
-                      balancer_nonce, "\">\n", NULL);
+                      bsel->nonce, "\">\n", NULL);
             ap_rvputs(r, "</form>\n", NULL);
             ap_rputs("<hr />\n", r);
         }
@@ -1090,7 +1085,7 @@ static void balancer_child_init(apr_pool_t *p, server_rec *s)
                                              p);
             if (rv != APR_SUCCESS) {
                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
-                             "Failed to reopen mutex %: %s in child",
+                             "Failed to reopen mutex %s: %s in child",
                              balancer->name, balancer_mutex_type);
                 exit(1); /* Ugly, but what else? */
             }
@@ -1111,35 +1106,6 @@ static void balancer_child_init(apr_pool_t *p, server_rec *s)
 
 }
 
-static const char *set_balancer_nonce (cmd_parms *cmd, void *dummy, const char *arg,
-                                       const char *val)
-{
-    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
-    if (err != NULL) {
-        return err;
-    }
-
-    if (!strcasecmp(arg, "None")) {
-        *balancer_nonce = '\0';
-    } else if (!strcasecmp(arg, "Set")) {
-        if (val) {
-            apr_cpystrn(balancer_nonce, val, sizeof(balancer_nonce));
-        } else {
-            return "BalancerNonce Set requires an argument";
-        }
-    } else if (strcasecmp(arg, "Default")) {
-        return "Bad argument for BalancerNonce: Must be 'Set', 'None' or 'Default'";
-    }
-    return NULL;
-}
-
-static const command_rec balancer_cmds[] =
-{
-    AP_INIT_TAKE12("BalancerNonce", set_balancer_nonce, NULL,
-       RSRC_CONF, "Set value for balancer-manager nonce"),
-    {NULL}
-};
-
 static void ap_proxy_balancer_register_hook(apr_pool_t *p)
 {
     /* Only the mpm_winnt has child init hook handler.
@@ -1163,6 +1129,6 @@ AP_DECLARE_MODULE(proxy_balancer) = {
     NULL,       /* merge per-directory config structures */
     NULL,       /* create per-server config structure */
     NULL,       /* merge per-server config structures */
-    balancer_cmds,       /* command apr_table_t */
+    NULL,       /* command apr_table_t */
     ap_proxy_balancer_register_hook /* register hooks */
 };
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 64c112044c..cf81e2474c 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -1332,6 +1332,7 @@ PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p,
 {
     char *c, *q, *uri = apr_pstrdup(p, url);
     proxy_balancer_method *lbmethod;
+    apr_uuid_t uuid;
 
     /* We should never get here without a valid BALANCER_PREFIX... */
 
@@ -1360,6 +1361,10 @@ PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p,
     (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker *));
     (*balancer)->updated = apr_time_now();
     (*balancer)->mutex = NULL;
+    /* Retrieve a UUID and store the nonce for the lifetime of
+     * the process. */
+    apr_uuid_get(&uuid);
+    apr_uuid_format((*balancer)->nonce, &uuid);
 
     return NULL;
 }
-- 
2.40.0