]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Backport:
authorGraham Leggett <minfrin@apache.org>
Sun, 22 Aug 2021 09:51:33 +0000 (09:51 +0000)
committerGraham Leggett <minfrin@apache.org>
Sun, 22 Aug 2021 09:51:33 +0000 (09:51 +0000)
  *) back port the add of balancer_manage in mod_proxy_balancer.
     trunk patch: http://svn.apache.org/r1859235
                  http://svn.apache.org/r1887176
                  http://svn.apache.org/r1887359
                  http://svn.apache.org/r1887144
     Backport version for 2.4.x of patch:
          https://people.apache.org/~jfclere/patches/patch.210810.txt
     +1: jfclere, jim, minfrin

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1892522 13f79535-47bb-0310-9956-ffa450edef68

STATUS
include/ap_mmn.h
modules/proxy/mod_proxy.h
modules/proxy/mod_proxy_balancer.c

diff --git a/STATUS b/STATUS
index c902247505410e0b11734c7c7068fe35c4094b2d..07a493cf1b130858cb72149fab0d40e222c37492 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -142,20 +142,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  *) back port the add of balancer_manage in mod_proxy_balancer.
-     trunk patch: http://svn.apache.org/r1859235
-                  http://svn.apache.org/r1887176
-                  http://svn.apache.org/r1887359
-                  http://svn.apache.org/r1887144
-     Backport version for 2.4.x of patch:
-          https://people.apache.org/~jfclere/patches/patch.210810.txt
-     +1: jfclere, jim, minfrin
-     jfclere: The previous proposal was removing the Referer check.
-     jorton: r1859235 has an "ok2change" param in the newly added
-             balancer_process_balancer_worker() but this is missing in the
-             backport patch, maybe include r1887144 for completeness?
-     jfclere: Fixed: Added in the patch.210810.txt
-
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]
index a162b8f90deb1efbb555d2b2528d291e5d7344c6..799998e9f76cebf4bd22358ec37379fbfbe2c729 100644 (file)
  *                           mod_dav.h.
  * 20120211.112 (2.4.49-dev) Add deliver_report and gather_reports hooks.
  * 20120211.113 (2.4.49-dev) Add method_precondition hook.
+ * 20120211.114 (2.4.49-dev) Add optional balancer_manage function.
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20120211
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 113                 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 114                 /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index bf6bbd0fb3385b4eaadf61b83b58b765bb796aba..c307bc9060adcbad69317383c512705ae0dfc9d3 100644 (file)
@@ -1169,6 +1169,16 @@ PROXY_DECLARE(apr_status_t) ap_proxy_sync_balancer(proxy_balancer *b,
                                                    server_rec *s,
                                                    proxy_server_conf *conf);
 
+/**
+ * Configure and create workers (and balancer) in mod_balancer.
+ * @param r request
+ * @param params table with the parameters like b=mycluster etc.
+ * @return 404 when the worker/balancer doesn't exist,
+ *         400 if something is invalid
+ *         200 for success.
+ */ 
+APR_DECLARE_OPTIONAL_FN(apr_status_t, balancer_manage,
+        (request_rec *, apr_table_t *params));
 
 /**
  * Find the matched alias for this request and setup for proxy handler
index ece8498b6d9fdfedd7b413e9a437bd6825ad85ed..db469528bfc134b0ada8fe6f2eb9c70bf041412e 100644 (file)
@@ -1120,119 +1120,20 @@ static int safe_referer(request_rec *r, const char *ref)
     return strcasecmp(uri.hostname, ap_get_server_name(r)) == 0;
 }
 
-/* Manages the loadfactors and member status
- *   The balancer, worker and nonce are obtained from
- *   the request args (?b=...&w=...&nonce=....).
- *   All other params are pulled from any POST
- *   data that exists.
- * TODO:
- *   /.../<whatever>/balancer/worker/nonce
+/*
+ * Process the paramters and add or update the worker of the
+ * balancer.  Must only be called if the nonce has been validated to
+ * match, to avoid XSS attacks.
  */
