Add Coccinelle patch for replacing NULL/non-NULL tt_assert().
[tor.git] / src / or / hs_config.c
blob5f9282ea7942d1e11b7c666c4a3badb7acd399e2
1 /* Copyright (c) 2017, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file hs_config.c
6 * \brief Implement hidden service configuration subsystem.
8 * \details
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.
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.
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 **/
26 #define HS_CONFIG_PRIVATE
28 #include "hs_common.h"
29 #include "hs_config.h"
30 #include "hs_service.h"
31 #include "rendservice.h"
33 /* Using the given list of services, stage them into our global state. Every
34 * service version are handled. This function can remove entries in the given
35 * service_list.
37 * Staging a service means that we take all services in service_list and we
38 * put them in the staging list (global) which acts as a temporary list that
39 * is used by the service loading key process. In other words, staging a
40 * service puts it in a list to be considered when loading the keys and then
41 * moved to the main global list. */
42 static void
43 stage_services(smartlist_t *service_list)
45 tor_assert(service_list);
47 /* This is v2 specific. Trigger service pruning which will make sure the
48 * just configured services end up in the main global list. It should only
49 * be done in non validation mode because v2 subsystem handles service
50 * object differently. */
51 rend_service_prune_list();
53 /* Cleanup v2 service from the list, we don't need those object anymore
54 * because we validated them all against the others and we want to stage
55 * only >= v3 service. And remember, v2 has a different object type which is
56 * shadow copied from an hs_service_t type. */
57 SMARTLIST_FOREACH_BEGIN(service_list, hs_service_t *, s) {
58 if (s->config.version == HS_VERSION_TWO) {
59 SMARTLIST_DEL_CURRENT(service_list, s);
60 hs_service_free(s);
62 } SMARTLIST_FOREACH_END(s);
64 /* This is >= v3 specific. Using the newly configured service list, stage
65 * them into our global state. Every object ownership is lost after. */
66 hs_service_stage_services(service_list);
69 /* Validate the given service against all service in the given list. If the
70 * service is ephemeral, this function ignores it. Services with the same
71 * directory path aren't allowed and will return an error. If a duplicate is
72 * found, 1 is returned else 0 if none found. */
73 static int
74 service_is_duplicate_in_list(const smartlist_t *service_list,
75 const hs_service_t *service)
77 int ret = 0;
79 tor_assert(service_list);
80 tor_assert(service);
82 /* Ephemeral service don't have a directory configured so no need to check
83 * for a service in the list having the same path. */
84 if (service->config.is_ephemeral) {
85 goto end;
88 /* XXX: Validate if we have any service that has the given service dir path.
89 * This has two problems:
91 * a) It's O(n^2), but the same comment from the bottom of
92 * rend_config_services() should apply.
94 * b) We only compare directory paths as strings, so we can't
95 * detect two distinct paths that specify the same directory
96 * (which can arise from symlinks, case-insensitivity, bind
97 * mounts, etc.).
99 * It also can't detect that two separate Tor instances are trying
100 * to use the same HiddenServiceDir; for that, we would need a
101 * lock file. But this is enough to detect a simple mistake that
102 * at least one person has actually made. */
103 SMARTLIST_FOREACH_BEGIN(service_list, const hs_service_t *, s) {
104 if (!strcmp(s->config.directory_path, service->config.directory_path)) {
105 log_warn(LD_REND, "Another hidden service is already configured "
106 "for directory %s",
107 escaped(service->config.directory_path));
108 ret = 1;
109 goto end;
111 } SMARTLIST_FOREACH_END(s);
113 end:
114 return ret;
117 /* Helper function: Given an configuration option name, its value, a minimum
118 * min and a maxium max, parse the value as a uint64_t. On success, ok is set
119 * to 1 and ret is the parsed value. On error, ok is set to 0 and ret must be
120 * ignored. This function logs both on error and success. */
121 static uint64_t
122 helper_parse_uint64(const char *opt, const char *value, uint64_t min,
123 uint64_t max, int *ok)
125 uint64_t ret = 0;
127 tor_assert(opt);
128 tor_assert(value);
129 tor_assert(ok);
131 *ok = 0;
132 ret = tor_parse_uint64(value, 10, min, max, ok, NULL);
133 if (!*ok) {
134 log_warn(LD_CONFIG, "%s must be between %" PRIu64 " and %"PRIu64
135 ", not %s.",
136 opt, min, max, value);
137 goto err;
139 log_info(LD_CONFIG, "%s was parsed to %" PRIu64, opt, ret);
140 err:
141 return ret;
144 /* Return true iff the given options starting at line_ for a hidden service
145 * contains at least one invalid option. Each hidden service option don't
146 * apply to all versions so this function can find out. The line_ MUST start
147 * right after the HiddenServiceDir line of this service.
149 * This is mainly for usability so we can inform the user of any invalid
150 * option for the hidden service version instead of silently ignoring. */
151 static int
152 config_has_invalid_options(const config_line_t *line_,
153 const hs_service_t *service)
155 int ret = 0;
156 const char **optlist;
157 const config_line_t *line;
159 tor_assert(service);
160 tor_assert(service->config.version <= HS_VERSION_MAX);
162 /* List of options that a v3 service doesn't support thus must exclude from
163 * its configuration. */
164 const char *opts_exclude_v3[] = {
165 "HiddenServiceAuthorizeClient",
166 NULL /* End marker. */
169 /* Defining the size explicitly allows us to take advantage of the compiler
170 * which warns us if we ever bump the max version but forget to grow this
171 * array. The plus one is because we have a version 0 :). */
172 struct {
173 const char **list;
174 } exclude_lists[HS_VERSION_MAX + 1] = {
175 { NULL }, /* v0. */
176 { NULL }, /* v1. */
177 { NULL }, /* v2 */
178 { opts_exclude_v3 }, /* v3. */
181 optlist = exclude_lists[service->config.version].list;
182 if (optlist == NULL) {
183 /* No exclude options to look at for this version. */
184 goto end;
186 for (int i = 0; optlist[i]; i++) {
187 const char *opt = optlist[i];
188 for (line = line_; line; line = line->next) {
189 if (!strcasecmp(line->key, "HiddenServiceDir")) {
190 /* We just hit the next hidden service, stop right now. */
191 goto end;
193 if (!strcasecmp(line->key, opt)) {
194 log_warn(LD_CONFIG, "Hidden service option %s is incompatible with "
195 "version %" PRIu32 " of service in %s",
196 opt, service->config.version,
197 service->config.directory_path);
198 ret = 1;
199 /* Continue the loop so we can find all possible options. */
200 continue;
204 end:
205 return ret;
208 /* Validate service configuration. This is used when loading the configuration
209 * and once we've setup a service object, it's config object is passed to this
210 * function for further validation. This does not validate service key
211 * material. Return 0 if valid else -1 if invalid. */
212 static int
213 config_validate_service(const hs_service_config_t *config)
215 tor_assert(config);
217 /* Amount of ports validation. */
218 if (!config->ports || smartlist_len(config->ports) == 0) {
219 log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured.",
220 escaped(config->directory_path));
221 goto invalid;
224 /* Valid. */
225 return 0;
226 invalid:
227 return -1;
230 /* Configuration funcion for a version 3 service. The line_ must be pointing
231 * to the directive directly after a HiddenServiceDir. That way, when hitting
232 * the next HiddenServiceDir line or reaching the end of the list of lines, we
233 * know that we have to stop looking for more options. The given service
234 * object must be already allocated and passed through
235 * config_generic_service() prior to calling this function.
237 * Return 0 on success else a negative value. */
238 static int
239 config_service_v3(const config_line_t *line_,
240 hs_service_config_t *config)
242 int have_num_ip = 0;
243 const char *dup_opt_seen = NULL;
244 const config_line_t *line;
246 tor_assert(config);
248 for (line = line_; line; line = line->next) {
249 int ok = 0;
250 if (!strcasecmp(line->key, "HiddenServiceDir")) {
251 /* We just hit the next hidden service, stop right now. */
252 break;
254 /* Number of introduction points. */
255 if (!strcasecmp(line->key, "HiddenServiceNumIntroductionPoints")) {
256 config->num_intro_points =
257 (unsigned int) helper_parse_uint64(line->key, line->value,
258 NUM_INTRO_POINTS_DEFAULT,
259 HS_CONFIG_V3_MAX_INTRO_POINTS,
260 &ok);
261 if (!ok || have_num_ip) {
262 if (have_num_ip)
263 dup_opt_seen = line->key;
264 goto err;
266 have_num_ip = 1;
267 continue;
271 /* We do not load the key material for the service at this stage. This is
272 * done later once tor can confirm that it is in a running state. */
274 /* We are about to return a fully configured service so do one last pass of
275 * validation at it. */
276 if (config_validate_service(config) < 0) {
277 goto err;
280 return 0;
281 err:
282 if (dup_opt_seen) {
283 log_warn(LD_CONFIG, "Duplicate directive %s.", dup_opt_seen);
285 return -1;
288 /* Configure a service using the given options in line_ and options. This is
289 * called for any service regardless of its version which means that all
290 * directives in this function are generic to any service version. This
291 * function will also check the validity of the service directory path.
293 * The line_ must be pointing to the directive directly after a
294 * HiddenServiceDir. That way, when hitting the next HiddenServiceDir line or
295 * reaching the end of the list of lines, we know that we have to stop looking
296 * for more options.
298 * Return 0 on success else -1. */
299 static int
300 config_generic_service(const config_line_t *line_,
301 const or_options_t *options,
302 hs_service_t *service)
304 int dir_seen = 0;
305 const config_line_t *line;
306 hs_service_config_t *config;
307 /* If this is set, we've seen a duplicate of this option. Keep the string
308 * so we can log the directive. */
309 const char *dup_opt_seen = NULL;
310 /* These variables will tell us if we ever have duplicate. */
311 int have_version = 0, have_allow_unknown_ports = 0;
312 int have_dir_group_read = 0, have_max_streams = 0;
313 int have_max_streams_close = 0;
315 tor_assert(line_);
316 tor_assert(options);
317 tor_assert(service);
319 /* Makes thing easier. */
320 config = &service->config;
322 /* The first line starts with HiddenServiceDir so we consider what's next is
323 * the configuration of the service. */
324 for (line = line_; line ; line = line->next) {
325 int ok = 0;
327 /* This indicate that we have a new service to configure. */
328 if (!strcasecmp(line->key, "HiddenServiceDir")) {
329 /* This function only configures one service at a time so if we've
330 * already seen one, stop right now. */
331 if (dir_seen) {
332 break;
334 /* Ok, we've seen one and we are about to configure it. */
335 dir_seen = 1;
336 config->directory_path = tor_strdup(line->value);
337 log_info(LD_CONFIG, "HiddenServiceDir=%s. Configuring...",
338 escaped(config->directory_path));
339 continue;
341 if (BUG(!dir_seen)) {
342 goto err;
344 /* Version of the service. */
345 if (!strcasecmp(line->key, "HiddenServiceVersion")) {
346 service->config.version =
347 (uint32_t) helper_parse_uint64(line->key, line->value, HS_VERSION_MIN,
348 HS_VERSION_MAX, &ok);
349 if (!ok || have_version) {
350 if (have_version)
351 dup_opt_seen = line->key;
352 goto err;
354 have_version = 1;
355 continue;
357 /* Virtual port. */
358 if (!strcasecmp(line->key, "HiddenServicePort")) {
359 char *err_msg = NULL;
360 /* XXX: Can we rename this? */
361 rend_service_port_config_t *portcfg =
362 rend_service_parse_port_config(line->value, " ", &err_msg);
363 if (!portcfg) {
364 if (err_msg) {
365 log_warn(LD_CONFIG, "%s", err_msg);
367 tor_free(err_msg);
368 goto err;
370 tor_assert(!err_msg);
371 smartlist_add(config->ports, portcfg);
372 log_info(LD_CONFIG, "HiddenServicePort=%s for %s",
373 line->value, escaped(config->directory_path));
374 continue;
376 /* Do we allow unknown ports. */
377 if (!strcasecmp(line->key, "HiddenServiceAllowUnknownPorts")) {
378 config->allow_unknown_ports =
379 (unsigned int) helper_parse_uint64(line->key, line->value, 0, 1, &ok);
380 if (!ok || have_allow_unknown_ports) {
381 if (have_allow_unknown_ports)
382 dup_opt_seen = line->key;
383 goto err;
385 have_allow_unknown_ports = 1;
386 continue;
388 /* Directory group readable. */
389 if (!strcasecmp(line->key, "HiddenServiceDirGroupReadable")) {
390 config->dir_group_readable =
391 (unsigned int) helper_parse_uint64(line->key, line->value, 0, 1, &ok);
392 if (!ok || have_dir_group_read) {
393 if (have_dir_group_read)
394 dup_opt_seen = line->key;
395 goto err;
397 have_dir_group_read = 1;
398 continue;
400 /* Maximum streams per circuit. */
401 if (!strcasecmp(line->key, "HiddenServiceMaxStreams")) {
402 config->max_streams_per_rdv_circuit =
403 helper_parse_uint64(line->key, line->value, 0,
404 HS_CONFIG_MAX_STREAMS_PER_RDV_CIRCUIT, &ok);
405 if (!ok || have_max_streams) {
406 if (have_max_streams)
407 dup_opt_seen = line->key;
408 goto err;
410 have_max_streams = 1;
411 continue;
413 /* Maximum amount of streams before we close the circuit. */
414 if (!strcasecmp(line->key, "HiddenServiceMaxStreamsCloseCircuit")) {
415 config->max_streams_close_circuit =
416 (unsigned int) helper_parse_uint64(line->key, line->value, 0, 1, &ok);
417 if (!ok || have_max_streams_close) {
418 if (have_max_streams_close)
419 dup_opt_seen = line->key;
420 goto err;
422 have_max_streams_close = 1;
423 continue;
427 /* Check if we are configured in non anonymous mode and single hop mode
428 * meaning every service become single onion. */
429 if (rend_service_allow_non_anonymous_connection(options) &&
430 rend_service_non_anonymous_mode_enabled(options)) {
431 config->is_single_onion = 1;
434 /* Success */
435 return 0;
436 err:
437 if (dup_opt_seen) {
438 log_warn(LD_CONFIG, "Duplicate directive %s.", dup_opt_seen);
440 return -1;
443 /* Configure a service using the given line and options. This function will
444 * call the corresponding configuration function for a specific service
445 * version and validate the service against the other ones. On success, add
446 * the service to the given list and return 0. On error, nothing is added to
447 * the list and a negative value is returned. */
448 static int
449 config_service(const config_line_t *line, const or_options_t *options,
450 smartlist_t *service_list)
452 int ret;
453 hs_service_t *service = NULL;
455 tor_assert(line);
456 tor_assert(options);
457 tor_assert(service_list);
459 /* We have a new hidden service. */
460 service = hs_service_new(options);
461 /* We'll configure that service as a generic one and then pass it to a
462 * specific function according to the configured version number. */
463 if (config_generic_service(line, options, service) < 0) {
464 goto err;
466 tor_assert(service->config.version <= HS_VERSION_MAX);
467 /* Before we configure the service on a per-version basis, we'll make
468 * sure that this set of options for a service are valid that is for
469 * instance an option only for v2 is not used for v3. */
470 if (config_has_invalid_options(line->next, service)) {
471 goto err;
473 /* Check permission on service directory that was just parsed. And this must
474 * be done regardless of the service version. Do not ask for the directory
475 * to be created, this is done when the keys are loaded because we could be
476 * in validation mode right now. */
477 if (hs_check_service_private_dir(options->User,
478 service->config.directory_path,
479 service->config.dir_group_readable,
480 0) < 0) {
481 goto err;
483 /* Different functions are in charge of specific options for a version. We
484 * start just after the service directory line so once we hit another
485 * directory line, the function knows that it has to stop parsing. */
486 switch (service->config.version) {
487 case HS_VERSION_TWO:
488 ret = rend_config_service(line->next, options, &service->config);
489 break;
490 case HS_VERSION_THREE:
491 ret = config_service_v3(line->next, &service->config);
492 break;
493 default:
494 /* We do validate before if we support the parsed version. */
495 tor_assert_nonfatal_unreached();
496 goto err;
498 if (ret < 0) {
499 goto err;
501 /* We'll check if this service can be kept depending on the others
502 * configured previously. */
503 if (service_is_duplicate_in_list(service_list, service)) {
504 goto err;
506 /* Passes, add it to the given list. */
507 smartlist_add(service_list, service);
508 return 0;
510 err:
511 hs_service_free(service);
512 return -1;
515 /* From a set of <b>options</b>, setup every hidden service found. Return 0 on
516 * success or -1 on failure. If <b>validate_only</b> is set, parse, warn and
517 * return as normal, but don't actually change the configured services. */
519 hs_config_service_all(const or_options_t *options, int validate_only)
521 int dir_option_seen = 0, ret = -1;
522 const config_line_t *line;
523 smartlist_t *new_service_list = NULL;
525 tor_assert(options);
527 /* Newly configured service are put in that list which is then used for
528 * validation and staging for >= v3. */
529 new_service_list = smartlist_new();
531 for (line = options->RendConfigLines; line; line = line->next) {
532 /* Ignore all directives that aren't the start of a service. */
533 if (strcasecmp(line->key, "HiddenServiceDir")) {
534 if (!dir_option_seen) {
535 log_warn(LD_CONFIG, "%s with no preceding HiddenServiceDir directive",
536 line->key);
537 goto err;
539 continue;
541 /* Flag that we've seen a directory directive and we'll use it to make
542 * sure that the torrc options ordering is actually valid. */
543 dir_option_seen = 1;
545 /* Try to configure this service now. On success, it will be added to the
546 * list and validated against the service in that same list. */
547 if (config_service(line, options, new_service_list) < 0) {
548 goto err;
552 /* In non validation mode, we'll stage those services we just successfully
553 * configured. Service ownership is transfered from the list to the global
554 * state. If any service is invalid, it will be removed from the list and
555 * freed. All versions are handled in that function. */
556 if (!validate_only) {
557 stage_services(new_service_list);
558 } else {
559 /* We've just validated that we were able to build a clean working list of
560 * services. We don't need those objects anymore. */
561 SMARTLIST_FOREACH(new_service_list, hs_service_t *, s,
562 hs_service_free(s));
563 /* For the v2 subsystem, the configuration function adds the service
564 * object to the staging list and it is transferred in the main list
565 * through the prunning process. In validation mode, we thus have to purge
566 * the staging list so it's not kept in memory as valid service. */
567 rend_service_free_staging_list();
570 /* Success. Note that the service list has no ownership of its content. */
571 ret = 0;
572 goto end;
574 err:
575 SMARTLIST_FOREACH(new_service_list, hs_service_t *, s, hs_service_free(s));
577 end:
578 smartlist_free(new_service_list);
579 /* Tor main should call the free all function on error. */
580 return ret;