diff options
author | Nick Mathewson <nickm@torproject.org> | 2016-11-07 16:31:40 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2016-11-07 16:31:40 -0500 |
commit | 3e3040a5d911e6c4ae59114a0f98daf09ee299bc (patch) | |
tree | 74ef382fdecab05746d0fb8ccbd81dd0a2c29878 /src/or/rendservice.c | |
parent | 7236e42684de017d66b38bac13c4f7ff8dac428c (diff) | |
parent | 9994404238e6b87907f811cab2a5126d030ff55d (diff) | |
download | tor-3e3040a5d911e6c4ae59114a0f98daf09ee299bc.tar.gz tor-3e3040a5d911e6c4ae59114a0f98daf09ee299bc.zip |
Merge branch 'maint-0.2.9'
Conflicts:
src/or/rendservice.c
Diffstat (limited to 'src/or/rendservice.c')
-rw-r--r-- | src/or/rendservice.c | 76 |
1 files changed, 52 insertions, 24 deletions
diff --git a/src/or/rendservice.c b/src/or/rendservice.c index b6bf63d829..0819d8a713 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -73,6 +73,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. */ @@ -472,6 +476,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 @@ -687,12 +696,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; } @@ -1016,7 +1020,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; } @@ -1032,7 +1038,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; } @@ -1105,6 +1113,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)) { @@ -1260,6 +1272,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. */ @@ -1268,24 +1311,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.", - rend_service_escaped_dir(s)); - } - } -#endif /* Load key */ fname = rend_service_path(s, private_key_fname); |