Tor  0.4.7.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 
26 #include "feature/hs/hs_common.h"
27 #include "feature/hs/hs_config.h"
28 #include "feature/hs/hs_client.h"
29 #include "feature/hs/hs_ob.h"
30 #include "feature/hs/hs_service.h"
31 #include "lib/encoding/confline.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 
46 static 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*/
55 static config_mgr_t *hs_opts_mgr = NULL;
56 
57 /**
58  * Return a configuration manager for the hs_opts_t configuration type.
59  **/
60 static 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  **/
73 static 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. */
98 static 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. */
112 static 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. */
158 static bool
159 check_value_oob(int i, const char *name, int low, int high)
160 {
161  if (i < low || i > high) {
162  log_warn(LD_CONFIG, "%s must be between %d and %d, not %d.",
163  name, low, high, i);
164  return true;
165  }
166  return false;
167 }
168 
169 /**
170  * Helper: check whether the integer value called <b>name</b> in <b>opts</b>
171  * is out-of-bounds.
172  **/
173 #define CHECK_OOB(opts, name, low, high) \
174  check_value_oob((opts)->name, #name, (low), (high))
175 
176 /** Helper function: Given a configuration option and its value, parse the
177  * value as a hs_circuit_id_protocol_t. On success, ok is set to 1 and ret is
178  * the parse value. On error, ok is set to 0 and the "none"
179  * hs_circuit_id_protocol_t is returned. This function logs on error. */
181 helper_parse_circuit_id_protocol(const char *key, const char *value, int *ok)
182 {
183  tor_assert(value);
184  tor_assert(ok);
185 
187  *ok = 0;
188 
189  if (! strcasecmp(value, "haproxy")) {
190  *ok = 1;
192  } else if (! strcasecmp(value, "none")) {
193  *ok = 1;
195  } else {
196  log_warn(LD_CONFIG, "%s must be 'haproxy' or 'none'.", key);
197  goto err;
198  }
199 
200  err:
201  return ret;
202 }
203 
204 /** Return the service version by trying to learn it from the key on disk if
205  * any. If nothing is found, the current service configured version is
206  * returned. */
207 static int
209 {
210  int version;
211 
212  tor_assert(service);
213 
214  version = hs_service_get_version_from_key(service);
215  if (version < 0) {
216  version = service->config.version;
217  }
218 
219  return version;
220 }
221 
222 /**
223  * Header key indicating the start of a new hidden service configuration
224  * block.
225  **/
226 static const char SECTION_HEADER[] = "HiddenServiceDir";
227 
228 /** Return true iff the given options starting at line_ for a hidden service
229  * contains at least one invalid option. Each hidden service option don't
230  * apply to all versions so this function can find out. The line_ MUST start
231  * right after the HiddenServiceDir line of this service.
232  *
233  * This is mainly for usability so we can inform the user of any invalid
234  * option for the hidden service version instead of silently ignoring. */
235 static int
237  const hs_service_t *service)
238 {
239  int ret = 0;
240  const char **optlist;
241  const config_line_t *line;
242 
243  tor_assert(service);
245 
246  /* List of options that a v3 service doesn't support thus must exclude from
247  * its configuration. */
248  const char *opts_exclude_v3[] = {
249  "HiddenServiceAuthorizeClient",
250  NULL /* End marker. */
251  };
252 
253  /* Defining the size explicitly allows us to take advantage of the compiler
254  * which warns us if we ever bump the max version but forget to grow this
255  * array. The plus one is because we have a version 0 :). */
256  struct {
257  const char **list;
258  } exclude_lists[HS_VERSION_MAX + 1] = {
259  { NULL }, /* v0. */
260  { NULL }, /* v1. */
261  { NULL }, /* v2. */
262  { opts_exclude_v3 }, /* v3. */
263  };
264 
265  optlist = exclude_lists[service->config.version].list;
266  if (optlist == NULL) {
267  /* No exclude options to look at for this version. */
268  goto end;
269  }
270  for (int i = 0; optlist[i]; i++) {
271  const char *opt = optlist[i];
272  for (line = line_; line; line = line->next) {
273  if (!strcasecmp(line->key, SECTION_HEADER)) {
274  /* We just hit the next hidden service, stop right now.
275  * (This shouldn't be possible, now that we have partitioned the list
276  * into sections.) */
278  goto end;
279  }
280  if (!strcasecmp(line->key, opt)) {
281  log_warn(LD_CONFIG, "Hidden service option %s is incompatible with "
282  "version %" PRIu32 " of service in %s",
283  opt, service->config.version,
284  service->config.directory_path);
285  ret = 1;
286  /* Continue the loop so we can find all possible options. */
287  continue;
288  }
289  }
290  }
291  end:
292  return ret;
293 }
294 
295 /** Validate service configuration. This is used when loading the configuration
296  * and once we've setup a service object, it's config object is passed to this
297  * function for further validation. This does not validate service key
298  * material. Return 0 if valid else -1 if invalid. */
299 static int
301 {
302  tor_assert(config);
303 
304  /* Amount of ports validation. */
305  if (!config->ports || smartlist_len(config->ports) == 0) {
306  log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured.",
307  escaped(config->directory_path));
308  goto invalid;
309  }
310 
311  /* DoS validation values. */
312  if (config->has_dos_defense_enabled &&
313  (config->intro_dos_burst_per_sec < config->intro_dos_rate_per_sec)) {
314  log_warn(LD_CONFIG, "Hidden service DoS defenses burst (%" PRIu32 ") can "
315  "not be smaller than the rate value (%" PRIu32 ").",
316  config->intro_dos_burst_per_sec, config->intro_dos_rate_per_sec);
317  goto invalid;
318  }
319 
320  /* Valid. */
321  return 0;
322  invalid:
323  return -1;
324 }
325 
326 /** Configuration function for a version 3 service. The given service
327  * object must be already allocated and passed through
328  * config_generic_service() prior to calling this function.
329  *
330  * Return 0 on success else a negative value. */
331 static int
333  hs_service_config_t *config)
334 {
335  tor_assert(config);
336  tor_assert(hs_opts);
337 
338  /* Number of introduction points. */
339  if (CHECK_OOB(hs_opts, HiddenServiceNumIntroductionPoints,
341  HS_CONFIG_V3_MAX_INTRO_POINTS)) {
342  goto err;
343  }
344  config->num_intro_points = hs_opts->HiddenServiceNumIntroductionPoints;
345 
346  /* Circuit ID export setting. */
347  if (hs_opts->HiddenServiceExportCircuitID) {
348  int ok;
349  config->circuit_id_protocol =
350  helper_parse_circuit_id_protocol("HiddenServcieExportCircuitID",
351  hs_opts->HiddenServiceExportCircuitID,
352  &ok);
353  if (!ok) {
354  goto err;
355  }
356  }
357 
358  /* Is the DoS defense enabled? */
359  config->has_dos_defense_enabled =
360  hs_opts->HiddenServiceEnableIntroDoSDefense;
361 
362  /* Rate for DoS defense */
363  if (CHECK_OOB(hs_opts, HiddenServiceEnableIntroDoSRatePerSec,
364  HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MIN,
365  HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MAX)) {
366  goto err;
367  }
368  config->intro_dos_rate_per_sec =
369  hs_opts->HiddenServiceEnableIntroDoSRatePerSec;
370  log_info(LD_REND, "Service INTRO2 DoS defenses rate set to: %" PRIu32,
371  config->intro_dos_rate_per_sec);
372 
373  if (CHECK_OOB(hs_opts, HiddenServiceEnableIntroDoSBurstPerSec,
374  HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MIN,
375  HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MAX)) {
376  goto err;
377  }
378  config->intro_dos_burst_per_sec =
379  hs_opts->HiddenServiceEnableIntroDoSBurstPerSec;
380  log_info(LD_REND, "Service INTRO2 DoS defenses burst set to: %" PRIu32,
381  config->intro_dos_burst_per_sec);
382 
383  /* Is this an onionbalance instance? */
384  if (hs_opts->HiddenServiceOnionBalanceInstance) {
385  /* Option is enabled, parse config file. */
386  if (! hs_ob_parse_config_file(config)) {
387  goto err;
388  }
389  }
390 
391  /* We do not load the key material for the service at this stage. This is
392  * done later once tor can confirm that it is in a running state. */
393 
394  /* We are about to return a fully configured service so do one last pass of
395  * validation at it. */
396  if (config_validate_service(config) < 0) {
397  goto err;
398  }
399 
400  return 0;
401  err:
402  return -1;
403 }
404 
405 /** Configure a service using the given options in hs_opts and options. This is
406  * called for any service regardless of its version which means that all
407  * directives in this function are generic to any service version. This
408  * function will also check the validity of the service directory path.
409  *
410  * The line_ must be pointing to the directive directly after a
411  * HiddenServiceDir. That way, when hitting the next HiddenServiceDir line or
412  * reaching the end of the list of lines, we know that we have to stop looking
413  * for more options.
414  *
415  * Return 0 on success else -1. */
416 static int
418  const or_options_t *options,
419  hs_service_t *service)
420 {
421  hs_service_config_t *config;
422 
423  tor_assert(hs_opts);
424  tor_assert(options);
425  tor_assert(service);
426 
427  /* Makes thing easier. */
428  config = &service->config;
429 
430  /* Directory where the service's keys are stored. */
431  tor_assert(hs_opts->HiddenServiceDir);
432  config->directory_path = tor_strdup(hs_opts->HiddenServiceDir);
433  log_info(LD_CONFIG, "%s=%s. Configuring...",
435 
436  /* Protocol version for the service. */
437  if (hs_opts->HiddenServiceVersion == -1) {
438  /* No value was set; stay with the default. */
439  } else if (hs_opts->HiddenServiceVersion == 2) {
440  log_warn(LD_CONFIG, "Onion services version 2 are obsolete. Please see "
441  "https://blog.torproject.org/v2-deprecation-timeline "
442  "for more details and for instructions on how to "
443  "transition to version 3.");
444  goto err;
445  } else if (CHECK_OOB(hs_opts, HiddenServiceVersion,
447  goto err;
448  } else {
449  config->hs_version_explicitly_set = 1;
450  config->version = hs_opts->HiddenServiceVersion;
451  }
452 
453  /* Virtual port. */
454  for (const config_line_t *portline = hs_opts->HiddenServicePort;
455  portline; portline = portline->next) {
456  char *err_msg = NULL;
457  /* XXX: Can we rename this? */
458  hs_port_config_t *portcfg =
459  hs_parse_port_config(portline->value, " ", &err_msg);
460  if (!portcfg) {
461  if (err_msg) {
462  log_warn(LD_CONFIG, "%s", err_msg);
463  }
464  tor_free(err_msg);
465  goto err;
466  }
467  tor_assert(!err_msg);
468  smartlist_add(config->ports, portcfg);
469  log_info(LD_CONFIG, "HiddenServicePort=%s for %s",
470  portline->value, escaped(config->directory_path));
471  }
472 
473  /* Do we allow unknown ports? */
474  config->allow_unknown_ports = hs_opts->HiddenServiceAllowUnknownPorts;
475 
476  /* Directory group readable. */
477  config->dir_group_readable = hs_opts->HiddenServiceDirGroupReadable;
478 
479  /* Maximum streams per circuit. */
480  if (CHECK_OOB(hs_opts, HiddenServiceMaxStreams,
481  0, HS_CONFIG_MAX_STREAMS_PER_RDV_CIRCUIT)) {
482  goto err;
483  }
484  config->max_streams_per_rdv_circuit = hs_opts->HiddenServiceMaxStreams;
485 
486  /* Maximum amount of streams before we close the circuit. */
487  config->max_streams_close_circuit =
488  hs_opts->HiddenServiceMaxStreamsCloseCircuit;
489 
490  /* Check if we are configured in non anonymous mode meaning every service
491  * becomes a single onion service. */
492  if (hs_service_non_anonymous_mode_enabled(options)) {
493  config->is_single_onion = 1;
494  }
495 
496  /* Success */
497  return 0;
498  err:
499  return -1;
500 }
501 
502 /** Configure a service using the given line and options. This function will
503  * call the corresponding configuration function for a specific service
504  * version and validate the service against the other ones. On success, add
505  * the service to the given list and return 0. On error, nothing is added to
506  * the list and a negative value is returned. */
507 static int
509  smartlist_t *service_list)
510 {
511  int ret;
512  hs_service_t *service = NULL;
513  hs_opts_t *hs_opts = NULL;
514  char *msg = NULL;
515 
516  tor_assert(line);
517  tor_assert(options);
518  tor_assert(service_list);
519 
520  /* We have a new hidden service. */
521  service = hs_service_new(options);
522 
523  /* Try to validate and parse the configuration lines into 'hs_opts' */
524  hs_opts = hs_opts_new();
525  ret = config_assign(get_hs_opts_mgr(), hs_opts, line, 0, &msg);
526  if (ret < 0) {
527  log_warn(LD_REND, "Can't parse configuration for onion service: %s", msg);
528  goto err;
529  }
530  tor_assert_nonfatal(msg == NULL);
532  hs_opts, &msg);
533  if (vs < 0) {
534  log_warn(LD_REND, "Bad configuration for onion service: %s", msg);
535  goto err;
536  }
537  tor_assert_nonfatal(msg == NULL);
538 
539  /* We'll configure that service as a generic one and then pass it to a
540  * specific function according to the configured version number. */
541  if (config_generic_service(hs_opts, options, service) < 0) {
542  goto err;
543  }
544 
546 
547  /* Check permission on service directory that was just parsed. And this must
548  * be done regardless of the service version. Do not ask for the directory
549  * to be created, this is done when the keys are loaded because we could be
550  * in validation mode right now. */
551  if (hs_check_service_private_dir(options->User,
552  service->config.directory_path,
553  service->config.dir_group_readable,
554  0) < 0) {
555  goto err;
556  }
557 
558  /* We'll try to learn the service version here by loading the key(s) if
559  * present and we did not set HiddenServiceVersion. Depending on the key
560  * format, we can figure out the service version. */
561  if (!service->config.hs_version_explicitly_set) {
562  service->config.version = config_learn_service_version(service);
563  }
564 
565  /* We make sure that this set of options for a service are valid. */
566  if (config_has_invalid_options(line->next, service)) {
567  goto err;
568  }
569 
570  /* Different functions are in charge of specific options for a version. We
571  * start just after the service directory line so once we hit another
572  * directory line, the function knows that it has to stop parsing. */
573  switch (service->config.version) {
574  case HS_VERSION_THREE:
575  ret = config_service_v3(hs_opts, &service->config);
576  break;
577  default:
578  /* We do validate before if we support the parsed version. */
580  goto err;
581  }
582  if (ret < 0) {
583  goto err;
584  }
585 
586  /* We'll check if this service can be kept depending on the others
587  * configured previously. */
588  if (service_is_duplicate_in_list(service_list, service)) {
589  goto err;
590  }
591 
592  /* Passes, add it to the given list. */
593  smartlist_add(service_list, service);
594  hs_opts_free(hs_opts);
595 
596  return 0;
597 
598  err:
599  hs_service_free(service);
600  hs_opts_free(hs_opts);
601  tor_free(msg);
602  return -1;
603 }
604 
605 /** From a set of <b>options</b>, setup every hidden service found. Return 0 on
606  * success or -1 on failure. If <b>validate_only</b> is set, parse, warn and
607  * return as normal, but don't actually change the configured services. */
608 int
609 hs_config_service_all(const or_options_t *options, int validate_only)
610 {
611  int ret = -1;
612  config_line_t *remaining = NULL;
613  smartlist_t *new_service_list = NULL;
614 
615  tor_assert(options);
616 
617  /* Newly configured service are put in that list which is then used for
618  * validation and staging for >= v3. */
619  new_service_list = smartlist_new();
620 
621  /* We need to start with a HiddenServiceDir line */
622  if (options->RendConfigLines &&
623  strcasecmp(options->RendConfigLines->key, SECTION_HEADER)) {
624  log_warn(LD_CONFIG, "%s with no preceding %s directive",
625  options->RendConfigLines->key, SECTION_HEADER);
626  goto err;
627  }
628 
629  remaining = config_lines_dup(options->RendConfigLines);
630  while (remaining) {
631  config_line_t *section = remaining;
632  remaining = config_lines_partition(section, SECTION_HEADER);
633 
634  /* Try to configure this service now. On success, it will be added to the
635  * list and validated against the service in that same list. */
636  int rv = config_service(section, options, new_service_list);
637  config_free_lines(section);
638  if (rv < 0) {
639  goto err;
640  }
641  }
642 
643  /* In non validation mode, we'll stage those services we just successfully
644  * configured. Service ownership is transferred from the list to the global
645  * state. If any service is invalid, it will be removed from the list and
646  * freed. All versions are handled in that function. */
647  if (!validate_only) {
648  stage_services(new_service_list);
649  } else {
650  /* We've just validated that we were able to build a clean working list of
651  * services. We don't need those objects anymore. */
652  SMARTLIST_FOREACH(new_service_list, hs_service_t *, s,
653  hs_service_free(s));
654  }
655 
656  /* Success. Note that the service list has no ownership of its content. */
657  ret = 0;
658  goto end;
659 
660  err:
661  SMARTLIST_FOREACH(new_service_list, hs_service_t *, s, hs_service_free(s));
662 
663  end:
664  smartlist_free(new_service_list);
665  /* Tor main should call the free all function on error. */
666  return ret;
667 }
668 
669 /** From a set of <b>options</b>, setup every client authorization found.
670  * Return 0 on success or -1 on failure. If <b>validate_only</b> is set,
671  * parse, warn and return as normal, but don't actually change the
672  * configured state. */
673 int
674 hs_config_client_auth_all(const or_options_t *options, int validate_only)
675 {
676  int ret = -1;
677 
678  /* Configure v3 authorization. */
679  if (hs_config_client_authorization(options, validate_only) < 0) {
680  goto done;
681  }
682 
683  /* Success. */
684  ret = 0;
685  done:
686  return ret;
687 }
688 
689 /**
690  * Free all resources held by the hs_config.c module.
691  **/
692 void
694 {
695  config_mgr_free(hs_opts_mgr);
696 }
Macros for generating a configuration struct from a list of its individual fields.
const char * name
Definition: config.c:2434
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
void * config_new(const config_mgr_t *mgr)
Definition: confmgt.c:387
config_mgr_t * config_mgr_new(const config_format_t *toplevel_fmt)
Definition: confmgt.c:145
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
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:2276
Header file containing client data for the HS subsystem.
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
hs_port_config_t * hs_parse_port_config(const char *string, const char *sep, char **err_msg_out)
Definition: hs_common.c:685
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
int hs_config_client_auth_all(const or_options_t *options, int validate_only)
Definition: hs_config.c:674
static int config_service_v3(const hs_opts_t *hs_opts, hs_service_config_t *config)
Definition: hs_config.c:332
static int config_generic_service(const hs_opts_t *hs_opts, const or_options_t *options, hs_service_t *service)
Definition: hs_config.c:417
void hs_config_free_all(void)
Definition: hs_config.c:693
#define CHECK_OOB(opts, name, low, high)
Definition: hs_config.c:173
int hs_config_service_all(const or_options_t *options, int validate_only)
Definition: hs_config.c:609
static int config_learn_service_version(hs_service_t *service)
Definition: hs_config.c:208
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:181
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:226
static const config_mgr_t * get_hs_opts_mgr(void)
Definition: hs_config.c:61
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:508
static hs_opts_t * hs_opts_new(void)
Definition: hs_config.c:74
#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:236
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:300
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:4249
hs_service_t * hs_service_new(const or_options_t *options)
Definition: hs_service.c:4294
int hs_service_get_version_from_key(const hs_service_t *service)
Definition: hs_service.c:4151
Header file containing service data for the HS subsystem.
hs_circuit_id_protocol_t
Definition: hs_service.h:194
@ HS_CIRCUIT_ID_PROTOCOL_NONE
Definition: hs_service.h:196
@ HS_CIRCUIT_ID_PROTOCOL_HAPROXY
Definition: hs_service.h:199
#define hs_service_free(s)
Definition: hs_service.h:343
#define LD_REND
Definition: log.h:84
#define LD_CONFIG
Definition: log.h:68
#define tor_free(p)
Definition: malloc.h:52
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:253
uint64_t max_streams_per_rdv_circuit
Definition: hs_service.h:223
unsigned int is_single_onion
Definition: hs_service.h:243
smartlist_t * ports
Definition: hs_service.h:214
unsigned int dir_group_readable
Definition: hs_service.h:247
unsigned int hs_version_explicitly_set
Definition: hs_service.h:211
unsigned int max_streams_close_circuit
Definition: hs_service.h:227
unsigned int is_ephemeral
Definition: hs_service.h:250
unsigned int has_dos_defense_enabled
Definition: hs_service.h:256
unsigned int num_intro_points
Definition: hs_service.h:231
unsigned int allow_unknown_ports
Definition: hs_service.h:239
hs_service_config_t config
Definition: hs_service.h:313
struct config_line_t * RendConfigLines
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:176
#define tor_assert(expr)
Definition: util_bug.h:102