-static int balancer_handler(request_rec *r)
+static int balancer_process_balancer_worker(request_rec *r, proxy_server_conf *conf,
+                                            proxy_balancer *bsel,
+                                            proxy_worker *wsel,
+                                            apr_table_t *params)
+
 {
-    void *sconf;
-    proxy_server_conf *conf;
-    proxy_balancer *balancer, *bsel = NULL;
-    proxy_worker *worker, *wsel = NULL;
-    proxy_worker **workers = NULL;
-    apr_table_t *params;
-    int i, n;
-    int ok2change = 1;
-    const char *name, *ref;
-    const char *action;
     apr_status_t rv;
-
-    /* is this for us? */
-    if (strcmp(r->handler, "balancer-manager")) {
-        return DECLINED;
-    }
-
-    r->allowed = 0
-    | (AP_METHOD_BIT << M_GET)
-    | (AP_METHOD_BIT << M_POST);
-    if ((r->method_number != M_GET) && (r->method_number != M_POST)) {
-        return DECLINED;
-    }
-
-    sconf = r->server->module_config;
-    conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
-    params = apr_table_make(r->pool, 10);
-
-    balancer = (proxy_balancer *)conf->balancers->elts;
-    for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
-#if APR_HAS_THREADS
-        if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01189)
-                          "%s: Lock failed for balancer_handler",
-                          balancer->s->name);
-        }
-#endif
-        ap_proxy_sync_balancer(balancer, r->server, conf);
-#if APR_HAS_THREADS
-        if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01190)
-                          "%s: Unlock failed for balancer_handler",
-                          balancer->s->name);
-        }
-#endif
-    }
-
-    if (r->args && (r->method_number == M_GET)) {
-        const char *allowed[] = { "w", "b", "nonce", "xml", NULL };
-        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01191) "parsing r->args");
-
-        push2table(r->args, params, allowed, r->pool);
-    }
-    if (r->method_number == M_POST) {
-        apr_bucket_brigade *ib;
-        apr_size_t len = 1024;
-        char *buf = apr_pcalloc(r->pool, len+1);
-
-        ib = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
-        rv = ap_get_brigade(r->input_filters, ib, AP_MODE_READBYTES,
-                                APR_BLOCK_READ, len);
-        if (rv != APR_SUCCESS) {
-            return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
-        }
-        apr_brigade_flatten(ib, buf, &len);
-        buf[len] = '\0';
-        push2table(buf, params, NULL, r->pool);
-    }
-
-    /* Ignore parameters if this looks like XSRF */
-    ref = apr_table_get(r->headers_in, "Referer");
-    if (apr_table_elts(params)
-        && (!ref || !safe_referer(r, ref))) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10187)
-                      "ignoring params in balancer-manager cross-site access");
-        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), 0);
-
-    if ((name = apr_table_get(params, "w"))) {
-        wsel = ap_proxy_get_worker(r->pool, bsel, conf, name);
-    }
-
-
-    /* Check that the supplied nonce matches this server's nonce;
-     * otherwise ignore all parameters, to prevent a CSRF attack. */
-    if (!bsel ||
-        (*bsel->s->nonce &&
-         (
-          (name = apr_table_get(params, "nonce")) == NULL ||
-          strcmp(bsel->s->nonce, name) != 0
-         )
-        )
-       ) {
-        apr_table_clear(params);
-        ok2change = 0;
-    }
-
     /* First set the params */
-    if (wsel && ok2change) {
+    if (wsel) {
         const char *val;
         int was_usable = PROXY_WORKER_IS_USABLE(wsel);
 
@@ -1341,7 +1242,7 @@ static int balancer_handler(request_rec *r)
 
     }
 
-    if (bsel && ok2change) {
+    if (bsel) {
         const char *val;
         int ival;
         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01193)
@@ -1488,11 +1389,62 @@ static int balancer_handler(request_rec *r)
         }
 
     }
+    return APR_SUCCESS;
+}
+
+/*
+ * Process a request for balancer or worker management from another module
+ */
+static apr_status_t balancer_manage(request_rec *r, apr_table_t *params)
+{
+    void *sconf;
+    proxy_server_conf *conf;
+    proxy_balancer *bsel = NULL;
+    proxy_worker *wsel = NULL;
+    const char *name;
+    sconf = r->server->module_config;
+    conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
+
+    /* Process the parameters */
+    if ((name = apr_table_get(params, "b"))) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "balancer_manage "
+                  "balancer: %s", name);
+        bsel = ap_proxy_get_balancer(r->pool, conf,
+            apr_pstrcat(r->pool, BALANCER_PREFIX, name, NULL), 0);
+    }
 
+    if ((name = apr_table_get(params, "w"))) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "balancer_manage "
+                  "worker: %s", name);
+        wsel = ap_proxy_get_worker(r->pool, bsel, conf, name);
+    }
+    if (bsel) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "balancer_manage "
+                  "balancer: %s",  bsel->s->name);
+        return(balancer_process_balancer_worker(r, conf, bsel, wsel, params));
+    }
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "balancer_manage failed: "
+                      "No balancer!");
+    return HTTP_BAD_REQUEST;
+}
+
+/*
+ * builds the page and links to configure via HTLM or XML.
+ */
+static void balancer_display_page(request_rec *r, proxy_server_conf *conf,
+                                  proxy_balancer *bsel,
+                                  proxy_worker *wsel,
+                                  int usexml)
+{
+    const char *action;
+    proxy_balancer *balancer;
+    proxy_worker *worker;
+    proxy_worker **workers;
+    int i, n;
     action = ap_construct_url(r->pool, r->uri, r);
     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01204) "genning page");
 
