aboutsummaryrefslogtreecommitdiff
path: root/src/or/rendservice.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/rendservice.c')
-rw-r--r--src/or/rendservice.c110
1 files changed, 72 insertions, 38 deletions
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 35e8b9057..4413ae9d8 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -14,6 +14,7 @@
#include "config.h"
#include "directory.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "rendclient.h"
#include "rendcommon.h"
#include "rendservice.h"
@@ -181,6 +182,31 @@ rend_add_service(rend_service_t *service)
log_warn(LD_CONFIG, "Hidden service with no ports configured; ignoring.");
rend_service_free(service);
} else {
+ int dupe = 0;
+ /* XXX This duplicate check has two problems:
+ *
+ * a) It's O(n^2), but the same comment from the bottom of
+ * rend_config_services() should apply.
+ *
+ * b) We only compare directory paths as strings, so we can't
+ * detect two distinct paths that specify the same directory
+ * (which can arise from symlinks, case-insensitivity, bind
+ * mounts, etc.).
+ *
+ * It also can't detect that two separate Tor instances are trying
+ * to use the same HiddenServiceDir; for that, we would need a
+ * lock file. But this is enough to detect a simple mistake that
+ * at least one person has actually made.
+ */
+ SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
+ dupe = dupe ||
+ !strcmp(ptr->directory, service->directory));
+ if (dupe) {
+ log_warn(LD_REND, "Another hidden service is already configured for "
+ "directory %s, ignoring.", service->directory);
+ rend_service_free(service);
+ return;
+ }
smartlist_add(rend_service_list, service);
log_debug(LD_REND,"Configuring service with directory \"%s\"",
service->directory);
@@ -266,7 +292,7 @@ parse_port_config(const char *string)
* normal, but don't actually change the configured services.)
*/
int
-rend_config_services(or_options_t *options, int validate_only)
+rend_config_services(const or_options_t *options, int validate_only)
{
config_line_t *line;
rend_service_t *service = NULL;
@@ -474,7 +500,8 @@ rend_config_services(or_options_t *options, int validate_only)
if (keep_it)
continue;
log_info(LD_REND, "Closing intro point %s for service %s.",
- safe_str_client(oc->build_state->chosen_exit->nickname),
+ safe_str_client(extend_info_describe(
+ oc->build_state->chosen_exit)),
oc->rend_data->onion_address);
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
/* XXXX Is there another reason we should use here? */
@@ -543,7 +570,7 @@ rend_service_load_keys(void)
s->directory);
/* Check/create directory */
- if (check_private_dir(s->directory, CPD_CREATE) < 0)
+ if (check_private_dir(s->directory, CPD_CREATE, get_options()->User) < 0)
return -1;
/* Load key */
@@ -876,8 +903,9 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
time_t now = time(NULL);
char diffie_hellman_hash[DIGEST_LEN];
time_t *access_time;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->rend_data);
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
@@ -1005,7 +1033,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
} else {
char *rp_nickname;
size_t nickname_field_len;
- routerinfo_t *router;
+ const node_t *node;
int version;
if (*buf == 1) {
rp_nickname = buf+1;
@@ -1032,8 +1060,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
len -= nickname_field_len;
len -= rp_nickname - buf; /* also remove header space used by version, if
* any */
- router = router_get_by_nickname(rp_nickname, 0);
- if (!router) {
+ node = node_get_by_nickname(rp_nickname, 0);
+ if (!node) {
log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
escaped_safe_str_client(rp_nickname));
/* XXXX Add a no-such-router reason? */
@@ -1041,7 +1069,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
goto err;
}
- extend_info = extend_info_from_router(router);
+ extend_info = extend_info_from_node(node);
}
if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
@@ -1146,7 +1174,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
if (!launched) { /* give up */
log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous "
"point %s for service %s.",
- escaped_safe_str_client(extend_info->nickname),
+ safe_str_client(extend_info_describe(extend_info)),
serviceid);
reason = END_CIRC_REASON_CONNECTFAILED;
goto err;
@@ -1154,7 +1182,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
log_info(LD_REND,
"Accepted intro; launching circuit to %s "
"(cookie %s) for service %s.",
- escaped_safe_str_client(extend_info->nickname),
+ safe_str_client(extend_info_describe(extend_info)),
hexcookie, serviceid);
tor_assert(launched->build_state);
/* Fill in the circuit's state. */
@@ -1206,7 +1234,8 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
"Attempt to build circuit to %s for rendezvous has failed "
"too many times or expired; giving up.",
oldcirc->build_state ?
- oldcirc->build_state->chosen_exit->nickname : "*unknown*");
+ safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
+ : "*unknown*");
return;
}
@@ -1220,7 +1249,7 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
}
log_info(LD_REND,"Reattempting rendezvous circuit to '%s'",
- oldstate->chosen_exit->nickname);
+ safe_str(extend_info_describe(oldstate->chosen_exit)));
newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
oldstate->chosen_exit,
@@ -1228,7 +1257,7 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
if (!newcirc) {
log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.",
- oldstate->chosen_exit->nickname);
+ safe_str(extend_info_describe(oldstate->chosen_exit)));
return;
}
newstate = newcirc->build_state;
@@ -1252,7 +1281,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
log_info(LD_REND,
"Launching circuit to introduction point %s for service %s",
- escaped_safe_str_client(intro->extend_info->nickname),
+ safe_str_client(extend_info_describe(intro->extend_info)),
service->service_id);
rep_hist_note_used_internal(time(NULL), 1, 0);
@@ -1265,7 +1294,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
if (!launched) {
log_info(LD_REND,
"Can't launch circuit to establish introduction at %s.",
- escaped_safe_str_client(intro->extend_info->nickname));
+ safe_str_client(extend_info_describe(intro->extend_info)));
return -1;
}
@@ -1331,6 +1360,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
crypto_pk_env_t *intro_key;
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->cpath);
tor_assert(circuit->rend_data);
@@ -1349,7 +1379,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
/* If we already have enough introduction circuits for this service,
* redefine this one as a general circuit or close it, depending. */
if (count_established_intro_points(serviceid) > NUM_INTRO_POINTS) {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->ExcludeNodes) {
/* XXXX in some future version, we can test whether the transition is
allowed or not given the actual nodes in the circuit. But for now,
@@ -1473,6 +1503,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
tor_assert(circuit->cpath);
tor_assert(circuit->build_state);
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->rend_data);
hop = circuit->build_state->pending_final_cpath;
tor_assert(hop);
@@ -1606,11 +1637,11 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
hs_dir->identity_digest))
/* Don't upload descriptor if we succeeded in doing so last time. */
continue;
- if (!router_get_by_digest(hs_dir->identity_digest)) {
+ if (!router_get_by_id_digest(hs_dir->identity_digest)) {
log_info(LD_REND, "Not sending publish request for v2 descriptor to "
- "hidden service directory '%s'; we don't have its "
+ "hidden service directory %s; we don't have its "
"router descriptor. Queuing for later upload.",
- hs_dir->nickname);
+ safe_str_client(routerstatus_describe(hs_dir)));
failed_upload = -1;
continue;
}
@@ -1783,19 +1814,19 @@ void
rend_services_introduce(void)
{
int i,j,r;
- routerinfo_t *router;
+ const node_t *node;
rend_service_t *service;
rend_intro_point_t *intro;
int changed, prev_intro_nodes;
- smartlist_t *intro_routers;
+ smartlist_t *intro_nodes;
time_t now;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
- intro_routers = smartlist_create();
+ intro_nodes = smartlist_create();
now = time(NULL);
for (i=0; i < smartlist_len(rend_service_list); ++i) {
- smartlist_clear(intro_routers);
+ smartlist_clear(intro_nodes);
service = smartlist_get(rend_service_list, i);
tor_assert(service);
@@ -1815,10 +1846,11 @@ rend_services_introduce(void)
service. */
for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
intro = smartlist_get(service->intro_nodes, j);
- router = router_get_by_digest(intro->extend_info->identity_digest);
- if (!router || !find_intro_circuit(intro, service->pk_digest)) {
+ node = node_get_by_id(intro->extend_info->identity_digest);
+ if (!node || !find_intro_circuit(intro, service->pk_digest)) {
log_info(LD_REND,"Giving up on %s as intro point for %s.",
- intro->extend_info->nickname, service->service_id);
+ safe_str_client(extend_info_describe(intro->extend_info)),
+ safe_str_client(service->service_id));
if (service->desc) {
SMARTLIST_FOREACH(service->desc->intro_nodes, rend_intro_point_t *,
dintro, {
@@ -1835,8 +1867,8 @@ rend_services_introduce(void)
smartlist_del(service->intro_nodes,j--);
changed = 1;
}
- if (router)
- smartlist_add(intro_routers, router);
+ if (node)
+ smartlist_add(intro_nodes, (void*)node);
}
/* We have enough intro points, and the intro points we thought we had were
@@ -1865,26 +1897,27 @@ rend_services_introduce(void)
#define NUM_INTRO_POINTS_INIT (NUM_INTRO_POINTS + 2)
for (j=prev_intro_nodes; j < (prev_intro_nodes == 0 ?
NUM_INTRO_POINTS_INIT : NUM_INTRO_POINTS); ++j) {
- router_crn_flags_t flags = CRN_NEED_UPTIME;
+ router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
flags |= CRN_ALLOW_INVALID;
- router = router_choose_random_node(intro_routers,
- options->ExcludeNodes, flags);
- if (!router) {
+ node = router_choose_random_node(intro_nodes,
+ options->ExcludeNodes, flags);
+ if (!node) {
log_warn(LD_REND,
"Could only establish %d introduction points for %s.",
smartlist_len(service->intro_nodes), service->service_id);
break;
}
changed = 1;
- smartlist_add(intro_routers, router);
+ smartlist_add(intro_nodes, (void*)node);
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- intro->extend_info = extend_info_from_router(router);
+ intro->extend_info = extend_info_from_node(node);
intro->intro_key = crypto_new_pk_env();
tor_assert(!crypto_pk_generate_key(intro->intro_key));
smartlist_add(service->intro_nodes, intro);
log_info(LD_REND, "Picked router %s as an intro point for %s.",
- router->nickname, service->service_id);
+ safe_str_client(node_describe(node)),
+ safe_str_client(service->service_id));
}
/* If there's no need to launch new circuits, stop here. */
@@ -1897,11 +1930,12 @@ rend_services_introduce(void)
r = rend_service_launch_establish_intro(service, intro);
if (r<0) {
log_warn(LD_REND, "Error launching circuit to node %s for service %s.",
- intro->extend_info->nickname, service->service_id);
+ safe_str_client(extend_info_describe(intro->extend_info)),
+ safe_str_client(service->service_id));
}
}
}
- smartlist_free(intro_routers);
+ smartlist_free(intro_nodes);
}
/** Regenerate and upload rendezvous service descriptors for all