1 /* Copyright (c) 2017-2020, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 * \brief Implement hidden service configuration subsystem.
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
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.
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).
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 "feature/rend/rendclient.h"
32 #include "feature/rend/rendservice.h"
33 #include "lib/encoding/confline.h"
34 #include "lib/conf/confdecl.h"
35 #include "lib/confmgt/confmgt.h"
37 #include "feature/hs/hs_opts_st.h"
38 #include "app/config/or_options_st.h"
40 /* Declare the table mapping hs options to hs_opts_t */
41 #define CONF_CONTEXT TABLE
42 #include "feature/hs/hs_options.inc"
45 /** Magic number for hs_opts_t. */
46 #define HS_OPTS_MAGIC 0x6f6e796e
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
,
56 /** Global configuration manager to handle HS sections*/
57 static config_mgr_t
*hs_opts_mgr
= NULL
;
60 * Return a configuration manager for the hs_opts_t configuration type.
62 static const config_mgr_t
*
65 if (PREDICT_UNLIKELY(hs_opts_mgr
== NULL
)) {
66 hs_opts_mgr
= config_mgr_new(&hs_opts_fmt
);
67 config_mgr_freeze(hs_opts_mgr
);
73 * Allocate, initialize, and return a new hs_opts_t.
78 const config_mgr_t
*mgr
= get_hs_opts_mgr();
79 hs_opts_t
*r
= config_new(mgr
);
88 #define hs_opts_free(opts) \
89 config_free(get_hs_opts_mgr(), (opts))
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
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. */
101 stage_services(smartlist_t
*service_list
)
103 tor_assert(service_list
);
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();
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
);
120 } SMARTLIST_FOREACH_END(s
);
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
);
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. */
132 service_is_duplicate_in_list(const smartlist_t
*service_list
,
133 const hs_service_t
*service
)
137 tor_assert(service_list
);
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
) {
146 /* XXX: Validate if we have any service that has the given service dir path.
147 * This has two problems:
149 * a) It's O(n^2), but the same comment from the bottom of
150 * rend_config_services() should apply.
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
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 "
165 escaped(service
->config
.directory_path
));
169 } SMARTLIST_FOREACH_END(s
);
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. */
179 check_value_oob(int i
, const char *name
, int low
, int high
)
181 if (i
< low
|| i
> high
) {
183 log_warn(LD_CONFIG
, "%s must be %d, not %d.", name
, low
, i
);
185 log_warn(LD_CONFIG
, "%s must be between %d and %d, not %d.",
194 * Helper: check whether the integer value called <b>name</b> in <b>opts</b>
197 #define CHECK_OOB(opts, name, low, high) \
198 check_value_oob((opts)->name, #name, (low), (high))
200 /** Helper function: Given a configuration option and its value, parse the
201 * value as a hs_circuit_id_protocol_t. On success, ok is set to 1 and ret is
202 * the parse value. On error, ok is set to 0 and the "none"
203 * hs_circuit_id_protocol_t is returned. This function logs on error. */
204 static hs_circuit_id_protocol_t
205 helper_parse_circuit_id_protocol(const char *key
, const char *value
, int *ok
)
210 hs_circuit_id_protocol_t ret
= HS_CIRCUIT_ID_PROTOCOL_NONE
;
213 if (! strcasecmp(value
, "haproxy")) {
215 ret
= HS_CIRCUIT_ID_PROTOCOL_HAPROXY
;
216 } else if (! strcasecmp(value
, "none")) {
218 ret
= HS_CIRCUIT_ID_PROTOCOL_NONE
;
220 log_warn(LD_CONFIG
, "%s must be 'haproxy' or 'none'.", key
);
228 /** Return the service version by trying to learn it from the key on disk if
229 * any. If nothing is found, the current service configured version is
232 config_learn_service_version(hs_service_t
*service
)
238 version
= hs_service_get_version_from_key(service
);
240 version
= service
->config
.version
;
247 * Header key indicating the start of a new hidden service configuration
250 static const char SECTION_HEADER
[] = "HiddenServiceDir";
252 /** Return true iff the given options starting at line_ for a hidden service
253 * contains at least one invalid option. Each hidden service option don't
254 * apply to all versions so this function can find out. The line_ MUST start
255 * right after the HiddenServiceDir line of this service.
257 * This is mainly for usability so we can inform the user of any invalid
258 * option for the hidden service version instead of silently ignoring. */
260 config_has_invalid_options(const config_line_t
*line_
,
261 const hs_service_t
*service
)
264 const char **optlist
;
265 const config_line_t
*line
;
268 tor_assert(service
->config
.version
<= HS_VERSION_MAX
);
270 /* List of options that a v3 service doesn't support thus must exclude from
271 * its configuration. */
272 const char *opts_exclude_v3
[] = {
273 "HiddenServiceAuthorizeClient",
274 NULL
/* End marker. */
277 const char *opts_exclude_v2
[] = {
278 "HiddenServiceExportCircuitID",
279 "HiddenServiceEnableIntroDoSDefense",
280 "HiddenServiceEnableIntroDoSRatePerSec",
281 "HiddenServiceEnableIntroDoSBurstPerSec",
282 "HiddenServiceOnionBalanceInstance",
283 NULL
/* End marker. */
286 /* Defining the size explicitly allows us to take advantage of the compiler
287 * which warns us if we ever bump the max version but forget to grow this
288 * array. The plus one is because we have a version 0 :). */
291 } exclude_lists
[HS_VERSION_MAX
+ 1] = {
294 { opts_exclude_v2
}, /* v2 */
295 { opts_exclude_v3
}, /* v3. */
298 optlist
= exclude_lists
[service
->config
.version
].list
;
299 if (optlist
== NULL
) {
300 /* No exclude options to look at for this version. */
303 for (int i
= 0; optlist
[i
]; i
++) {
304 const char *opt
= optlist
[i
];
305 for (line
= line_
; line
; line
= line
->next
) {
306 if (!strcasecmp(line
->key
, SECTION_HEADER
)) {
307 /* We just hit the next hidden service, stop right now.
308 * (This shouldn't be possible, now that we have partitioned the list
310 tor_assert_nonfatal_unreached();
313 if (!strcasecmp(line
->key
, opt
)) {
314 log_warn(LD_CONFIG
, "Hidden service option %s is incompatible with "
315 "version %" PRIu32
" of service in %s",
316 opt
, service
->config
.version
,
317 service
->config
.directory_path
);
319 if (!strcasecmp(line
->key
, "HiddenServiceAuthorizeClient")) {
320 /* Special case this v2 option so that we can offer alternatives.
321 * If more such special cases appear, it would be good to
322 * generalize the exception mechanism here. */
323 log_warn(LD_CONFIG
, "For v3 onion service client authorization, "
324 "please read the 'CLIENT AUTHORIZATION' section in the "
329 /* Continue the loop so we can find all possible options. */
338 /** Validate service configuration. This is used when loading the configuration
339 * and once we've setup a service object, it's config object is passed to this
340 * function for further validation. This does not validate service key
341 * material. Return 0 if valid else -1 if invalid. */
343 config_validate_service(const hs_service_config_t
*config
)
347 /* Amount of ports validation. */
348 if (!config
->ports
|| smartlist_len(config
->ports
) == 0) {
349 log_warn(LD_CONFIG
, "Hidden service (%s) with no ports configured.",
350 escaped(config
->directory_path
));
354 /* DoS validation values. */
355 if (config
->has_dos_defense_enabled
&&
356 (config
->intro_dos_burst_per_sec
< config
->intro_dos_rate_per_sec
)) {
357 log_warn(LD_CONFIG
, "Hidden service DoS defenses burst (%" PRIu32
") can "
358 "not be smaller than the rate value (%" PRIu32
").",
359 config
->intro_dos_burst_per_sec
, config
->intro_dos_rate_per_sec
);
369 /** Configuration function for a version 3 service. The given service
370 * object must be already allocated and passed through
371 * config_generic_service() prior to calling this function.
373 * Return 0 on success else a negative value. */
375 config_service_v3(const hs_opts_t
*hs_opts
,
376 hs_service_config_t
*config
)
381 /* Number of introduction points. */
382 if (CHECK_OOB(hs_opts
, HiddenServiceNumIntroductionPoints
,
383 NUM_INTRO_POINTS_DEFAULT
,
384 HS_CONFIG_V3_MAX_INTRO_POINTS
)) {
387 config
->num_intro_points
= hs_opts
->HiddenServiceNumIntroductionPoints
;
389 /* Circuit ID export setting. */
390 if (hs_opts
->HiddenServiceExportCircuitID
) {
392 config
->circuit_id_protocol
=
393 helper_parse_circuit_id_protocol("HiddenServcieExportCircuitID",
394 hs_opts
->HiddenServiceExportCircuitID
,
401 /* Is the DoS defense enabled? */
402 config
->has_dos_defense_enabled
=
403 hs_opts
->HiddenServiceEnableIntroDoSDefense
;
405 /* Rate for DoS defense */
406 if (CHECK_OOB(hs_opts
, HiddenServiceEnableIntroDoSRatePerSec
,
407 HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MIN
,
408 HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MAX
)) {
411 config
->intro_dos_rate_per_sec
=
412 hs_opts
->HiddenServiceEnableIntroDoSRatePerSec
;
413 log_info(LD_REND
, "Service INTRO2 DoS defenses rate set to: %" PRIu32
,
414 config
->intro_dos_rate_per_sec
);
416 if (CHECK_OOB(hs_opts
, HiddenServiceEnableIntroDoSBurstPerSec
,
417 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MIN
,
418 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MAX
)) {
421 config
->intro_dos_burst_per_sec
=
422 hs_opts
->HiddenServiceEnableIntroDoSBurstPerSec
;
423 log_info(LD_REND
, "Service INTRO2 DoS defenses burst set to: %" PRIu32
,
424 config
->intro_dos_burst_per_sec
);
426 /* Is this an onionbalance instance? */
427 if (hs_opts
->HiddenServiceOnionBalanceInstance
) {
428 /* Option is enabled, parse config file. */
429 if (! hs_ob_parse_config_file(config
)) {
434 /* We do not load the key material for the service at this stage. This is
435 * done later once tor can confirm that it is in a running state. */
437 /* We are about to return a fully configured service so do one last pass of
438 * validation at it. */
439 if (config_validate_service(config
) < 0) {
448 /** Configure a service using the given options in hs_opts and options. This is
449 * called for any service regardless of its version which means that all
450 * directives in this function are generic to any service version. This
451 * function will also check the validity of the service directory path.
453 * The line_ must be pointing to the directive directly after a
454 * HiddenServiceDir. That way, when hitting the next HiddenServiceDir line or
455 * reaching the end of the list of lines, we know that we have to stop looking
458 * Return 0 on success else -1. */
460 config_generic_service(const hs_opts_t
*hs_opts
,
461 const or_options_t
*options
,
462 hs_service_t
*service
)
464 hs_service_config_t
*config
;
470 /* Makes thing easier. */
471 config
= &service
->config
;
473 /* Directory where the service's keys are stored. */
474 tor_assert(hs_opts
->HiddenServiceDir
);
475 config
->directory_path
= tor_strdup(hs_opts
->HiddenServiceDir
);
476 log_info(LD_CONFIG
, "%s=%s. Configuring...",
477 SECTION_HEADER
, escaped(config
->directory_path
));
479 /* Protocol version for the service. */
480 if (hs_opts
->HiddenServiceVersion
== -1) {
481 /* No value was set; stay with the default. */
482 } else if (CHECK_OOB(hs_opts
, HiddenServiceVersion
,
483 HS_VERSION_MIN
, HS_VERSION_MAX
)) {
486 config
->hs_version_explicitly_set
= 1;
487 config
->version
= hs_opts
->HiddenServiceVersion
;
491 for (const config_line_t
*portline
= hs_opts
->HiddenServicePort
;
492 portline
; portline
= portline
->next
) {
493 char *err_msg
= NULL
;
494 /* XXX: Can we rename this? */
495 rend_service_port_config_t
*portcfg
=
496 rend_service_parse_port_config(portline
->value
, " ", &err_msg
);
499 log_warn(LD_CONFIG
, "%s", err_msg
);
504 tor_assert(!err_msg
);
505 smartlist_add(config
->ports
, portcfg
);
506 log_info(LD_CONFIG
, "HiddenServicePort=%s for %s",
507 portline
->value
, escaped(config
->directory_path
));
510 /* Do we allow unknown ports? */
511 config
->allow_unknown_ports
= hs_opts
->HiddenServiceAllowUnknownPorts
;
513 /* Directory group readable. */
514 config
->dir_group_readable
= hs_opts
->HiddenServiceDirGroupReadable
;
516 /* Maximum streams per circuit. */
517 if (CHECK_OOB(hs_opts
, HiddenServiceMaxStreams
,
518 0, HS_CONFIG_MAX_STREAMS_PER_RDV_CIRCUIT
)) {
521 config
->max_streams_per_rdv_circuit
= hs_opts
->HiddenServiceMaxStreams
;
523 /* Maximum amount of streams before we close the circuit. */
524 config
->max_streams_close_circuit
=
525 hs_opts
->HiddenServiceMaxStreamsCloseCircuit
;
527 /* Check if we are configured in non anonymous mode meaning every service
528 * becomes a single onion service. */
529 if (rend_service_non_anonymous_mode_enabled(options
)) {
530 config
->is_single_onion
= 1;
539 /** Configure a service using the given line and options. This function will
540 * call the corresponding configuration function for a specific service
541 * version and validate the service against the other ones. On success, add
542 * the service to the given list and return 0. On error, nothing is added to
543 * the list and a negative value is returned. */
545 config_service(config_line_t
*line
, const or_options_t
*options
,
546 smartlist_t
*service_list
)
549 hs_service_t
*service
= NULL
;
550 hs_opts_t
*hs_opts
= NULL
;
555 tor_assert(service_list
);
557 /* We have a new hidden service. */
558 service
= hs_service_new(options
);
560 /* Try to validate and parse the configuration lines into 'hs_opts' */
561 hs_opts
= hs_opts_new();
562 ret
= config_assign(get_hs_opts_mgr(), hs_opts
, line
, 0, &msg
);
564 log_warn(LD_REND
, "Can't parse configuration for onion service: %s", msg
);
567 tor_assert_nonfatal(msg
== NULL
);
568 validation_status_t vs
= config_validate(get_hs_opts_mgr(), NULL
,
571 log_warn(LD_REND
, "Bad configuration for onion service: %s", msg
);
574 tor_assert_nonfatal(msg
== NULL
);
576 /* We'll configure that service as a generic one and then pass it to a
577 * specific function according to the configured version number. */
578 if (config_generic_service(hs_opts
, options
, service
) < 0) {
582 tor_assert(service
->config
.version
<= HS_VERSION_MAX
);
584 /* Check permission on service directory that was just parsed. And this must
585 * be done regardless of the service version. Do not ask for the directory
586 * to be created, this is done when the keys are loaded because we could be
587 * in validation mode right now. */
588 if (hs_check_service_private_dir(options
->User
,
589 service
->config
.directory_path
,
590 service
->config
.dir_group_readable
,
595 /* We'll try to learn the service version here by loading the key(s) if
596 * present and we did not set HiddenServiceVersion. Depending on the key
597 * format, we can figure out the service version. */
598 if (!service
->config
.hs_version_explicitly_set
) {
599 service
->config
.version
= config_learn_service_version(service
);
602 /* We make sure that this set of options for a service are valid that is for
603 * instance an option only for v2 is not used for v3. */
604 if (config_has_invalid_options(line
->next
, service
)) {
608 /* Different functions are in charge of specific options for a version. We
609 * start just after the service directory line so once we hit another
610 * directory line, the function knows that it has to stop parsing. */
611 switch (service
->config
.version
) {
613 ret
= rend_config_service(hs_opts
, options
, &service
->config
);
615 case HS_VERSION_THREE
:
616 ret
= config_service_v3(hs_opts
, &service
->config
);
619 /* We do validate before if we support the parsed version. */
620 tor_assert_nonfatal_unreached();
627 /* We'll check if this service can be kept depending on the others
628 * configured previously. */
629 if (service_is_duplicate_in_list(service_list
, service
)) {
633 /* Passes, add it to the given list. */
634 smartlist_add(service_list
, service
);
635 hs_opts_free(hs_opts
);
640 hs_service_free(service
);
641 hs_opts_free(hs_opts
);
646 /** From a set of <b>options</b>, setup every hidden service found. Return 0 on
647 * success or -1 on failure. If <b>validate_only</b> is set, parse, warn and
648 * return as normal, but don't actually change the configured services. */
650 hs_config_service_all(const or_options_t
*options
, int validate_only
)
653 config_line_t
*remaining
= NULL
;
654 smartlist_t
*new_service_list
= NULL
;
658 /* Newly configured service are put in that list which is then used for
659 * validation and staging for >= v3. */
660 new_service_list
= smartlist_new();
662 /* We need to start with a HiddenServiceDir line */
663 if (options
->RendConfigLines
&&
664 strcasecmp(options
->RendConfigLines
->key
, SECTION_HEADER
)) {
665 log_warn(LD_CONFIG
, "%s with no preceding %s directive",
666 options
->RendConfigLines
->key
, SECTION_HEADER
);
670 remaining
= config_lines_dup(options
->RendConfigLines
);
672 config_line_t
*section
= remaining
;
673 remaining
= config_lines_partition(section
, SECTION_HEADER
);
675 /* Try to configure this service now. On success, it will be added to the
676 * list and validated against the service in that same list. */
677 int rv
= config_service(section
, options
, new_service_list
);
678 config_free_lines(section
);
684 /* In non validation mode, we'll stage those services we just successfully
685 * configured. Service ownership is transferred from the list to the global
686 * state. If any service is invalid, it will be removed from the list and
687 * freed. All versions are handled in that function. */
688 if (!validate_only
) {
689 stage_services(new_service_list
);
691 /* We've just validated that we were able to build a clean working list of
692 * services. We don't need those objects anymore. */
693 SMARTLIST_FOREACH(new_service_list
, hs_service_t
*, s
,
695 /* For the v2 subsystem, the configuration function adds the service
696 * object to the staging list and it is transferred in the main list
697 * through the prunning process. In validation mode, we thus have to purge
698 * the staging list so it's not kept in memory as valid service. */
699 rend_service_free_staging_list();
702 /* Success. Note that the service list has no ownership of its content. */
707 SMARTLIST_FOREACH(new_service_list
, hs_service_t
*, s
, hs_service_free(s
));
710 smartlist_free(new_service_list
);
711 /* Tor main should call the free all function on error. */
715 /** From a set of <b>options</b>, setup every client authorization found.
716 * Return 0 on success or -1 on failure. If <b>validate_only</b> is set,
717 * parse, warn and return as normal, but don't actually change the
718 * configured state. */
720 hs_config_client_auth_all(const or_options_t
*options
, int validate_only
)
724 /* Configure v2 authorization. */
725 if (rend_parse_service_authorization(options
, validate_only
) < 0) {
729 /* Configure v3 authorization. */
730 if (hs_config_client_authorization(options
, validate_only
) < 0) {
741 * Free all resources held by the hs_config.c module.
744 hs_config_free_all(void)
746 config_mgr_free(hs_opts_mgr
);