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.
This commit is contained in:
Nick Mathewson 2020-01-21 10:23:27 -05:00 committed by David Goulet
parent 43b578e099
commit cfaf1bca98
7 changed files with 157 additions and 2 deletions

View File

@ -1 +1,2 @@
*.h
*.inc

View File

@ -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);
}

View File

@ -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) */

View File

@ -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)

View File

@ -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

View File

@ -4112,6 +4112,7 @@ hs_service_free_all(void)
{
rend_service_free_all();
service_free_all();
hs_config_free_all();
}
#ifdef TOR_UNIT_TESTS

View File

@ -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