-    if (apr_table_get(params, "xml")) {
+    if (usexml) {
         char date[APR_RFC822_DATE_LEN];
         ap_set_content_type(r, "text/xml");
         ap_rputs("<?xml version='1.0' encoding='UTF-8' ?>\n", r);
@@ -1938,6 +1890,123 @@ static int balancer_handler(request_rec *r)
         ap_rputs("</body></html>\n", r);
         ap_rflush(r);
     }
+}
+
+/* Manages the loadfactors and member status
+ *   The balancer, worker and nonce are obtained from
+ *   the request args (?b=...&w=...&nonce=....).
+ *   All other params are pulled from any POST
+ *   data that exists.
+ * TODO:
+ *   /.../<whatever>/balancer/worker/nonce
+ */
+static int balancer_handler(request_rec *r)
+{
+    void *sconf;
+    proxy_server_conf *conf;
+    proxy_balancer *balancer, *bsel = NULL;
+    proxy_worker *wsel = NULL;
+    apr_table_t *params;
+    int i;
+    const char *name, *ref;
+    apr_status_t rv;
+
+    /* is this for us? */
+    if (strcmp(r->handler, "balancer-manager")) {
+        return DECLINED;
+    }
+
+    r->allowed = 0
+    | (AP_METHOD_BIT << M_GET)
+    | (AP_METHOD_BIT << M_POST);
+    if ((r->method_number != M_GET) && (r->method_number != M_POST)) {
+        return DECLINED;
+    }
+
+    sconf = r->server->module_config;
+    conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
+    params = apr_table_make(r->pool, 10);
+
+    balancer = (proxy_balancer *)conf->balancers->elts;
+    for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
+#if APR_HAS_THREADS
+        if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01189)
+                          "%s: Lock failed for balancer_handler",
+                          balancer->s->name);
+        }
+#endif
+        ap_proxy_sync_balancer(balancer, r->server, conf);
+#if APR_HAS_THREADS
+        if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01190)
+                          "%s: Unlock failed for balancer_handler",
+                          balancer->s->name);
+        }
+#endif
+    }
+
+    if (r->args && (r->method_number == M_GET)) {
+        const char *allowed[] = { "w", "b", "nonce", "xml", NULL };
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01191) "parsing r->args");
+
+        push2table(r->args, params, allowed, r->pool);
+    }
+    if (r->method_number == M_POST) {
+        apr_bucket_brigade *ib;
+        apr_size_t len = 1024;
+        char *buf = apr_pcalloc(r->pool, len+1);
+
+        ib = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
+        rv = ap_get_brigade(r->input_filters, ib, AP_MODE_READBYTES,
+                                APR_BLOCK_READ, len);
+        if (rv != APR_SUCCESS) {
+            return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
+        }
+        apr_brigade_flatten(ib, buf, &len);
+        buf[len] = '\0';
+        push2table(buf, params, NULL, r->pool);
+    }
+
+    /* Ignore parameters if this looks like XSRF */
+    ref = apr_table_get(r->headers_in, "Referer");
+    if (apr_table_elts(params)
+        && (!ref || !safe_referer(r, ref))) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10187)
+                      "ignoring params in balancer-manager cross-site access %s: %s", ref, ap_get_server_name(r));
+        apr_table_clear(params);
+    }
+
+    /* Process the parameters */
+    if ((name = apr_table_get(params, "b")))
+        bsel = ap_proxy_get_balancer(r->pool, conf,
+            apr_pstrcat(r->pool, BALANCER_PREFIX, name, NULL), 0);
+
+    if ((name = apr_table_get(params, "w"))) {
+        wsel = ap_proxy_get_worker(r->pool, bsel, conf, name);
+    }
+
+
+    /* Check that the supplied nonce matches this server's nonce;
+     * otherwise ignore all parameters, to prevent a CSRF
+     * attack. */
+    if (bsel
+        && (*bsel->s->nonce
+            && ((name = apr_table_get(params, "nonce")) != NULL
+                && strcmp(bsel->s->nonce, name) == 0))) {
+        /* Process the parameters and add the worker to the balancer */
+        rv = balancer_process_balancer_worker(r, conf, bsel, wsel, params);
+        if (rv != APR_SUCCESS) {
+            return HTTP_BAD_REQUEST;
+        }
+    }
+
+    /* display the HTML or XML page */
+    if (apr_table_get(params, "xml")) {
+        balancer_display_page(r, conf, bsel, wsel, 1);
+    } else {
+        balancer_display_page(r, conf, bsel, wsel, 0);
+    }
     return DONE;
 }
 
@@ -1986,6 +2055,7 @@ static void ap_proxy_balancer_register_hook(apr_pool_t *p)
     static const char *const aszPred[] = { "mpm_winnt.c", "mod_slotmem_shm.c", NULL};
     static const char *const aszPred2[] = { "mod_proxy.c", NULL};
      /* manager handler */
+    APR_REGISTER_OPTIONAL_FN(balancer_manage);
     ap_hook_post_config(balancer_post_config, aszPred2, NULL, APR_HOOK_MIDDLE);
     ap_hook_pre_config(balancer_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_handler(balancer_handler, NULL, NULL, APR_HOOK_FIRST);