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