summaryrefslogtreecommitdiff
path: root/src/configfile.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2021-06-19 22:39:20 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2021-08-27 02:16:54 -0400
commit4b9da9f1e8fb12dc136d1a384d003ac502385159 (patch)
tree0cf73a1d4836d2749508cdcd9915a9a04a3106b0 /src/configfile.c
parente34ce5f2177eb70089549662f42d61e176a75421 (diff)
downloadlighttpd-git-4b9da9f1e8fb12dc136d1a384d003ac502385159.tar.gz
[core] parse $HTTP["remote-ip"] CIDR mask at start
parse $HTTP["remote-ip"] CIDR mask into structured data at startup note: adds buffer_move() to configparser.y to reduce memory copying for all config values, and is required for remote-ip to preserve the structured data added after the config value string. (Alternatively, could have normalized the remote-ip value after copying into dc->string)
Diffstat (limited to 'src/configfile.c')
-rw-r--r--src/configfile.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/configfile.c b/src/configfile.c
index a673ad99..74b61aad 100644
--- a/src/configfile.c
+++ b/src/configfile.c
@@ -13,6 +13,7 @@
#include "configfile.h"
#include "plugin.h"
#include "reqpool.h"
+#include "sock_addr.h"
#include "stat_cache.h"
#include "sys-crypto.h"
@@ -2393,6 +2394,74 @@ int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
return ret;
}
+static int config_remoteip_normalize_ipv6(buffer * const b, buffer * const tb) {
+ /* $HTTP["remote-ip"] IPv6 accepted with or without '[]' for config compat
+ * http_request_host_normalize() expects IPv6 with '[]',
+ * and config processing at runtime expects COMP_HTTP_REMOTE_IP
+ * compared without '[]', so strip '[]' after normalization */
+ buffer_clear(tb);
+ if (b->ptr[0] != '[')
+ buffer_append_str3(tb,
+ CONST_STR_LEN("["),
+ BUF_PTR_LEN(b),
+ CONST_STR_LEN("]"));
+ else
+ buffer_append_string_buffer(tb, b);
+
+ int rc = http_request_host_normalize(tb, 0);
+ if (0 == rc) {
+ /* remove surrounding '[]' */
+ size_t blen = buffer_clen(tb);
+ if (blen > 1) buffer_copy_string_len(b, tb->ptr+1, blen-2);
+ }
+ return rc;
+}
+
+int config_remoteip_normalize(buffer * const b, buffer * const tb) {
+ if (b->ptr[0] == '/') return 1; /*(skip AF_UNIX /path/file)*/
+
+ const char * const slash = strchr(b->ptr, '/'); /* CIDR mask */
+ const char * const colon = strchr(b->ptr, ':'); /* IPv6 */
+ unsigned long nm_bits = 0;
+
+ if (NULL != slash) {
+ char *nptr;
+ nm_bits = strtoul(slash + 1, &nptr, 10);
+ if (*nptr || 0 == nm_bits || nm_bits > (NULL != colon ? 128 : 32)) {
+ /*(also rejects (slash+1 == nptr) which results in nm_bits = 0)*/
+ return -1;
+ }
+ buffer_truncate(b, (size_t)(slash - b->ptr));
+ }
+
+ int family = colon ? AF_INET6 : AF_INET;
+ int rc = (family == AF_INET)
+ ? http_request_host_normalize(b, 0)
+ : config_remoteip_normalize_ipv6(b, tb);
+
+ uint32_t len = buffer_clen(b); /*(save len before adding CIDR mask)*/
+ if (nm_bits) {
+ buffer_append_string_len(b, CONST_STR_LEN("/"));
+ buffer_append_int(b, (int)nm_bits);
+ }
+
+ if (0 != rc) {
+ return -1;
+ }
+
+ /* extend b to hold structured data after end of string:
+ * nm_bits and memory-aligned sock_addr for AF_INET or AF_INET6 (28 bytes)*/
+ char *after = buffer_string_prepare_append(b, 1 + 7 + 28);
+ ++after; /*(increment to pos after string end '\0')*/
+ *(unsigned char *)after = (unsigned char)nm_bits;
+ sock_addr * const addr = (sock_addr *)(((uintptr_t)after+1+7) & ~7);
+ if (nm_bits) b->ptr[len] = '\0'; /*(sock_addr_inet_pton() w/o CIDR mask)*/
+ rc = sock_addr_inet_pton(addr, b->ptr, family, 0);
+ if (nm_bits) b->ptr[len] = '/';
+ return (1 == rc);
+}
+
+
static void context_init(server *srv, config_t *context) {
context->srv = srv;
context->ok = 1;