mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
hs-v3: Add the Onion Balance config file option
At this commit, the service reads the config file and parse it to finally set the service config object with the options. Part of #32709 Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
f1498e75dd
commit
ef28afa255
@ -510,6 +510,8 @@ static const config_var_t option_vars_[] = {
|
||||
LINELIST_S, RendConfigLines, NULL),
|
||||
VAR("HiddenServiceEnableIntroDoSBurstPerSec",
|
||||
LINELIST_S, RendConfigLines, NULL),
|
||||
VAR("HiddenServiceOnionBalanceInstance",
|
||||
LINELIST_S, RendConfigLines, NULL),
|
||||
VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"),
|
||||
V(HidServAuth, LINELIST, NULL),
|
||||
V(ClientOnionAuthDir, FILENAME, NULL),
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "feature/hs/hs_common.h"
|
||||
#include "feature/hs/hs_config.h"
|
||||
#include "feature/hs/hs_client.h"
|
||||
#include "feature/hs/hs_ob.h"
|
||||
#include "feature/hs/hs_service.h"
|
||||
#include "feature/rend/rendclient.h"
|
||||
#include "feature/rend/rendservice.h"
|
||||
@ -219,6 +220,7 @@ config_has_invalid_options(const config_line_t *line_,
|
||||
"HiddenServiceEnableIntroDoSDefense",
|
||||
"HiddenServiceEnableIntroDoSRatePerSec",
|
||||
"HiddenServiceEnableIntroDoSBurstPerSec",
|
||||
"HiddenServiceOnionBalanceInstance",
|
||||
NULL /* End marker. */
|
||||
};
|
||||
|
||||
@ -317,7 +319,7 @@ config_service_v3(const config_line_t *line_,
|
||||
int have_num_ip = 0;
|
||||
bool export_circuit_id = false; /* just to detect duplicate options */
|
||||
bool dos_enabled = false, dos_rate_per_sec = false;
|
||||
bool dos_burst_per_sec = false;
|
||||
bool dos_burst_per_sec = false, ob_instance = false;
|
||||
const char *dup_opt_seen = NULL;
|
||||
const config_line_t *line;
|
||||
|
||||
@ -402,6 +404,27 @@ config_service_v3(const config_line_t *line_,
|
||||
config->intro_dos_burst_per_sec);
|
||||
continue;
|
||||
}
|
||||
if (!strcasecmp(line->key, "HiddenServiceOnionBalanceInstance")) {
|
||||
bool enabled = !!helper_parse_uint64(line->key, line->value,
|
||||
0, 1, &ok);
|
||||
if (!ok || ob_instance) {
|
||||
if (ob_instance) {
|
||||
dup_opt_seen = line->key;
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
ob_instance = true;
|
||||
if (!enabled) {
|
||||
/* Skip if this is disabled. */
|
||||
continue;
|
||||
}
|
||||
/* Option is enabled, parse config file. */
|
||||
ok = hs_ob_parse_config_file(config);
|
||||
if (!ok) {
|
||||
goto err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* We do not load the key material for the service at this stage. This is
|
||||
|
222
src/feature/hs/hs_ob.c
Normal file
222
src/feature/hs/hs_ob.c
Normal file
@ -0,0 +1,222 @@
|
||||
/* Copyright (c) 2017-2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file hs_ob.c
|
||||
* \brief Implement Onion Balance specific code.
|
||||
*
|
||||
* \details
|
||||
*
|
||||
* XXX:
|
||||
**/
|
||||
|
||||
#define HS_OB_PRIVATE
|
||||
|
||||
#include "lib/confmgt/confmgt.h"
|
||||
#include "lib/encoding/confline.h"
|
||||
|
||||
#include "hs_ob.h"
|
||||
|
||||
/* Options config magic number. */
|
||||
#define OB_OPTIONS_MAGIC 0x631DE7EA
|
||||
|
||||
/* Helper macros. */
|
||||
#define VAR(varname, conftype, member, initvalue) \
|
||||
CONFIG_VAR_ETYPE(ob_options_t, varname, conftype, member, 0, initvalue)
|
||||
#define V(member,conftype,initvalue) \
|
||||
VAR(#member, conftype, member, initvalue)
|
||||
|
||||
/* Dummy instance of ob_options_t, used for type-checking its members with
|
||||
* CONF_CHECK_VAR_TYPE. */
|
||||
DUMMY_TYPECHECK_INSTANCE(ob_options_t);
|
||||
|
||||
/* Array of variables for the config file options. */
|
||||
static const config_var_t config_vars[] = {
|
||||
V(MasterOnionAddress, LINELIST, NULL),
|
||||
|
||||
END_OF_CONFIG_VARS
|
||||
};
|
||||
|
||||
/* "Extra" variable in the state that receives lines we can't parse. This
|
||||
* lets us preserve options from versions of Tor newer than us. */
|
||||
static const struct_member_t config_extra_vars = {
|
||||
.name = "__extra",
|
||||
.type = CONFIG_TYPE_LINELIST,
|
||||
.offset = offsetof(ob_options_t, ExtraLines),
|
||||
};
|
||||
|
||||
/* Configuration format of ob_options_t. */
|
||||
static const config_format_t config_format = {
|
||||
.size = sizeof(ob_options_t),
|
||||
.magic = {
|
||||
"ob_options_t",
|
||||
OB_OPTIONS_MAGIC,
|
||||
offsetof(ob_options_t, magic_),
|
||||
},
|
||||
.vars = config_vars,
|
||||
.extra = &config_extra_vars,
|
||||
};
|
||||
|
||||
/* Global configuration manager for the config file. */
|
||||
static config_mgr_t *config_options_mgr = NULL;
|
||||
|
||||
/* Return the configuration manager for the config file. */
|
||||
static const config_mgr_t *
|
||||
get_config_options_mgr(void)
|
||||
{
|
||||
if (PREDICT_UNLIKELY(config_options_mgr == NULL)) {
|
||||
config_options_mgr = config_mgr_new(&config_format);
|
||||
config_mgr_freeze(config_options_mgr);
|
||||
}
|
||||
return config_options_mgr;
|
||||
}
|
||||
|
||||
#define ob_option_free(val) \
|
||||
FREE_AND_NULL(ob_options_t, ob_option_free_, (val))
|
||||
|
||||
/** Helper: Free a config options object. */
|
||||
static void
|
||||
ob_option_free_(ob_options_t *opts)
|
||||
{
|
||||
if (opts == NULL) {
|
||||
return;
|
||||
}
|
||||
config_free(get_config_options_mgr(), opts);
|
||||
}
|
||||
|
||||
/** Return an allocated config options object. */
|
||||
static ob_options_t *
|
||||
ob_option_new(void)
|
||||
{
|
||||
ob_options_t *opts = config_new(get_config_options_mgr());
|
||||
config_init(get_config_options_mgr(), opts);
|
||||
return opts;
|
||||
}
|
||||
|
||||
/** Helper function: From the configuration line value which is an onion
|
||||
* address with the ".onion" extension, find the public key and put it in
|
||||
* pkey_out.
|
||||
*
|
||||
* On success, true is returned. Else, false and pkey is untouched. */
|
||||
static bool
|
||||
get_onion_public_key(const char *value, ed25519_public_key_t *pkey_out)
|
||||
{
|
||||
char address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
|
||||
|
||||
tor_assert(value);
|
||||
tor_assert(pkey_out);
|
||||
|
||||
if (strcmpend(value, ".onion")) {
|
||||
/* Not a .onion extension, bad format. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Length validation. The -1 is because sizeof() counts the NUL byte. */
|
||||
if (strlen(value) >
|
||||
(HS_SERVICE_ADDR_LEN_BASE32 + sizeof(".onion") - 1)) {
|
||||
/* Too long, bad format. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We don't want the .onion so we add 2 because size - 1 is copied with
|
||||
* strlcpy() in order to accomodate the NUL byte and sizeof() counts the NUL
|
||||
* byte so we need to remove them from the equation. */
|
||||
strlcpy(address, value, strlen(value) - sizeof(".onion") + 2);
|
||||
|
||||
if (hs_parse_address_no_log(address, pkey_out, NULL, NULL, NULL) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Success. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Parse the given ob options in opts and set the service config object
|
||||
* accordingly.
|
||||
*
|
||||
* Return 1 on success else 0. */
|
||||
static int
|
||||
ob_option_parse(hs_service_config_t *config, const ob_options_t *opts)
|
||||
{
|
||||
int ret = 0;
|
||||
config_line_t *line;
|
||||
|
||||
tor_assert(config);
|
||||
tor_assert(opts);
|
||||
|
||||
for (line = opts->MasterOnionAddress; line; line = line->next) {
|
||||
/* Allocate config list if need be. */
|
||||
if (!config->ob_master_pubkeys) {
|
||||
config->ob_master_pubkeys = smartlist_new();
|
||||
}
|
||||
ed25519_public_key_t *pubkey = tor_malloc_zero(sizeof(*pubkey));
|
||||
|
||||
if (!get_onion_public_key(line->value, pubkey)) {
|
||||
log_warn(LD_REND, "OnionBalance: MasterOnionAddress %s is invalid",
|
||||
line->value);
|
||||
tor_free(pubkey);
|
||||
goto end;
|
||||
}
|
||||
smartlist_add(config->ob_master_pubkeys, pubkey);
|
||||
}
|
||||
/* Success. */
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
/* No keys added, we free the list since no list means no onion balance
|
||||
* support for this tor instance. */
|
||||
if (smartlist_len(config->ob_master_pubkeys) == 0) {
|
||||
smartlist_free(config->ob_master_pubkeys);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Read and parse the config file at fname on disk. The service config object
|
||||
* is populated with the options if any.
|
||||
*
|
||||
* Return 1 on success else 0. This is to follow the "ok" convention in
|
||||
* hs_config.c. */
|
||||
int
|
||||
hs_ob_parse_config_file(hs_service_config_t *config)
|
||||
{
|
||||
static const char *fname = "ob_config";
|
||||
int ret = 0;
|
||||
char *content = NULL, *errmsg = NULL, *config_file_path = NULL;
|
||||
ob_options_t *options = NULL;
|
||||
config_line_t *lines = NULL;
|
||||
|
||||
tor_assert(config);
|
||||
|
||||
/* Read file from disk. */
|
||||
config_file_path = hs_path_from_filename(config->directory_path, fname);
|
||||
content = read_file_to_str(config_file_path, 0, NULL);
|
||||
if (!content) {
|
||||
log_warn(LD_FS, "OnionBalance: Unable to read config file %s",
|
||||
escaped(config_file_path));
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Parse lines. */
|
||||
if (config_get_lines(content, &lines, 0) < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
options = ob_option_new();
|
||||
config_assign(get_config_options_mgr(), options, lines, 0, &errmsg);
|
||||
if (errmsg) {
|
||||
log_warn(LD_REND, "OnionBalance: Unable to parse config file: %s",
|
||||
errmsg);
|
||||
tor_free(errmsg);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Parse the options and set the service config object with the details. */
|
||||
ret = ob_option_parse(config, options);
|
||||
|
||||
end:
|
||||
config_free_lines(lines);
|
||||
ob_option_free(options);
|
||||
tor_free(content);
|
||||
tor_free(config_file_path);
|
||||
return ret;
|
||||
}
|
29
src/feature/hs/hs_ob.h
Normal file
29
src/feature/hs/hs_ob.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* Copyright (c) 2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file hs_ob.h
|
||||
* \brief Header file for the specific code for onion balance.
|
||||
**/
|
||||
|
||||
#ifndef TOR_HS_OB_H
|
||||
#define TOR_HS_OB_H
|
||||
|
||||
#include "hs_service.h"
|
||||
|
||||
int hs_ob_parse_config_file(hs_service_config_t *config);
|
||||
|
||||
#ifdef HS_OB_PRIVATE
|
||||
|
||||
typedef struct ob_options_t {
|
||||
/** Magic number to identify the structure in memory. */
|
||||
uint32_t magic_;
|
||||
/** Master Onion Address(es). */
|
||||
struct config_line_t *MasterOnionAddress;
|
||||
/** Extra Lines for configuration we might not know. */
|
||||
struct config_line_t *ExtraLines;
|
||||
} ob_options_t;
|
||||
|
||||
#endif /* defined(HS_OB_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_HS_OB_H) */
|
@ -267,6 +267,11 @@ service_clear_config(hs_service_config_t *config)
|
||||
service_authorized_client_free(p));
|
||||
smartlist_free(config->clients);
|
||||
}
|
||||
if (config->ob_master_pubkeys) {
|
||||
SMARTLIST_FOREACH(config->ob_master_pubkeys, ed25519_public_key_t *, k,
|
||||
tor_free(k));
|
||||
smartlist_free(config->ob_master_pubkeys);
|
||||
}
|
||||
memset(config, 0, sizeof(*config));
|
||||
}
|
||||
|
||||
|
@ -248,10 +248,14 @@ typedef struct hs_service_config_t {
|
||||
/** Does this service export the circuit ID of its clients? */
|
||||
hs_circuit_id_protocol_t circuit_id_protocol;
|
||||
|
||||
/* DoS defenses. For the ESTABLISH_INTRO cell extension. */
|
||||
/** DoS defenses. For the ESTABLISH_INTRO cell extension. */
|
||||
unsigned int has_dos_defense_enabled : 1;
|
||||
uint32_t intro_dos_rate_per_sec;
|
||||
uint32_t intro_dos_burst_per_sec;
|
||||
|
||||
/** If set, contains the Onion Balance master ed25519 public key (taken from
|
||||
* an .onion addresses) that this tor instance serves as backend. */
|
||||
smartlist_t *ob_master_pubkeys;
|
||||
} hs_service_config_t;
|
||||
|
||||
/** Service state. */
|
||||
|
@ -13,6 +13,7 @@ LIBTOR_APP_A_SOURCES += \
|
||||
src/feature/hs/hs_dos.c \
|
||||
src/feature/hs/hs_ident.c \
|
||||
src/feature/hs/hs_intropoint.c \
|
||||
src/feature/hs/hs_ob.c \
|
||||
src/feature/hs/hs_service.c \
|
||||
src/feature/hs/hs_stats.c
|
||||
|
||||
@ -30,6 +31,7 @@ noinst_HEADERS += \
|
||||
src/feature/hs/hs_dos.h \
|
||||
src/feature/hs/hs_ident.h \
|
||||
src/feature/hs/hs_intropoint.h \
|
||||
src/feature/hs/hs_ob.h \
|
||||
src/feature/hs/hs_service.h \
|
||||
src/feature/hs/hs_stats.h \
|
||||
src/feature/hs/hsdir_index_st.h
|
||||
|
Loading…
Reference in New Issue
Block a user