Tor 0.4.9.0-alpha-dev
hs_config.c
Go to the documentation of this file.
1/* Copyright (c) 2017-2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file hs_config.c
6 * \brief Implement hidden service configuration subsystem.
7 *
8 * \details
9 *
10 * This file has basically one main entry point: hs_config_service_all(). It
11 * takes the torrc options and configure hidden service from it. In validate
12 * mode, nothing is added to the global service list or keys are not generated
13 * nor loaded.
14 *
15 * A service is configured in two steps. It is first created using the tor
16 * options and then put in a staging list. It will stay there until
17 * hs_service_load_all_keys() is called. That function is responsible to
18 * load/generate the keys for the service in the staging list and if
19 * successful, transferred the service to the main global service list where
20 * at that point it is ready to be used.
21 *
22 * Configuration functions are per-version and there is a main generic one for
23 * every option that is common to all version (config_generic_service).
24 **/
25
29#include "feature/hs/hs_ob.h"
32#include "lib/conf/confdecl.h"
33#include "lib/confmgt/confmgt.h"
34
35#include "feature/hs/hs_opts_st.h"
37
38/* Declare the table mapping hs options to hs_opts_t */
39#define CONF_CONTEXT TABLE
40#include "feature/hs/hs_options.inc"
41#undef CONF_CONTEXT
42
43/** Magic number for hs_opts_t. */
44#define HS_OPTS_MAGIC 0x6f6e796e
45
46static const config_format_t hs_opts_fmt = {
47 .size = sizeof(hs_opts_t),
48 .magic = { "hs_opts_t",
50 offsetof(hs_opts_t, magic) },
51 .vars = hs_opts_t_vars,
52};
53
54/** Global configuration manager to handle HS sections*/
56
57/**
58 * Return a configuration manager for the hs_opts_t configuration type.
59 **/
60static const config_mgr_t *
62{
63 if (PREDICT_UNLIKELY(hs_opts_mgr == NULL)) {
64 hs_opts_mgr = config_mgr_new(&hs_opts_fmt);
66 }
67 return hs_opts_mgr;
68}
69
70/**
71 * Allocate, initialize, and return a new hs_opts_t.
72 **/
73static hs_opts_t *
75{
76 const config_mgr_t *mgr = get_hs_opts_mgr();
77 hs_opts_t *r = config_new(mgr);
78 tor_assert(r);
79 config_init(mgr, r);
80 return r;
81}
82
83/**
84 * Free an hs_opts_t.
85 **/
86#define hs_opts_free(opts) \
87 config_free(get_hs_opts_mgr(), (opts))
88
89/** Using the given list of services, stage them into our global state. Every
90 * service version are handled. This function can remove entries in the given
91 * service_list.
92 *
93 * Staging a service means that we take all services in service_list and we
94 * put them in the staging list (global) which acts as a temporary list that
95 * is used by the service loading key process. In other words, staging a
96 * service puts it in a list to be considered when loading the keys and then
97 * moved to the main global list. */
98static void
100{
101 tor_assert(service_list);
102
103 /* This is >= v3 specific. Using the newly configured service list, stage
104 * them into our global state. Every object ownership is lost after. */
105 hs_service_stage_services(service_list);
106}
107
108/** Validate the given service against all service in the given list. If the
109 * service is ephemeral, this function ignores it. Services with the same
110 * directory path aren't allowed and will return an error. If a duplicate is
111 * found, 1 is returned else 0 if none found. */
112static int
114 const hs_service_t *service)
115{
116 int ret = 0;
117
118 tor_assert(service_list);
119 tor_assert(service);
120
121 /* Ephemeral service don't have a directory configured so no need to check
122 * for a service in the list having the same path. */
123 if (service->config.is_ephemeral) {
124 goto end;
125 }
126
127 /* XXX: Validate if we have any service that has the given service dir path.
128 * This has two problems:
129 *
130 * a) It's O(n^2)
131 *
132 * b) We only compare directory paths as strings, so we can't
133 * detect two distinct paths that specify the same directory
134 * (which can arise from symlinks, case-insensitivity, bind
135 * mounts, etc.).
136 *
137 * It also can't detect that two separate Tor instances are trying
138 * to use the same HiddenServiceDir; for that, we would need a
139 * lock file. But this is enough to detect a simple mistake that
140 * at least one person has actually made. */
141 SMARTLIST_FOREACH_BEGIN(service_list, const hs_service_t *, s) {
142 if (!strcmp(s->config.directory_path, service->config.directory_path)) {
143 log_warn(LD_REND, "Another hidden service is already configured "
144 "for directory %s",
145 escaped(service->config.directory_path));
146 ret = 1;
147 goto end;
148 }
149 } SMARTLIST_FOREACH_END(s);
150
151 end:
152 return ret;
153}
154
155/** Check whether an integer <b>i</b> is out of bounds (not between <b>low</b>
156 * and <b>high</b> incusive). If it is, then log a warning about the option
157 * <b>name</b>, and return true. Otherwise return false. */
158static bool
159check_value_oob(int i, const char *name, int low, int high)
160{
161 if (i < low || i > high) {
162 if (low == high) {
163 log_warn(LD_CONFIG, "%s must be %d, not %d.", name, low, i);
164 } else {
165 log_warn(LD_CONFIG, "%s must be between %d and %d, not %d.",
166 name, low, high, i);
167 }
168 return true;
169 }
170 return false;
171}
172
173/**
174 * Helper: check whether the integer value called <b>name</b> in <b>opts</b>
175 * is out-of-bounds.
176 **/
177#define CHECK_OOB(opts, name, low, high) \
178 check_value_oob((opts)->name, #name, (low), (high))
179
180/** Helper function: Given a configuration option and its value, parse the
181 * value as a hs_circuit_id_protocol_t. On success, ok is set to 1 and ret is
182 * the parse value. On error, ok is set to 0 and the "none"
183 * hs_circuit_id_protocol_t is returned. This function logs on error. */
185helper_parse_circuit_id_protocol(const char *key, const char *value, int *ok)
186{
187 tor_assert(value);
188 tor_assert(ok);
189
191 *ok = 0;
192
193 if (! strcasecmp(value, "haproxy")) {
194 *ok = 1;
196 } else if (! strcasecmp(value, "none")) {
197 *ok = 1;
199 } else {
200 log_warn(LD_CONFIG, "%s must be 'haproxy' or 'none'.", key);
201 goto err;
202 }
203
204 err:
205 return ret;
206}
207
208/** Return the service version by trying to learn it from the key on disk if
209 * any. If nothing is found, the current service configured version is
210 * returned. */
211static int
213{
214 int version;
215
216 tor_assert(service);
217
218 version = hs_service_get_version_from_key(service);
219 if (version < 0) {
220 version = service->config.version;
221 }
222
223 return version;
224}
225
226/**
227 * Header key indicating the start of a new hidden service configuration
228 * block.
229 **/
230static const char SECTION_HEADER[] = "HiddenServiceDir";
231
232/** Return true iff the given options starting at line_ for a hidden service
233 * contains at least one invalid option. Each hidden service option don't
234 * apply to all versions so this function can find out. The line_ MUST start
235 * right after the HiddenServiceDir line of this service.
236 *
237 * This is mainly for usability so we can inform the user of any invalid
238 * option for the hidden service version instead of silently ignoring. */
239static int
241 const hs_service_t *service)
242{
243 int ret = 0;
244 const char **optlist;
245 const config_line_t *line;
246
247 tor_assert(service);
249
250 /* List of options that a v3 service doesn't support thus must exclude from
251 * its configuration. */
252 const char *opts_exclude_v3[] = {
253 "HiddenServiceAuthorizeClient",
254 NULL /* End marker. */
255 };
256
257 /* Defining the size explicitly allows us to take advantage of the compiler
258 * which warns us if we ever bump the max version but forget to grow this
259 * array. The plus one is because we have a version 0 :). */
260 struct {
261 const char **list;
262 } exclude_lists[HS_VERSION_MAX + 1] = {
263 { NULL }, /* v0. */
264 { NULL }, /* v1. */
265 { NULL }, /* v2. */
266 { opts_exclude_v3 }, /* v3. */
267 };
268
269 optlist = exclude_lists[service->config.version].list;
270 if (optlist == NULL) {
271 /* No exclude options to look at for this version. */
272 goto end;
273 }
274 for (int i = 0; optlist[i]; i++) {
275 const char *opt = optlist[i];
276 for (line = line_; line; line = line->next) {
277 if (!strcasecmp(line->key, SECTION_HEADER)) {
278 /* We just hit the next hidden service, stop right now.
279 * (This shouldn't be possible, now that we have partitioned the list
280 * into sections.) */
282 goto end;
283 }
284 if (!strcasecmp(line->key, opt)) {
285 log_warn(LD_CONFIG, "Hidden service option %s is incompatible with "
286 "version %" PRIu32 " of service in %s",
287 opt, service->config.version,
288 service->config.directory_path);
289 ret = 1;
290 /* Continue the loop so we can find all possible options. */
291 continue;
292 }
293 }
294 }
295 end:
296 return ret;
297}
298
299/** Validate service configuration. This is used when loading the configuration
300 * and once we've setup a service object, it's config object is passed to this
301 * function for further validation. This does not validate service key
302 * material. Return 0 if valid else -1 if invalid. */
303static int
305{
306 tor_assert(config);
307
308 /* Amount of ports validation. */
309 if (!config->ports || smartlist_len(config->ports) == 0) {
310 log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured.",
311 escaped(config->directory_path));
312 goto invalid;
313 }
314
315 /* DoS validation values. */
316 if (config->has_dos_defense_enabled &&
317 (config->intro_dos_burst_per_sec < config->intro_dos_rate_per_sec)) {
318 log_warn(LD_CONFIG, "Hidden service DoS defenses burst (%" PRIu32 ") can "
319 "not be smaller than the rate value (%" PRIu32 ").",
320 config->intro_dos_burst_per_sec, config->intro_dos_rate_per_sec);
321 goto invalid;
322 }
323 if (config->has_pow_defenses_enabled &&
324 (config->pow_queue_burst < config->pow_queue_rate)) {
325 log_warn(LD_CONFIG, "Hidden service PoW queue burst (%" PRIu32 ") can "
326 "not be smaller than the rate value (%" PRIu32 ").",
327 config->pow_queue_burst, config->pow_queue_rate);
328 goto invalid;
329 }
330 if (config->has_pow_defenses_enabled && !have_module_pow()) {
331 log_warn(LD_CONFIG, "Hidden service proof-of-work defenses are enabled "
332 "in our configuration but this build of tor does not "
333 "include the required 'pow' module.");
334 goto invalid;
335 }
336
337 /* Valid. */
338 return 0;
339 invalid:
340 return -1;
341}
342
343/** Configuration function for a version 3 service. The given service
344 * object must be already allocated and passed through
345 * config_generic_service() prior to calling this function.
346 *
347 * Return 0 on success else a negative value. */
348static int
350 hs_service_config_t *config)
351{
352 tor_assert(config);
353 tor_assert(hs_opts);
354
355 /* Number of introduction points. */
356 if (CHECK_OOB(hs_opts, HiddenServiceNumIntroductionPoints,
358 HS_CONFIG_V3_MAX_INTRO_POINTS)) {
359 goto err;
360 }
361 config->num_intro_points = hs_opts->HiddenServiceNumIntroductionPoints;
362
363 /* Circuit ID export setting. */
364 if (hs_opts->HiddenServiceExportCircuitID) {
365 int ok;
366 config->circuit_id_protocol =
367 helper_parse_circuit_id_protocol("HiddenServiceExportCircuitID",
368 hs_opts->HiddenServiceExportCircuitID,
369 &ok);
370 if (!ok) {
371 goto err;
372 }
373 }
374
375 /* Is the DoS defense enabled? */
377 hs_opts->HiddenServiceEnableIntroDoSDefense;
378
379 /* Rate for DoS defense */
380 if (CHECK_OOB(hs_opts, HiddenServiceEnableIntroDoSRatePerSec,
381 HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MIN,
382 HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MAX)) {
383 goto err;
384 }
385 config->intro_dos_rate_per_sec =
386 hs_opts->HiddenServiceEnableIntroDoSRatePerSec;
387 log_info(LD_REND, "Service INTRO2 DoS defenses rate set to: %" PRIu32,
388 config->intro_dos_rate_per_sec);
389
390 if (CHECK_OOB(hs_opts, HiddenServiceEnableIntroDoSBurstPerSec,
391 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MIN,
392 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MAX)) {
393 goto err;
394 }
395 config->intro_dos_burst_per_sec =
396 hs_opts->HiddenServiceEnableIntroDoSBurstPerSec;
397 log_info(LD_REND, "Service INTRO2 DoS defenses burst set to: %" PRIu32,
398 config->intro_dos_burst_per_sec);
399
400 /* Is this an onionbalance instance? */
401 if (hs_opts->HiddenServiceOnionBalanceInstance) {
402 /* Option is enabled, parse config file. */
403 if (! hs_ob_parse_config_file(config)) {
404 goto err;
405 }
406 }
407
408 /* Are the PoW anti-DoS defenses enabled? */
409 config->has_pow_defenses_enabled = hs_opts->HiddenServicePoWDefensesEnabled;
410 config->pow_queue_rate = hs_opts->HiddenServicePoWQueueRate;
411 config->pow_queue_burst = hs_opts->HiddenServicePoWQueueBurst;
412
413 log_info(LD_REND, "Service PoW defenses are %s",
414 config->has_pow_defenses_enabled ? "enabled" : "disabled");
415 if (config->has_pow_defenses_enabled) {
416 log_info(LD_REND, "Service PoW queue rate set to: %" PRIu32,
417 config->pow_queue_rate);
418 log_info(LD_REND, "Service PoW queue burst set to: %" PRIu32,
419 config->pow_queue_burst);
420 }
421
422 /* We do not load the key material for the service at this stage. This is
423 * done later once tor can confirm that it is in a running state. */
424
425 /* We are about to return a fully configured service so do one last pass of
426 * validation at it. */
427 if (config_validate_service(config) < 0) {
428 goto err;
429 }
430
431 return 0;
432 err:
433 return -1;
434}
435
436/** Configure a service using the given options in hs_opts and options. This is
437 * called for any service regardless of its version which means that all
438 * directives in this function are generic to any service version. This
439 * function will also check the validity of the service directory path.
440 *
441 * The line_ must be pointing to the directive directly after a
442 * HiddenServiceDir. That way, when hitting the next HiddenServiceDir line or
443 * reaching the end of the list of lines, we know that we have to stop looking
444 * for more options.
445 *
446 * Return 0 on success else -1. */
447static int
449 const or_options_t *options,
450 hs_service_t *service)
451{
452 hs_service_config_t *config;
453
454 tor_assert(hs_opts);
455 tor_assert(options);
456 tor_assert(service);
457
458 /* Makes thing easier. */
459 config = &service->config;
460
461 /* Directory where the service's keys are stored. */
462 tor_assert(hs_opts->HiddenServiceDir);
463 config->directory_path = tor_strdup(hs_opts->HiddenServiceDir);
464 log_info(LD_CONFIG, "%s=%s. Configuring...",
466
467 /* Protocol version for the service. */
468 if (hs_opts->HiddenServiceVersion == -1) {
469 /* No value was set; stay with the default. */
470 } else if (hs_opts->HiddenServiceVersion == 2) {
471 log_warn(LD_CONFIG, "Onion services version 2 are obsolete. Please see "
472 "https://blog.torproject.org/v2-deprecation-timeline "
473 "for more details and for instructions on how to "
474 "transition to version 3.");
475 goto err;
476 } else if (CHECK_OOB(hs_opts, HiddenServiceVersion,
478 goto err;
479 } else {
480 config->hs_version_explicitly_set = 1;
481 config->version = hs_opts->HiddenServiceVersion;
482 }
483
484 /* Virtual port. */
485 for (const config_line_t *portline = hs_opts->HiddenServicePort;
486 portline; portline = portline->next) {
487 char *err_msg = NULL;
488 /* XXX: Can we rename this? */
489 hs_port_config_t *portcfg =
490 hs_parse_port_config(portline->value, " ", &err_msg);
491 if (!portcfg) {
492 if (err_msg) {
493 log_warn(LD_CONFIG, "%s", err_msg);
494 }
495 tor_free(err_msg);
496 goto err;
497 }
498 tor_assert(!err_msg);
499 smartlist_add(config->ports, portcfg);
500 log_info(LD_CONFIG, "HiddenServicePort=%s for %s",
501 portline->value, escaped(config->directory_path));
502 }
503
504 /* Do we allow unknown ports? */
505 config->allow_unknown_ports = hs_opts->HiddenServiceAllowUnknownPorts;
506
507 /* Directory group readable. */
508 config->dir_group_readable = hs_opts->HiddenServiceDirGroupReadable;
509
510 /* Maximum streams per circuit. */
511 if (CHECK_OOB(hs_opts, HiddenServiceMaxStreams,
512 0, HS_CONFIG_MAX_STREAMS_PER_RDV_CIRCUIT)) {
513 goto err;
514 }
515 config->max_streams_per_rdv_circuit = hs_opts->HiddenServiceMaxStreams;
516
517 /* Maximum amount of streams before we close the circuit. */
519 hs_opts->HiddenServiceMaxStreamsCloseCircuit;
520
521 /* Check if we are configured in non anonymous mode meaning every service
522 * becomes a single onion service. */
523 if (hs_service_non_anonymous_mode_enabled(options)) {
524 config->is_single_onion = 1;
525 }
526
527 /* Success */
528 return 0;
529 err:
530 return -1;
531}
532
533/** Configure a service using the given line and options. This function will
534 * call the corresponding configuration function for a specific service
535 * version and validate the service against the other ones. On success, add
536 * the service to the given list and return 0. On error, nothing is added to
537 * the list and a negative value is returned. */
538static int
540 smartlist_t *service_list)
541{
542 int ret;
543 hs_service_t *service = NULL;
544 hs_opts_t *hs_opts = NULL;
545 char *msg = NULL;
546
547 tor_assert(line);
548 tor_assert(options);
549 tor_assert(service_list);
550
551 /* We have a new hidden service. */
552 service = hs_service_new(options);
553
554 /* Try to validate and parse the configuration lines into 'hs_opts' */
555 hs_opts = hs_opts_new();
556 ret = config_assign(get_hs_opts_mgr(), hs_opts, line, 0, &msg);
557 if (ret < 0) {
558 log_warn(LD_REND, "Can't parse configuration for onion service: %s", msg);
559 goto err;
560 }
561 tor_assert_nonfatal(msg == NULL);
563 hs_opts, &msg);
564 if (vs < 0) {
565 log_warn(LD_REND, "Bad configuration for onion service: %s", msg);
566 goto err;
567 }
568 tor_assert_nonfatal(msg == NULL);
569
570 /* We'll configure that service as a generic one and then pass it to a
571 * specific function according to the configured version number. */
572 if (config_generic_service(hs_opts, options, service) < 0) {
573 goto err;
574 }
575
577
578 /* If we're running with TestingTorNetwork enabled, we relax the permissions
579 * check on the hs directory. */
580 if (!options->TestingTorNetwork) {
581 /* Check permission on service directory that was just parsed. And this
582 * must be done regardless of the service version. Do not ask for the
583 * directory to be created, this is done when the keys are loaded because
584 * we could be in validation mode right now. */
586 service->config.directory_path,
587 service->config.dir_group_readable,
588 0) < 0) {
589 goto err;
590 }
591 }
592
593 /* We'll try to learn the service version here by loading the key(s) if
594 * present and we did not set HiddenServiceVersion. Depending on the key
595 * format, we can figure out the service version. */
596 if (!service->config.hs_version_explicitly_set) {
597 service->config.version = config_learn_service_version(service);
598 }
599
600 /* We make sure that this set of options for a service are valid. */
601 if (config_has_invalid_options(line->next, service)) {
602 goto err;
603 }
604
605 /* Different functions are in charge of specific options for a version. We
606 * start just after the service directory line so once we hit another
607 * directory line, the function knows that it has to stop parsing. */
608 switch (service->config.version) {
609 case HS_VERSION_THREE:
610 ret = config_service_v3(hs_opts, &service->config);
611 break;
612 default:
613 /* We do validate before if we support the parsed version. */
615 goto err;
616 }
617 if (ret < 0) {
618 goto err;
619 }
620
621 /* We'll check if this service can be kept depending on the others
622 * configured previously. */
623 if (service_is_duplicate_in_list(service_list, service)) {
624 goto err;
625 }
626
627 /* Passes, add it to the given list. */
628 smartlist_add(service_list, service);
629 hs_opts_free(hs_opts);
630
631 return 0;
632
633 err:
634 hs_service_free(service);
635 hs_opts_free(hs_opts);
636 tor_free(msg);
637 return -1;
638}
639
640/** From a set of <b>options</b>, setup every hidden service found. Return 0 on
641 * success or -1 on failure. If <b>validate_only</b> is set, parse, warn and
642 * return as normal, but don't actually change the configured services. */
643int
644hs_config_service_all(const or_options_t *options, int validate_only)
645{
646 int ret = -1;
647 config_line_t *remaining = NULL;
648 smartlist_t *new_service_list = NULL;
649
650 tor_assert(options);
651
652 /* Newly configured service are put in that list which is then used for
653 * validation and staging for >= v3. */
654 new_service_list = smartlist_new();
655
656 /* We need to start with a HiddenServiceDir line */
657 if (options->RendConfigLines &&
658 strcasecmp(options->RendConfigLines->key, SECTION_HEADER)) {
659 log_warn(LD_CONFIG, "%s with no preceding %s directive",
660 options->RendConfigLines->key, SECTION_HEADER);
661 goto err;
662 }
663
664 remaining = config_lines_dup(options->RendConfigLines);
665 while (remaining) {
666 config_line_t *section = remaining;
667 remaining = config_lines_partition(section, SECTION_HEADER);
668
669 /* Try to configure this service now. On success, it will be added to the
670 * list and validated against the service in that same list. */
671 int rv = config_service(section, options, new_service_list);
672 config_free_lines(section);
673 if (rv < 0) {
674 config_free_lines(remaining);
675 goto err;
676 }
677 }
678
679 /* In non validation mode, we'll stage those services we just successfully
680 * configured. Service ownership is transferred from the list to the global
681 * state. If any service is invalid, it will be removed from the list and
682 * freed. All versions are handled in that function. */
683 if (!validate_only) {
684 stage_services(new_service_list);
685 } else {
686 /* We've just validated that we were able to build a clean working list of
687 * services. We don't need those objects anymore. */
688 SMARTLIST_FOREACH(new_service_list, hs_service_t *, s,
689 hs_service_free(s));
690 }
691
692 /* Success. Note that the service list has no ownership of its content. */
693 ret = 0;
694 goto end;
695
696 err:
697 SMARTLIST_FOREACH(new_service_list, hs_service_t *, s, hs_service_free(s));
698
699 end:
700 smartlist_free(new_service_list);
701 /* Tor main should call the free all function on error. */
702 return ret;
703}
704
705/** From a set of <b>options</b>, setup every client authorization found.
706 * Return 0 on success or -1 on failure. If <b>validate_only</b> is set,
707 * parse, warn and return as normal, but don't actually change the
708 * configured state. */
709int
710hs_config_client_auth_all(const or_options_t *options, int validate_only)
711{
712 int ret = -1;
713
714 /* Configure v3 authorization. */
715 if (hs_config_client_authorization(options, validate_only) < 0) {
716 goto done;
717 }
718
719 /* Success. */
720 ret = 0;
721 done:
722 return ret;
723}
724
725/**
726 * Free all resources held by the hs_config.c module.
727 **/
728void
730{
731 config_mgr_free(hs_opts_mgr);
732}
Macros for generating a configuration struct from a list of its individual fields.
const char * name
Definition: config.c:2462
config_line_t * config_lines_partition(config_line_t *inp, const char *header)
Definition: confline.c:266
config_line_t * config_lines_dup(const config_line_t *inp)
Definition: confline.c:226
Header for confline.c.
void config_init(const config_mgr_t *mgr, void *options)
Definition: confmgt.c:1158
void config_mgr_freeze(config_mgr_t *mgr)
Definition: confmgt.c:285
validation_status_t config_validate(const config_mgr_t *mgr, const void *old_options, void *options, char **msg_out)
Definition: confmgt.c:1272
int config_assign(const config_mgr_t *mgr, void *options, config_line_t *list, unsigned config_assign_flags, char **msg)
Definition: confmgt.c:937
config_mgr_t * config_mgr_new(const config_format_t *toplevel_fmt)
Definition: confmgt.c:145
void * config_new(const config_mgr_t *mgr)
Definition: confmgt.c:387
Header for confmgt.c.
validation_status_t
Definition: confmgt.h:83
const char * escaped(const char *s)
Definition: escape.c:126
int hs_config_client_authorization(const or_options_t *options, int validate_only)
Definition: hs_client.c:2467
Header file containing client data for the HS subsystem.
hs_port_config_t * hs_parse_port_config(const char *string, const char *sep, char **err_msg_out)
Definition: hs_common.c:685
int hs_check_service_private_dir(const char *username, const char *path, unsigned int dir_group_readable, unsigned int create)
Definition: hs_common.c:200
Header file containing common data for the whole HS subsystem.
#define NUM_INTRO_POINTS_DEFAULT
Definition: hs_common.h:30
#define HS_VERSION_MAX
Definition: hs_common.h:27
#define HS_VERSION_MIN
Definition: hs_common.h:25
#define HS_VERSION_THREE
Definition: hs_common.h:23
static hs_opts_t * hs_opts_new(void)
Definition: hs_config.c:74
int hs_config_client_auth_all(const or_options_t *options, int validate_only)
Definition: hs_config.c:710
static int config_service_v3(const hs_opts_t *hs_opts, hs_service_config_t *config)
Definition: hs_config.c:349
static int config_generic_service(const hs_opts_t *hs_opts, const or_options_t *options, hs_service_t *service)
Definition: hs_config.c:448
void hs_config_free_all(void)
Definition: hs_config.c:729
#define CHECK_OOB(opts, name, low, high)
Definition: hs_config.c:177
static const config_mgr_t * get_hs_opts_mgr(void)
Definition: hs_config.c:61
int hs_config_service_all(const or_options_t *options, int validate_only)
Definition: hs_config.c:644
static int config_learn_service_version(hs_service_t *service)
Definition: hs_config.c:212
static bool check_value_oob(int i, const char *name, int low, int high)
Definition: hs_config.c:159
static hs_circuit_id_protocol_t helper_parse_circuit_id_protocol(const char *key, const char *value, int *ok)
Definition: hs_config.c:185
static void stage_services(smartlist_t *service_list)
Definition: hs_config.c:99
#define hs_opts_free(opts)
Definition: hs_config.c:86
static const char SECTION_HEADER[]
Definition: hs_config.c:230
static config_mgr_t * hs_opts_mgr
Definition: hs_config.c:55
static int config_service(config_line_t *line, const or_options_t *options, smartlist_t *service_list)
Definition: hs_config.c:539
#define HS_OPTS_MAGIC
Definition: hs_config.c:44
static int config_has_invalid_options(const config_line_t *line_, const hs_service_t *service)
Definition: hs_config.c:240
static int service_is_duplicate_in_list(const smartlist_t *service_list, const hs_service_t *service)
Definition: hs_config.c:113
static int config_validate_service(const hs_service_config_t *config)
Definition: hs_config.c:304
Header file containing configuration ABI/API for the HS subsystem.
int hs_ob_parse_config_file(hs_service_config_t *config)
Definition: hs_ob.c:221
Header file for the specific code for onion balance.
void hs_service_stage_services(const smartlist_t *service_list)
Definition: hs_service.c:4560
int hs_service_get_version_from_key(const hs_service_t *service)
Definition: hs_service.c:4462
hs_service_t * hs_service_new(const or_options_t *options)
Definition: hs_service.c:4605
Header file containing service data for the HS subsystem.
hs_circuit_id_protocol_t
Definition: hs_service.h:203
@ HS_CIRCUIT_ID_PROTOCOL_NONE
Definition: hs_service.h:205
@ HS_CIRCUIT_ID_PROTOCOL_HAPROXY
Definition: hs_service.h:208
#define hs_service_free(s)
Definition: hs_service.h:361
#define LD_REND
Definition: log.h:84
#define LD_CONFIG
Definition: log.h:68
#define tor_free(p)
Definition: malloc.h:56
The or_options_t structure, which represents Tor's configuration.
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
hs_circuit_id_protocol_t circuit_id_protocol
Definition: hs_service.h:262
uint64_t max_streams_per_rdv_circuit
Definition: hs_service.h:232
unsigned int is_single_onion
Definition: hs_service.h:252
smartlist_t * ports
Definition: hs_service.h:223
unsigned int dir_group_readable
Definition: hs_service.h:256
unsigned int hs_version_explicitly_set
Definition: hs_service.h:220
unsigned int max_streams_close_circuit
Definition: hs_service.h:236
unsigned int is_ephemeral
Definition: hs_service.h:259
unsigned int has_dos_defense_enabled
Definition: hs_service.h:265
unsigned int num_intro_points
Definition: hs_service.h:240
unsigned int allow_unknown_ports
Definition: hs_service.h:248
unsigned int has_pow_defenses_enabled
Definition: hs_service.h:270
hs_service_config_t config
Definition: hs_service.h:331
struct config_line_t * RendConfigLines
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:177
#define tor_assert(expr)
Definition: util_bug.h:103