From 074f53744a2eac6787d14fa258dbf0f295407f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Thu, 13 Feb 2014 18:19:07 +0100 Subject: [PATCH] [angel] merge allow_listen_* items * allow_listen_ip ".." -> allow_listen ".." * allow_listen_unix ".." -> allow_listen "unix:.." * allow_listen also takes lists of strings --- contrib/angel.conf | 13 +++---- doc/core_config_angel.xml | 34 ++++++++---------- src/angel/angel_plugin_core.c | 66 ++++++++++++++++++++--------------- tests/base.py | 8 ++--- 4 files changed, 62 insertions(+), 59 deletions(-) diff --git a/contrib/angel.conf b/contrib/angel.conf index b215d2c..a64e5f7 100644 --- a/contrib/angel.conf +++ b/contrib/angel.conf @@ -2,13 +2,14 @@ user "www-data"; max_open_files 16384; copy_env [ "PATH" ]; -# env [ "G_SLICE=always-malloc", "G_DEBUG=gc-friendly" ]; +# env [ "G_SLICE=always-malloc", "G_DEBUG=gc-friendly,fatal_criticals" ]; # wrapper [ "/usr/bin/valgrind", "--leak-check=full", "--show-reachable=yes", "--leak-resolution=high" ]; -# need separate statements for IPv4 and IPv6. if none are configured, allow port 80 and 443 on all IPv4 and IPv6. +# need separate statements for IPv4 and IPv6. if none are configured, allow +# TCP port 80 and 443 on all IPv4 and IPv6. # no port means 80 and 443 are allowed: -# allow_listen_ip "0.0.0.0/0"; -# allow_listen_ip "[::/0]"; +# allow_listen "0.0.0.0/0"; +# allow_listen "[::/0]"; -# allow_listen_ip "0.0.0.0/0:8080"; -# allow_listen_ip "[::/0]:8080"; +# allow_listen "0.0.0.0/0:8080"; +# allow_listen "[::/0]:8080"; diff --git a/doc/core_config_angel.xml b/doc/core_config_angel.xml index d8240f0..b26c962 100644 --- a/doc/core_config_angel.xml +++ b/doc/core_config_angel.xml @@ -214,35 +214,31 @@ - - allow worker to listen on a TCP socket - - network mask (CIDR) + optional port + + allow worker to listen on sockets + + list of network mask (CIDR) + optional port or unix domain socket addresses - The worker uses the angel to bind TCP sockets; the angel checks whether those binds are allowed. If no @allow_listen_ip@ or @allow_listen_unix@ is specified, all TCP binds (IPv4 and IPv6) using port 80 or 443 are allowed. - IPv4 and IPv6 use different masks (no IPv4 to IPv6 mapping), the network length for the CIDR mask is optional (defaulting to a host address), and the port is optional too (allowing both 80 and 443 if omitted). + + The worker uses the angel to bind TCP/unix sockets; the angel checks whether those binds are allowed. If no @allow_listen@ is specified, all TCP binds (IPv4 and IPv6) using port 80 or 443 are allowed. + IPv4 and IPv6 use different masks (no IPv4 to IPv6 mapping), the network length for the CIDR mask is optional (defaults to a host address), and the port is optional too (allowing both 80 and 443 if omitted). + Formats: + * TCP on IPv4: @ipv4@, @ipv4:port@, @ipv4/net@, @ipv4/net:port@ + * TCP on IPv6: @ipv6@, @ipv6/net@, @[ipv6]@, @[ipv6/net]@, @[ipv6]:port@, @[ipv6/net]:port@ + * Unix domain: @unix:/wildcard/path/to/*.socket@ + - Only allow port 8080 for IPv4 and IPv6. + Only allow TCP port 8080 for IPv4 and IPv6 and unix domain socket @/run/lighttpd/internal.sock@. - allow_listen_ip "0.0.0.0/0:8080"; - allow_listen_ip "[::/0]:8080"; + allow_listen [ "0.0.0.0/0:8080", "[::/0]:8080" ]; + allow_listen "unix:/run/lighttpd/internal.sock"; - - allow worker to listen on a unix socket - - path for a unix socket - - - The path can contain wildcards. - - - diff --git a/src/angel/angel_plugin_core.c b/src/angel/angel_plugin_core.c index 0bbadba..f42fc2f 100644 --- a/src/angel/angel_plugin_core.c +++ b/src/angel/angel_plugin_core.c @@ -305,41 +305,50 @@ static void core_listen_mask_free(liPluginCoreListenMask *mask) { g_slice_free(liPluginCoreListenMask, mask); } -static gboolean core_parse_allow_listen_ip(liServer *srv, liPlugin *p, liValue *value, GError **err) { +static gboolean core_parse_allow_listen(liServer *srv, liPlugin *p, liValue *value, GError **err) { liPluginCoreConfig *pc = p->data; - liPluginCoreListenMask *mask; UNUSED(srv); - if (NULL == (value = core_parse_check_parameter_string(value, "allow_listen_ip", err))) return FALSE; - - mask = g_slice_new0(liPluginCoreListenMask); - if (li_parse_ipv4(value->data.string->str, &mask->value.ipv4.addr, &mask->value.ipv4.networkmask, &mask->value.ipv4.port)) { - mask->type = LI_PLUGIN_CORE_LISTEN_MASK_IPV4; - } else if (li_parse_ipv6(value->data.string->str, mask->value.ipv6.addr, &mask->value.ipv6.network, &mask->value.ipv6.port)) { - mask->type = LI_PLUGIN_CORE_LISTEN_MASK_IPV6; - } else { - ERROR(srv, "couldn't parse ip/network:port in allow_listen_ip mask '%s'", value->data.string->str); - g_slice_free(liPluginCoreListenMask, mask); - return FALSE; + value = li_value_get_single_argument(value); + if (LI_VALUE_LIST != li_value_type(value)) { + li_value_wrap_in_list(value); } - g_ptr_array_add(pc->parsing.listen_masks, mask); - return TRUE; -} + LI_VALUE_FOREACH(entry, value) + GString *s; + liPluginCoreListenMask *mask; -static gboolean core_parse_allow_listen_unix(liServer *srv, liPlugin *p, liValue *value, GError **err) { - liPluginCoreConfig *pc = p->data; - liPluginCoreListenMask *mask; - UNUSED(srv); + if (LI_VALUE_STRING != li_value_type(entry)) goto parameter_type_error; + s = entry->data.string; - if (NULL == (value = core_parse_check_parameter_string(value, "allow_listen_unix", err))) return FALSE; + mask = g_slice_new0(liPluginCoreListenMask); + if (li_string_prefix(s, CONST_STR_LEN("unix:/"))) { + mask->type = LI_PLUGIN_CORE_LISTEN_MASK_UNIX; + mask->value.unix_socket.path = li_value_extract_string(entry); + g_string_erase(mask->value.unix_socket.path, 0, 5); /* remove "unix:" prefix */ + } + else if (li_parse_ipv4(s->str, &mask->value.ipv4.addr, &mask->value.ipv4.networkmask, &mask->value.ipv4.port)) { + mask->type = LI_PLUGIN_CORE_LISTEN_MASK_IPV4; + } + else if (li_parse_ipv6(s->str, mask->value.ipv6.addr, &mask->value.ipv6.network, &mask->value.ipv6.port)) { + mask->type = LI_PLUGIN_CORE_LISTEN_MASK_IPV6; + } + else { + g_set_error(err, LI_ANGEL_CONFIG_PARSER_ERROR, LI_ANGEL_CONFIG_PARSER_ERROR_PARSE, + "allow_listen: couldn't parse socket address mask '%s'", s->str); + g_slice_free(liPluginCoreListenMask, mask); + return FALSE; + } - mask = g_slice_new0(liPluginCoreListenMask); - mask->type = LI_PLUGIN_CORE_LISTEN_MASK_UNIX; - mask->value.unix_socket.path = li_value_extract_string(value); + g_ptr_array_add(pc->parsing.listen_masks, mask); + LI_VALUE_END_FOREACH() - g_ptr_array_add(pc->parsing.listen_masks, mask); return TRUE; + +parameter_type_error: + g_set_error(err, LI_ANGEL_CONFIG_PARSER_ERROR, LI_ANGEL_CONFIG_PARSER_ERROR_PARSE, + "allow_listen: expecting string list as parameter"); + return FALSE; } @@ -355,8 +364,7 @@ static const liPluginItem core_items[] = { { "copy_env", core_parse_copy_env }, { "max_core_file_size", core_parse_max_core_file_size }, { "max_open_files", core_parse_max_open_files }, - { "allow_listen_ip", core_parse_allow_listen_ip }, - { "allow_listen_unix", core_parse_allow_listen_unix }, + { "allow_listen", core_parse_allow_listen }, { NULL, NULL } }; @@ -425,7 +433,7 @@ static gboolean core_check(liServer *srv, liPlugin *p, GError **err) { UNUSED(err); cmd = pc->parsing.wrapper; - pc->parsing.wrapper = NULL; + pc->parsing.wrapper = g_ptr_array_new(); if (NULL != pc->parsing.binary) { g_ptr_array_add(cmd, g_string_free(pc->parsing.binary, FALSE)); @@ -457,7 +465,7 @@ static gboolean core_check(liServer *srv, liPlugin *p, GError **err) { g_ptr_array_add(pc->parsing.env, NULL); cmdarr = (gchar**) g_ptr_array_free(cmd, FALSE); envarr = (gchar**) g_ptr_array_free(pc->parsing.env, FALSE); - pc->parsing.env = NULL; + pc->parsing.env = g_ptr_array_new(); user = pc->parsing.user; pc->parsing.user = NULL; diff --git a/tests/base.py b/tests/base.py index 5ce592c..c373bda 100644 --- a/tests/base.py +++ b/tests/base.py @@ -446,12 +446,10 @@ if request.is_handled {{ if Env.valgrind_leak != "": suppressions = ', "--suppressions=' + Env.valgrind_leak + '"' valgrindconfig = """ - env [ "G_SLICE=always-malloc", "G_DEBUG=gc-friendly,fatal-criticals,resident-modules" ]; wrapper [ "{valgrind}", "--leak-check=full", "--show-reachable=yes", "--leak-resolution=high" {suppressions} ]; """.format(valgrind = Env.valgrind, suppressions = suppressions) elif Env.valgrind: valgrindconfig = """ - env [ "G_SLICE=always-malloc", "G_DEBUG=gc-friendly,fatal-criticals,resident-modules" ]; wrapper [ "{valgrind}" ]; """.format(valgrind = Env.valgrind) @@ -460,11 +458,11 @@ binary "{Env.worker}"; config "{Env.lighttpdconf}"; modules_path "{Env.plugindir}"; copy_env [ "PATH" ]; +env [ "G_SLICE=always-malloc", "G_DEBUG=gc-friendly,fatal-criticals,resident-modules" ]; {valgrindconfig} -allow_listen_ip "127.0.0.2:{Env.port}"; -allow_listen_ip "127.0.0.2:{gnutlsport}"; -allow_listen_ip "127.0.0.2:{opensslport}"; +allow_listen "127.0.0.2:{Env.port}"; +allow_listen ["127.0.0.2:{gnutlsport}", "127.0.0.2:{opensslport}"]; """.format(Env = Env, gnutlsport = Env.port+1, opensslport = Env.port + 2, valgrindconfig = valgrindconfig)) print >> Env.log, "[Done] Preparing tests"