commit cfaf1bca989f1841acb5360a482e4e5da3ede7dd Author: Nick Mathewson nickm@torproject.org Date: Tue Jan 21 10:23:27 2020 -0500
Start using confmgt logic to parse HS configuration.
This patch doesn't actually use the results of the parsed object to create the service configuration: subsequent patches will do that. This patch just introduces the necessary configuration tables and starts using them to validate the configuration.
As of this writing, this patch breaks tests. I'll likely fix that in a rebase later on: the current error messages for failures to parse options are a regression, so I've opened #33640 for that. --- src/feature/hs/.may_include | 1 + src/feature/hs/hs_config.c | 87 ++++++++++++++++++++++++++++++++++++++++++- src/feature/hs/hs_config.h | 3 +- src/feature/hs/hs_options.inc | 35 +++++++++++++++++ src/feature/hs/hs_opts_st.h | 30 +++++++++++++++ src/feature/hs/hs_service.c | 1 + src/feature/hs/include.am | 2 + 7 files changed, 157 insertions(+), 2 deletions(-)
diff --git a/src/feature/hs/.may_include b/src/feature/hs/.may_include index 424c745c1..11c5ffbb1 100644 --- a/src/feature/hs/.may_include +++ b/src/feature/hs/.may_include @@ -1 +1,2 @@ *.h +*.inc diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c index f38e3655d..0f2cbbd58 100644 --- a/src/feature/hs/hs_config.c +++ b/src/feature/hs/hs_config.c @@ -31,8 +31,63 @@ #include "feature/rend/rendclient.h" #include "feature/rend/rendservice.h" #include "lib/encoding/confline.h" +#include "lib/conf/confdecl.h" +#include "lib/confmgt/confmgt.h" + +#include "feature/hs/hs_opts_st.h" #include "app/config/or_options_st.h"
+/* Declare the table mapping hs options to hs_opts_t */ +#define CONF_CONTEXT TABLE +#include "feature/hs/hs_options.inc" +#undef CONF_CONTEXT + +/** Magic number for hs_opts_t. */ +#define HS_OPTS_MAGIC 0x6f6e796e + +static const config_format_t hs_opts_fmt = { + .size = sizeof(hs_opts_t), + .magic = { "hs_opts_t", + HS_OPTS_MAGIC, + offsetof(hs_opts_t, magic) }, + .vars = hs_opts_t_vars, +}; + +/** Global configuration manager to handle HS sections*/ +static config_mgr_t *hs_opts_mgr = NULL; + +/** + * Return a configuration manager for the hs_opts_t configuration type. + **/ +static const config_mgr_t * +get_hs_opts_mgr(void) +{ + if (PREDICT_UNLIKELY(hs_opts_mgr == NULL)) { + hs_opts_mgr = config_mgr_new(&hs_opts_fmt); + config_mgr_freeze(hs_opts_mgr); + } + return hs_opts_mgr; +} + +/** + * Allocate, initialize, and return a new hs_opts_t. + **/ +static hs_opts_t * +hs_opts_new(void) +{ + const config_mgr_t *mgr = get_hs_opts_mgr(); + hs_opts_t *r = config_new(mgr); + tor_assert(r); + config_init(mgr, r); + return r; +} + +/** + * Free an hs_opts_t. + **/ +#define hs_opts_free(opts) \ + config_free(get_hs_opts_mgr(), (opts)) + /** Using the given list of services, stage them into our global state. Every * service version are handled. This function can remove entries in the given * service_list. @@ -607,11 +662,13 @@ config_generic_service(const config_line_t *line, * the service to the given list and return 0. On error, nothing is added to * the list and a negative value is returned. */ static int -config_service(const config_line_t *line, const or_options_t *options, +config_service(config_line_t *line, const or_options_t *options, smartlist_t *service_list) { int ret; hs_service_t *service = NULL; + hs_opts_t *hs_opts = NULL; + char *msg = NULL;
tor_assert(line); tor_assert(options); @@ -620,6 +677,22 @@ config_service(const config_line_t *line, const or_options_t *options, /* We have a new hidden service. */ service = hs_service_new(options);
+ /* Try to validate and parse the configuration lines into 'hs_opts' */ + hs_opts = hs_opts_new(); + ret = config_assign(get_hs_opts_mgr(), hs_opts, line, 0, &msg); + if (ret < 0) { + log_warn(LD_REND, "Can't parse configuration for onion service: %s", msg); + goto err; + } + tor_assert_nonfatal(msg == NULL); + validation_status_t vs = config_validate(get_hs_opts_mgr(), NULL, + hs_opts, &msg); + if (vs < 0) { + log_warn(LD_REND, "Bad configuration for onion service: %s", msg); + goto err; + } + tor_assert_nonfatal(msg == NULL); + /* We'll configure that service as a generic one and then pass it to a * specific function according to the configured version number. */ if (config_generic_service(line, options, service) < 0) { @@ -679,11 +752,14 @@ config_service(const config_line_t *line, const or_options_t *options,
/* Passes, add it to the given list. */ smartlist_add(service_list, service); + hs_opts_free(hs_opts);
return 0;
err: hs_service_free(service); + hs_opts_free(hs_opts); + tor_free(msg); return -1; }
@@ -780,3 +856,12 @@ hs_config_client_auth_all(const or_options_t *options, int validate_only) done: return ret; } + +/** + * Free all resources held by the hs_config.c module. + **/ +void +hs_config_free_all(void) +{ + config_mgr_free(hs_opts_mgr); +} diff --git a/src/feature/hs/hs_config.h b/src/feature/hs/hs_config.h index 5694cf1e9..c60b4fbb5 100644 --- a/src/feature/hs/hs_config.h +++ b/src/feature/hs/hs_config.h @@ -30,5 +30,6 @@ int hs_config_service_all(const or_options_t *options, int validate_only); int hs_config_client_auth_all(const or_options_t *options, int validate_only);
-#endif /* !defined(TOR_HS_CONFIG_H) */ +void hs_config_free_all(void);
+#endif /* !defined(TOR_HS_CONFIG_H) */ diff --git a/src/feature/hs/hs_options.inc b/src/feature/hs/hs_options.inc new file mode 100644 index 000000000..c3566f446 --- /dev/null +++ b/src/feature/hs/hs_options.inc @@ -0,0 +1,35 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file dirauth_options.inc + * @brief Declare configuration options for a single hidden service. + * + * Note that this options file behaves differently from most, since it + * is not used directly by the options manager. Instead, it is applied to + * a group of hidden service options starting with a HiddenServiceDir and + * extending up to the next HiddenServiceDir. + **/ + +/** Holds configuration for a single hidden service. */ +BEGIN_CONF_STRUCT(hs_opts_t) + +CONF_VAR(HiddenServiceDir, FILENAME, 0, NULL) +CONF_VAR(HiddenServiceDirGroupReadable, BOOL, 0, "0") +CONF_VAR(HiddenServicePort, STRING, 0, NULL) +CONF_VAR(HiddenServiceVersion, POSINT, 0, "3") +CONF_VAR(HiddenServiceAuthorizeClient, STRING, 0, NULL) +CONF_VAR(HiddenServiceAllowUnknownPorts, BOOL, 0, "0") +CONF_VAR(HiddenServiceMaxStreams, POSINT, 0, "0") +CONF_VAR(HiddenServiceMaxStreamsCloseCircuit, BOOL, 0, "0") +CONF_VAR(HiddenServiceNumIntroductionPoints, POSINT, 0, "3") +CONF_VAR(HiddenServiceExportCircuitID, STRING, 0, NULL) +CONF_VAR(HiddenServiceEnableIntroDoSDefense, BOOL, 0, "0") +CONF_VAR(HiddenServiceEnableIntroDoSRatePerSec, POSINT, 0, "25") +CONF_VAR(HiddenServiceEnableIntroDoSBurstPerSec, POSINT, 0, "200") +CONF_VAR(HiddenServiceOnionBalanceInstance, BOOL, 0, "0") + +END_CONF_STRUCT(hs_opts_t) diff --git a/src/feature/hs/hs_opts_st.h b/src/feature/hs/hs_opts_st.h new file mode 100644 index 000000000..f6ee0f3cf --- /dev/null +++ b/src/feature/hs/hs_opts_st.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file dirauth_options_st.h + * @brief Structure hs_opts_t to hold options for a single hidden service. + **/ + +#ifndef TOR_FEATURE_HS_HS_OPTS_ST_H +#define TOR_FEATURE_HS_HS_OPTS_ST_H + +#include "lib/conf/confdecl.h" +#define CONF_CONTEXT STRUCT +#include "feature/hs/hs_options.inc" +#undef CONF_CONTEXT + +/** + * An hs_opts_t holds the parsed options for a single HS configuration + * section. + * + * This name ends with 'opts' instead of 'options' to signal that it is not + * handled directly by the or_options_t configuration manager, but that + * first we partition the "HiddenService*" options by section. + **/ +typedef struct hs_opts_t hs_opts_t; + +#endif diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c index 8b51b770a..8c30b56b0 100644 --- a/src/feature/hs/hs_service.c +++ b/src/feature/hs/hs_service.c @@ -4112,6 +4112,7 @@ hs_service_free_all(void) { rend_service_free_all(); service_free_all(); + hs_config_free_all(); }
#ifdef TOR_UNIT_TESTS diff --git a/src/feature/hs/include.am b/src/feature/hs/include.am index f83907c76..af1dc6558 100644 --- a/src/feature/hs/include.am +++ b/src/feature/hs/include.am @@ -32,6 +32,8 @@ noinst_HEADERS += \ src/feature/hs/hs_ident.h \ src/feature/hs/hs_intropoint.h \ src/feature/hs/hs_ob.h \ + src/feature/hs/hs_opts_st.h \ + src/feature/hs/hs_options.inc \ src/feature/hs/hs_service.h \ src/feature/hs/hs_stats.h \ src/feature/hs/hsdir_index_st.h
tor-commits@lists.torproject.org