diff options
author | Nick Mathewson <nickm@torproject.org> | 2016-11-07 16:12:13 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2016-11-07 16:12:13 -0500 |
commit | c2fc0941a53884c63c477f68c74a26627bb35db8 (patch) | |
tree | 58b30f597f9e7e10a0cfe7806e9c028fc19d9560 /src/or | |
parent | e482541cfb0bd85cab8a7fed86e31e0b18912730 (diff) | |
parent | a77187a52c9594c0c168596eec856ee11c447fe0 (diff) | |
download | tor-c2fc0941a53884c63c477f68c74a26627bb35db8.tar.gz tor-c2fc0941a53884c63c477f68c74a26627bb35db8.zip |
Merge remote-tracking branch 'teor/bug20484_029_v2' into maint-0.2.9
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/rendservice.c | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 3afe880554..56dbacdaf7 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -72,6 +72,10 @@ static ssize_t rend_service_parse_intro_for_v3( size_t plaintext_len, char **err_msg_out); +static int rend_service_check_private_dir(const or_options_t *options, + const rend_service_t *s, + int create); + /** Represents the mapping from a virtual port of a rendezvous service to * a real port on some IP. */ @@ -462,6 +466,11 @@ rend_config_services(const or_options_t *options, int validate_only) for (line = options->RendConfigLines; line; line = line->next) { if (!strcasecmp(line->key, "HiddenServiceDir")) { if (service) { /* register the one we just finished parsing */ + if (rend_service_check_private_dir(options, service, 0) < 0) { + rend_service_free(service); + return -1; + } + if (validate_only) rend_service_free(service); else @@ -672,12 +681,7 @@ rend_config_services(const or_options_t *options, int validate_only) } } if (service) { - cpd_check_t check_opts = CPD_CHECK_MODE_ONLY|CPD_CHECK; - if (service->dir_group_readable) { - check_opts |= CPD_GROUP_READ; - } - - if (check_private_dir(service->directory, check_opts, options->User) < 0) { + if (rend_service_check_private_dir(options, service, 0) < 0) { rend_service_free(service); return -1; } @@ -1001,7 +1005,9 @@ service_is_single_onion_poisoned(const rend_service_t *service) fstatus = file_status(poison_fname); tor_free(poison_fname); - /* If this fname is occupied, the hidden service has been poisoned. */ + /* If this fname is occupied, the hidden service has been poisoned. + * fstatus can be FN_ERROR if the service directory does not exist, in that + * case, there is obviously no private key. */ if (fstatus == FN_FILE || fstatus == FN_EMPTY) { return 1; } @@ -1017,7 +1023,9 @@ rend_service_private_key_exists(const rend_service_t *service) char *private_key_path = rend_service_path(service, private_key_fname); const file_status_t private_key_status = file_status(private_key_path); tor_free(private_key_path); - /* Only non-empty regular private key files could have been used before. */ + /* Only non-empty regular private key files could have been used before. + * fstatus can be FN_ERROR if the service directory does not exist, in that + * case, there is obviously no private key. */ return private_key_status == FN_FILE; } @@ -1090,6 +1098,10 @@ poison_new_single_onion_hidden_service_dir(const rend_service_t *service) return -1; } + /* Make sure the directory exists */ + if (rend_service_check_private_dir(get_options(), service, 1) < 0) + return -1; + poison_fname = rend_service_sos_poison_path(service); switch (file_status(poison_fname)) { @@ -1245,6 +1257,37 @@ rend_service_derive_key_digests(struct rend_service_t *s) return 0; } +/** Make sure that the directory for <b>s</b> is private, using the config in + * <b>options</b>. + * If <b>create</b> is true: + * - if the directory exists, change permissions if needed, + * - if the directory does not exist, create it with the correct permissions. + * If <b>create</b> is false: + * - if the directory exists, check permissions, + * - if the directory does not exist, check if we think we can create it. + * Return 0 on success, -1 on failure. */ +static int +rend_service_check_private_dir(const or_options_t *options, + const rend_service_t *s, + int create) +{ + cpd_check_t check_opts = CPD_NONE; + if (create) { + check_opts |= CPD_CREATE; + } else { + check_opts |= CPD_CHECK_MODE_ONLY; + check_opts |= CPD_CHECK; + } + if (s->dir_group_readable) { + check_opts |= CPD_GROUP_READ; + } + /* Check/create directory */ + if (check_private_dir(s->directory, check_opts, options->User) < 0) { + return -1; + } + return 0; +} + /** Load and/or generate private keys for the hidden service <b>s</b>, * possibly including keys for client authorization. Return 0 on success, -1 * on failure. */ @@ -1253,23 +1296,9 @@ rend_service_load_keys(rend_service_t *s) { char *fname = NULL; char buf[128]; - cpd_check_t check_opts = CPD_CREATE; - if (s->dir_group_readable) { - check_opts |= CPD_GROUP_READ; - } - /* Check/create directory */ - if (check_private_dir(s->directory, check_opts, get_options()->User) < 0) { + if (rend_service_check_private_dir(get_options(), s, 1) < 0) goto err; - } -#ifndef _WIN32 - if (s->dir_group_readable) { - /* Only new dirs created get new opts, also enforce group read. */ - if (chmod(s->directory, 0750)) { - log_warn(LD_FS,"Unable to make %s group-readable.", s->directory); - } - } -#endif /* Load key */ fname = rend_service_path(s, private_key_fname); |