correct a point about logging
[tor.git] / src / or / rendservice.c
blob6af4778dfc118841ee92ef1fc2a0da414261e57e
1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 * Copyright (c) 2007-2012, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
5 /**
6 * \file rendservice.c
7 * \brief The hidden-service side of rendezvous functionality.
8 **/
10 #include "or.h"
11 #include "circuitbuild.h"
12 #include "circuitlist.h"
13 #include "circuituse.h"
14 #include "config.h"
15 #include "directory.h"
16 #include "networkstatus.h"
17 #include "nodelist.h"
18 #include "rendclient.h"
19 #include "rendcommon.h"
20 #include "rendservice.h"
21 #include "router.h"
22 #include "relay.h"
23 #include "rephist.h"
24 #include "routerlist.h"
25 #include "routerparse.h"
27 static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro,
28 const char *pk_digest);
29 static rend_intro_point_t *find_intro_point(origin_circuit_t *circ);
31 static int intro_point_accepted_intro_count(rend_intro_point_t *intro);
32 static int intro_point_should_expire_now(rend_intro_point_t *intro,
33 time_t now);
35 /** Represents the mapping from a virtual port of a rendezvous service to
36 * a real port on some IP.
38 typedef struct rend_service_port_config_t {
39 uint16_t virtual_port;
40 uint16_t real_port;
41 tor_addr_t real_addr;
42 } rend_service_port_config_t;
44 /** Try to maintain this many intro points per service by default. */
45 #define NUM_INTRO_POINTS_DEFAULT 3
46 /** Maintain no more than this many intro points per hidden service. */
47 #define NUM_INTRO_POINTS_MAX 10
49 /** If we can't build our intro circuits, don't retry for this long. */
50 #define INTRO_CIRC_RETRY_PERIOD (60*5)
51 /** Don't try to build more than this many circuits before giving up
52 * for a while.*/
53 #define MAX_INTRO_CIRCS_PER_PERIOD 10
54 /** How many times will a hidden service operator attempt to connect to
55 * a requested rendezvous point before giving up? */
56 #define MAX_REND_FAILURES 30
57 /** How many seconds should we spend trying to connect to a requested
58 * rendezvous point before giving up? */
59 #define MAX_REND_TIMEOUT 30
61 /** How many seconds should we wait for new HS descriptors to reach
62 * our clients before we close an expiring intro point? */
63 #define INTRO_POINT_EXPIRATION_GRACE_PERIOD 5*60
65 /** Represents a single hidden service running at this OP. */
66 typedef struct rend_service_t {
67 /* Fields specified in config file */
68 char *directory; /**< where in the filesystem it stores it */
69 smartlist_t *ports; /**< List of rend_service_port_config_t */
70 rend_auth_type_t auth_type; /**< Client authorization type or 0 if no client
71 * authorization is performed. */
72 smartlist_t *clients; /**< List of rend_authorized_client_t's of
73 * clients that may access our service. Can be NULL
74 * if no client authorization is performed. */
75 /* Other fields */
76 crypto_pk_t *private_key; /**< Permanent hidden-service key. */
77 char service_id[REND_SERVICE_ID_LEN_BASE32+1]; /**< Onion address without
78 * '.onion' */
79 char pk_digest[DIGEST_LEN]; /**< Hash of permanent hidden-service key. */
80 smartlist_t *intro_nodes; /**< List of rend_intro_point_t's we have,
81 * or are trying to establish. */
82 time_t intro_period_started; /**< Start of the current period to build
83 * introduction points. */
84 int n_intro_circuits_launched; /**< Count of intro circuits we have
85 * established in this period. */
86 unsigned int n_intro_points_wanted; /**< Number of intro points this
87 * service wants to have open. */
88 rend_service_descriptor_t *desc; /**< Current hidden service descriptor. */
89 time_t desc_is_dirty; /**< Time at which changes to the hidden service
90 * descriptor content occurred, or 0 if it's
91 * up-to-date. */
92 time_t next_upload_time; /**< Scheduled next hidden service descriptor
93 * upload time. */
94 /** Map from digests of Diffie-Hellman values INTRODUCE2 to time_t
95 * of when they were received. Clients may send INTRODUCE1 cells
96 * for the same rendezvous point through two or more different
97 * introduction points; when they do, this digestmap keeps us from
98 * launching multiple simultaneous attempts to connect to the same
99 * rend point. */
100 digestmap_t *accepted_intro_dh_parts;
101 /** Time at which we last removed expired values from
102 * accepted_intro_dh_parts. */
103 time_t last_cleaned_accepted_intro_dh_parts;
104 } rend_service_t;
106 /** A list of rend_service_t's for services run on this OP.
108 static smartlist_t *rend_service_list = NULL;
110 /** Return the number of rendezvous services we have configured. */
112 num_rend_services(void)
114 if (!rend_service_list)
115 return 0;
116 return smartlist_len(rend_service_list);
119 /** Return a string identifying <b>service</b>, suitable for use in a
120 * log message. The result does not need to be freed, but may be
121 * overwritten by the next call to this function. */
122 static const char *
123 rend_service_describe_for_log(rend_service_t *service)
125 /* XXX024 Use this function throughout rendservice.c. */
126 /* XXX024 Return a more useful description? */
127 return safe_str_client(service->service_id);
130 /** Helper: free storage held by a single service authorized client entry. */
131 static void
132 rend_authorized_client_free(rend_authorized_client_t *client)
134 if (!client)
135 return;
136 if (client->client_key)
137 crypto_pk_free(client->client_key);
138 tor_free(client->client_name);
139 tor_free(client);
142 /** Helper for strmap_free. */
143 static void
144 rend_authorized_client_strmap_item_free(void *authorized_client)
146 rend_authorized_client_free(authorized_client);
149 /** Release the storage held by <b>service</b>.
151 static void
152 rend_service_free(rend_service_t *service)
154 if (!service)
155 return;
157 tor_free(service->directory);
158 SMARTLIST_FOREACH(service->ports, void*, p, tor_free(p));
159 smartlist_free(service->ports);
160 if (service->private_key)
161 crypto_pk_free(service->private_key);
162 if (service->intro_nodes) {
163 SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro,
164 rend_intro_point_free(intro););
165 smartlist_free(service->intro_nodes);
168 rend_service_descriptor_free(service->desc);
169 if (service->clients) {
170 SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, c,
171 rend_authorized_client_free(c););
172 smartlist_free(service->clients);
174 digestmap_free(service->accepted_intro_dh_parts, _tor_free);
175 tor_free(service);
178 /** Release all the storage held in rend_service_list.
180 void
181 rend_service_free_all(void)
183 if (!rend_service_list)
184 return;
186 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
187 rend_service_free(ptr));
188 smartlist_free(rend_service_list);
189 rend_service_list = NULL;
192 /** Validate <b>service</b> and add it to rend_service_list if possible.
194 static void
195 rend_add_service(rend_service_t *service)
197 int i;
198 rend_service_port_config_t *p;
200 service->intro_nodes = smartlist_new();
202 if (service->auth_type != REND_NO_AUTH &&
203 smartlist_len(service->clients) == 0) {
204 log_warn(LD_CONFIG, "Hidden service (%s) with client authorization but no "
205 "clients; ignoring.",
206 escaped(service->directory));
207 rend_service_free(service);
208 return;
211 if (!smartlist_len(service->ports)) {
212 log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured; "
213 "ignoring.",
214 escaped(service->directory));
215 rend_service_free(service);
216 } else {
217 int dupe = 0;
218 /* XXX This duplicate check has two problems:
220 * a) It's O(n^2), but the same comment from the bottom of
221 * rend_config_services() should apply.
223 * b) We only compare directory paths as strings, so we can't
224 * detect two distinct paths that specify the same directory
225 * (which can arise from symlinks, case-insensitivity, bind
226 * mounts, etc.).
228 * It also can't detect that two separate Tor instances are trying
229 * to use the same HiddenServiceDir; for that, we would need a
230 * lock file. But this is enough to detect a simple mistake that
231 * at least one person has actually made.
233 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
234 dupe = dupe ||
235 !strcmp(ptr->directory, service->directory));
236 if (dupe) {
237 log_warn(LD_REND, "Another hidden service is already configured for "
238 "directory %s, ignoring.", service->directory);
239 rend_service_free(service);
240 return;
242 smartlist_add(rend_service_list, service);
243 log_debug(LD_REND,"Configuring service with directory \"%s\"",
244 service->directory);
245 for (i = 0; i < smartlist_len(service->ports); ++i) {
246 p = smartlist_get(service->ports, i);
247 log_debug(LD_REND,"Service maps port %d to %s:%d",
248 p->virtual_port, fmt_addr(&p->real_addr), p->real_port);
253 /** Parses a real-port to virtual-port mapping and returns a new
254 * rend_service_port_config_t.
256 * The format is: VirtualPort (IP|RealPort|IP:RealPort)?
258 * IP defaults to 127.0.0.1; RealPort defaults to VirtualPort.
260 static rend_service_port_config_t *
261 parse_port_config(const char *string)
263 smartlist_t *sl;
264 int virtport;
265 int realport;
266 uint16_t p;
267 tor_addr_t addr;
268 const char *addrport;
269 rend_service_port_config_t *result = NULL;
271 sl = smartlist_new();
272 smartlist_split_string(sl, string, " ",
273 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
274 if (smartlist_len(sl) < 1 || smartlist_len(sl) > 2) {
275 log_warn(LD_CONFIG, "Bad syntax in hidden service port configuration.");
276 goto err;
279 virtport = (int)tor_parse_long(smartlist_get(sl,0), 10, 1, 65535, NULL,NULL);
280 if (!virtport) {
281 log_warn(LD_CONFIG, "Missing or invalid port %s in hidden service port "
282 "configuration", escaped(smartlist_get(sl,0)));
283 goto err;
286 if (smartlist_len(sl) == 1) {
287 /* No addr:port part; use default. */
288 realport = virtport;
289 tor_addr_from_ipv4h(&addr, 0x7F000001u); /* 127.0.0.1 */
290 } else {
291 addrport = smartlist_get(sl,1);
292 if (strchr(addrport, ':') || strchr(addrport, '.')) {
293 if (tor_addr_port_lookup(addrport, &addr, &p)<0) {
294 log_warn(LD_CONFIG,"Unparseable address in hidden service port "
295 "configuration.");
296 goto err;
298 realport = p?p:virtport;
299 } else {
300 /* No addr:port, no addr -- must be port. */
301 realport = (int)tor_parse_long(addrport, 10, 1, 65535, NULL, NULL);
302 if (!realport) {
303 log_warn(LD_CONFIG,"Unparseable or out-of-range port %s in hidden "
304 "service port configuration.", escaped(addrport));
305 goto err;
307 tor_addr_from_ipv4h(&addr, 0x7F000001u); /* Default to 127.0.0.1 */
311 result = tor_malloc(sizeof(rend_service_port_config_t));
312 result->virtual_port = virtport;
313 result->real_port = realport;
314 tor_addr_copy(&result->real_addr, &addr);
315 err:
316 SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
317 smartlist_free(sl);
318 return result;
321 /** Set up rend_service_list, based on the values of HiddenServiceDir and
322 * HiddenServicePort in <b>options</b>. Return 0 on success and -1 on
323 * failure. (If <b>validate_only</b> is set, parse, warn and return as
324 * normal, but don't actually change the configured services.)
327 rend_config_services(const or_options_t *options, int validate_only)
329 config_line_t *line;
330 rend_service_t *service = NULL;
331 rend_service_port_config_t *portcfg;
332 smartlist_t *old_service_list = NULL;
334 if (!validate_only) {
335 old_service_list = rend_service_list;
336 rend_service_list = smartlist_new();
339 for (line = options->RendConfigLines; line; line = line->next) {
340 if (!strcasecmp(line->key, "HiddenServiceDir")) {
341 if (service) { /* register the one we just finished parsing */
342 if (validate_only)
343 rend_service_free(service);
344 else
345 rend_add_service(service);
347 service = tor_malloc_zero(sizeof(rend_service_t));
348 service->directory = tor_strdup(line->value);
349 service->ports = smartlist_new();
350 service->intro_period_started = time(NULL);
351 service->n_intro_points_wanted = NUM_INTRO_POINTS_DEFAULT;
352 continue;
354 if (!service) {
355 log_warn(LD_CONFIG, "%s with no preceding HiddenServiceDir directive",
356 line->key);
357 rend_service_free(service);
358 return -1;
360 if (!strcasecmp(line->key, "HiddenServicePort")) {
361 portcfg = parse_port_config(line->value);
362 if (!portcfg) {
363 rend_service_free(service);
364 return -1;
366 smartlist_add(service->ports, portcfg);
367 } else if (!strcasecmp(line->key, "HiddenServiceAuthorizeClient")) {
368 /* Parse auth type and comma-separated list of client names and add a
369 * rend_authorized_client_t for each client to the service's list
370 * of authorized clients. */
371 smartlist_t *type_names_split, *clients;
372 const char *authname;
373 int num_clients;
374 if (service->auth_type != REND_NO_AUTH) {
375 log_warn(LD_CONFIG, "Got multiple HiddenServiceAuthorizeClient "
376 "lines for a single service.");
377 rend_service_free(service);
378 return -1;
380 type_names_split = smartlist_new();
381 smartlist_split_string(type_names_split, line->value, " ", 0, 2);
382 if (smartlist_len(type_names_split) < 1) {
383 log_warn(LD_BUG, "HiddenServiceAuthorizeClient has no value. This "
384 "should have been prevented when parsing the "
385 "configuration.");
386 smartlist_free(type_names_split);
387 rend_service_free(service);
388 return -1;
390 authname = smartlist_get(type_names_split, 0);
391 if (!strcasecmp(authname, "basic")) {
392 service->auth_type = REND_BASIC_AUTH;
393 } else if (!strcasecmp(authname, "stealth")) {
394 service->auth_type = REND_STEALTH_AUTH;
395 } else {
396 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
397 "unrecognized auth-type '%s'. Only 'basic' or 'stealth' "
398 "are recognized.",
399 (char *) smartlist_get(type_names_split, 0));
400 SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
401 smartlist_free(type_names_split);
402 rend_service_free(service);
403 return -1;
405 service->clients = smartlist_new();
406 if (smartlist_len(type_names_split) < 2) {
407 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
408 "auth-type '%s', but no client names.",
409 service->auth_type == REND_BASIC_AUTH ? "basic" : "stealth");
410 SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
411 smartlist_free(type_names_split);
412 continue;
414 clients = smartlist_new();
415 smartlist_split_string(clients, smartlist_get(type_names_split, 1),
416 ",", SPLIT_SKIP_SPACE, 0);
417 SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
418 smartlist_free(type_names_split);
419 /* Remove duplicate client names. */
420 num_clients = smartlist_len(clients);
421 smartlist_sort_strings(clients);
422 smartlist_uniq_strings(clients);
423 if (smartlist_len(clients) < num_clients) {
424 log_info(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
425 "duplicate client name(s); removing.",
426 num_clients - smartlist_len(clients));
427 num_clients = smartlist_len(clients);
429 SMARTLIST_FOREACH_BEGIN(clients, const char *, client_name)
431 rend_authorized_client_t *client;
432 size_t len = strlen(client_name);
433 if (len < 1 || len > REND_CLIENTNAME_MAX_LEN) {
434 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
435 "illegal client name: '%s'. Length must be "
436 "between 1 and %d characters.",
437 client_name, REND_CLIENTNAME_MAX_LEN);
438 SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
439 smartlist_free(clients);
440 rend_service_free(service);
441 return -1;
443 if (strspn(client_name, REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
444 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
445 "illegal client name: '%s'. Valid "
446 "characters are [A-Za-z0-9+_-].",
447 client_name);
448 SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
449 smartlist_free(clients);
450 rend_service_free(service);
451 return -1;
453 client = tor_malloc_zero(sizeof(rend_authorized_client_t));
454 client->client_name = tor_strdup(client_name);
455 smartlist_add(service->clients, client);
456 log_debug(LD_REND, "Adding client name '%s'", client_name);
458 SMARTLIST_FOREACH_END(client_name);
459 SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
460 smartlist_free(clients);
461 /* Ensure maximum number of clients. */
462 if ((service->auth_type == REND_BASIC_AUTH &&
463 smartlist_len(service->clients) > 512) ||
464 (service->auth_type == REND_STEALTH_AUTH &&
465 smartlist_len(service->clients) > 16)) {
466 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
467 "client authorization entries, but only a "
468 "maximum of %d entries is allowed for "
469 "authorization type '%s'.",
470 smartlist_len(service->clients),
471 service->auth_type == REND_BASIC_AUTH ? 512 : 16,
472 service->auth_type == REND_BASIC_AUTH ? "basic" : "stealth");
473 rend_service_free(service);
474 return -1;
476 } else {
477 tor_assert(!strcasecmp(line->key, "HiddenServiceVersion"));
478 if (strcmp(line->value, "2")) {
479 log_warn(LD_CONFIG,
480 "The only supported HiddenServiceVersion is 2.");
481 rend_service_free(service);
482 return -1;
486 if (service) {
487 if (validate_only)
488 rend_service_free(service);
489 else
490 rend_add_service(service);
493 /* If this is a reload and there were hidden services configured before,
494 * keep the introduction points that are still needed and close the
495 * other ones. */
496 if (old_service_list && !validate_only) {
497 smartlist_t *surviving_services = smartlist_new();
498 circuit_t *circ;
500 /* Copy introduction points to new services. */
501 /* XXXX This is O(n^2), but it's only called on reconfigure, so it's
502 * probably ok? */
503 SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, new) {
504 SMARTLIST_FOREACH_BEGIN(old_service_list, rend_service_t *, old) {
505 if (!strcmp(old->directory, new->directory)) {
506 smartlist_add_all(new->intro_nodes, old->intro_nodes);
507 smartlist_clear(old->intro_nodes);
508 smartlist_add(surviving_services, old);
509 break;
511 } SMARTLIST_FOREACH_END(old);
512 } SMARTLIST_FOREACH_END(new);
514 /* Close introduction circuits of services we don't serve anymore. */
515 /* XXXX it would be nicer if we had a nicer abstraction to use here,
516 * so we could just iterate over the list of services to close, but
517 * once again, this isn't critical-path code. */
518 for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
519 if (!circ->marked_for_close &&
520 circ->state == CIRCUIT_STATE_OPEN &&
521 (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
522 circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
523 origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
524 int keep_it = 0;
525 tor_assert(oc->rend_data);
526 SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, {
527 if (tor_memeq(ptr->pk_digest, oc->rend_data->rend_pk_digest,
528 DIGEST_LEN)) {
529 keep_it = 1;
530 break;
533 if (keep_it)
534 continue;
535 log_info(LD_REND, "Closing intro point %s for service %s.",
536 safe_str_client(extend_info_describe(
537 oc->build_state->chosen_exit)),
538 oc->rend_data->onion_address);
539 circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
540 /* XXXX Is there another reason we should use here? */
543 smartlist_free(surviving_services);
544 SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr,
545 rend_service_free(ptr));
546 smartlist_free(old_service_list);
549 return 0;
552 /** Replace the old value of <b>service</b>-\>desc with one that reflects
553 * the other fields in service.
555 static void
556 rend_service_update_descriptor(rend_service_t *service)
558 rend_service_descriptor_t *d;
559 origin_circuit_t *circ;
560 int i;
562 rend_service_descriptor_free(service->desc);
563 service->desc = NULL;
565 d = service->desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
566 d->pk = crypto_pk_dup_key(service->private_key);
567 d->timestamp = time(NULL);
568 d->intro_nodes = smartlist_new();
569 /* Support intro protocols 2 and 3. */
570 d->protocols = (1 << 2) + (1 << 3);
572 for (i = 0; i < smartlist_len(service->intro_nodes); ++i) {
573 rend_intro_point_t *intro_svc = smartlist_get(service->intro_nodes, i);
574 rend_intro_point_t *intro_desc;
576 /* This intro point won't be listed in the descriptor... */
577 intro_svc->listed_in_last_desc = 0;
579 if (intro_svc->time_expiring != -1) {
580 /* This intro point is expiring. Don't list it. */
581 continue;
584 circ = find_intro_circuit(intro_svc, service->pk_digest);
585 if (!circ || circ->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) {
586 /* This intro point's circuit isn't finished yet. Don't list it. */
587 continue;
590 /* ...unless this intro point is listed in the descriptor. */
591 intro_svc->listed_in_last_desc = 1;
593 /* We have an entirely established intro circuit. Publish it in
594 * our descriptor. */
595 intro_desc = tor_malloc_zero(sizeof(rend_intro_point_t));
596 intro_desc->extend_info = extend_info_dup(intro_svc->extend_info);
597 if (intro_svc->intro_key)
598 intro_desc->intro_key = crypto_pk_dup_key(intro_svc->intro_key);
599 smartlist_add(d->intro_nodes, intro_desc);
601 if (intro_svc->time_published == -1) {
602 /* We are publishing this intro point in a descriptor for the
603 * first time -- note the current time in the service's copy of
604 * the intro point. */
605 intro_svc->time_published = time(NULL);
610 /** Load and/or generate private keys for all hidden services, possibly
611 * including keys for client authorization. Return 0 on success, -1 on
612 * failure.
615 rend_service_load_keys(void)
617 int r = 0;
618 char fname[512];
619 char buf[1500];
621 SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, s) {
622 if (s->private_key)
623 continue;
624 log_info(LD_REND, "Loading hidden-service keys from \"%s\"",
625 s->directory);
627 /* Check/create directory */
628 if (check_private_dir(s->directory, CPD_CREATE, get_options()->User) < 0)
629 return -1;
631 /* Load key */
632 if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
633 strlcat(fname,PATH_SEPARATOR"private_key",sizeof(fname))
634 >= sizeof(fname)) {
635 log_warn(LD_CONFIG, "Directory name too long to store key file: \"%s\".",
636 s->directory);
637 return -1;
639 s->private_key = init_key_from_file(fname, 1, LOG_ERR);
640 if (!s->private_key)
641 return -1;
643 /* Create service file */
644 if (rend_get_service_id(s->private_key, s->service_id)<0) {
645 log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
646 return -1;
648 if (crypto_pk_get_digest(s->private_key, s->pk_digest)<0) {
649 log_warn(LD_BUG, "Couldn't compute hash of public key.");
650 return -1;
652 if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
653 strlcat(fname,PATH_SEPARATOR"hostname",sizeof(fname))
654 >= sizeof(fname)) {
655 log_warn(LD_CONFIG, "Directory name too long to store hostname file:"
656 " \"%s\".", s->directory);
657 return -1;
659 tor_snprintf(buf, sizeof(buf),"%s.onion\n", s->service_id);
660 if (write_str_to_file(fname,buf,0)<0) {
661 log_warn(LD_CONFIG, "Could not write onion address to hostname file.");
662 return -1;
665 /* If client authorization is configured, load or generate keys. */
666 if (s->auth_type != REND_NO_AUTH) {
667 char *client_keys_str = NULL;
668 strmap_t *parsed_clients = strmap_new();
669 char cfname[512];
670 FILE *cfile, *hfile;
671 open_file_t *open_cfile = NULL, *open_hfile = NULL;
673 /* Load client keys and descriptor cookies, if available. */
674 if (tor_snprintf(cfname, sizeof(cfname), "%s"PATH_SEPARATOR"client_keys",
675 s->directory)<0) {
676 log_warn(LD_CONFIG, "Directory name too long to store client keys "
677 "file: \"%s\".", s->directory);
678 goto err;
680 client_keys_str = read_file_to_str(cfname, RFTS_IGNORE_MISSING, NULL);
681 if (client_keys_str) {
682 if (rend_parse_client_keys(parsed_clients, client_keys_str) < 0) {
683 log_warn(LD_CONFIG, "Previously stored client_keys file could not "
684 "be parsed.");
685 goto err;
686 } else {
687 log_info(LD_CONFIG, "Parsed %d previously stored client entries.",
688 strmap_size(parsed_clients));
689 tor_free(client_keys_str);
693 /* Prepare client_keys and hostname files. */
694 if (!(cfile = start_writing_to_stdio_file(cfname,
695 OPEN_FLAGS_REPLACE | O_TEXT,
696 0600, &open_cfile))) {
697 log_warn(LD_CONFIG, "Could not open client_keys file %s",
698 escaped(cfname));
699 goto err;
701 if (!(hfile = start_writing_to_stdio_file(fname,
702 OPEN_FLAGS_REPLACE | O_TEXT,
703 0600, &open_hfile))) {
704 log_warn(LD_CONFIG, "Could not open hostname file %s", escaped(fname));
705 goto err;
708 /* Either use loaded keys for configured clients or generate new
709 * ones if a client is new. */
710 SMARTLIST_FOREACH_BEGIN(s->clients, rend_authorized_client_t *, client)
712 char desc_cook_out[3*REND_DESC_COOKIE_LEN_BASE64+1];
713 char service_id[16+1];
714 rend_authorized_client_t *parsed =
715 strmap_get(parsed_clients, client->client_name);
716 int written;
717 size_t len;
718 /* Copy descriptor cookie from parsed entry or create new one. */
719 if (parsed) {
720 memcpy(client->descriptor_cookie, parsed->descriptor_cookie,
721 REND_DESC_COOKIE_LEN);
722 } else {
723 crypto_rand(client->descriptor_cookie, REND_DESC_COOKIE_LEN);
725 if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
726 client->descriptor_cookie,
727 REND_DESC_COOKIE_LEN) < 0) {
728 log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
729 strmap_free(parsed_clients, rend_authorized_client_strmap_item_free);
730 return -1;
732 /* Copy client key from parsed entry or create new one if required. */
733 if (parsed && parsed->client_key) {
734 client->client_key = crypto_pk_dup_key(parsed->client_key);
735 } else if (s->auth_type == REND_STEALTH_AUTH) {
736 /* Create private key for client. */
737 crypto_pk_t *prkey = NULL;
738 if (!(prkey = crypto_pk_new())) {
739 log_warn(LD_BUG,"Error constructing client key");
740 goto err;
742 if (crypto_pk_generate_key(prkey)) {
743 log_warn(LD_BUG,"Error generating client key");
744 crypto_pk_free(prkey);
745 goto err;
747 if (crypto_pk_check_key(prkey) <= 0) {
748 log_warn(LD_BUG,"Generated client key seems invalid");
749 crypto_pk_free(prkey);
750 goto err;
752 client->client_key = prkey;
754 /* Add entry to client_keys file. */
755 desc_cook_out[strlen(desc_cook_out)-1] = '\0'; /* Remove newline. */
756 written = tor_snprintf(buf, sizeof(buf),
757 "client-name %s\ndescriptor-cookie %s\n",
758 client->client_name, desc_cook_out);
759 if (written < 0) {
760 log_warn(LD_BUG, "Could not write client entry.");
761 goto err;
763 if (client->client_key) {
764 char *client_key_out = NULL;
765 crypto_pk_write_private_key_to_string(client->client_key,
766 &client_key_out, &len);
767 if (rend_get_service_id(client->client_key, service_id)<0) {
768 log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
769 tor_free(client_key_out);
770 goto err;
772 written = tor_snprintf(buf + written, sizeof(buf) - written,
773 "client-key\n%s", client_key_out);
774 tor_free(client_key_out);
775 if (written < 0) {
776 log_warn(LD_BUG, "Could not write client entry.");
777 goto err;
781 if (fputs(buf, cfile) < 0) {
782 log_warn(LD_FS, "Could not append client entry to file: %s",
783 strerror(errno));
784 goto err;
787 /* Add line to hostname file. */
788 if (s->auth_type == REND_BASIC_AUTH) {
789 /* Remove == signs (newline has been removed above). */
790 desc_cook_out[strlen(desc_cook_out)-2] = '\0';
791 tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
792 s->service_id, desc_cook_out, client->client_name);
793 } else {
794 char extended_desc_cookie[REND_DESC_COOKIE_LEN+1];
795 memcpy(extended_desc_cookie, client->descriptor_cookie,
796 REND_DESC_COOKIE_LEN);
797 extended_desc_cookie[REND_DESC_COOKIE_LEN] =
798 ((int)s->auth_type - 1) << 4;
799 if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
800 extended_desc_cookie,
801 REND_DESC_COOKIE_LEN+1) < 0) {
802 log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
803 goto err;
805 desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove A= and
806 newline. */
807 tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
808 service_id, desc_cook_out, client->client_name);
811 if (fputs(buf, hfile)<0) {
812 log_warn(LD_FS, "Could not append host entry to file: %s",
813 strerror(errno));
814 goto err;
817 SMARTLIST_FOREACH_END(client);
819 goto done;
820 err:
821 r = -1;
822 done:
823 tor_free(client_keys_str);
824 strmap_free(parsed_clients, rend_authorized_client_strmap_item_free);
825 if (r<0) {
826 if (open_cfile)
827 abort_writing_to_file(open_cfile);
828 if (open_hfile)
829 abort_writing_to_file(open_hfile);
830 return r;
831 } else {
832 finish_writing_to_file(open_cfile);
833 finish_writing_to_file(open_hfile);
836 } SMARTLIST_FOREACH_END(s);
837 return r;
840 /** Return the service whose public key has a digest of <b>digest</b>, or
841 * NULL if no such service exists.
843 static rend_service_t *
844 rend_service_get_by_pk_digest(const char* digest)
846 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s,
847 if (tor_memeq(s->pk_digest,digest,DIGEST_LEN))
848 return s);
849 return NULL;
852 /** Return 1 if any virtual port in <b>service</b> wants a circuit
853 * to have good uptime. Else return 0.
855 static int
856 rend_service_requires_uptime(rend_service_t *service)
858 int i;
859 rend_service_port_config_t *p;
861 for (i=0; i < smartlist_len(service->ports); ++i) {
862 p = smartlist_get(service->ports, i);
863 if (smartlist_string_num_isin(get_options()->LongLivedPorts,
864 p->virtual_port))
865 return 1;
867 return 0;
870 /** Check client authorization of a given <b>descriptor_cookie</b> for
871 * <b>service</b>. Return 1 for success and 0 for failure. */
872 static int
873 rend_check_authorization(rend_service_t *service,
874 const char *descriptor_cookie)
876 rend_authorized_client_t *auth_client = NULL;
877 tor_assert(service);
878 tor_assert(descriptor_cookie);
879 if (!service->clients) {
880 log_warn(LD_BUG, "Can't check authorization for a service that has no "
881 "authorized clients configured.");
882 return 0;
885 /* Look up client authorization by descriptor cookie. */
886 SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, client, {
887 if (tor_memeq(client->descriptor_cookie, descriptor_cookie,
888 REND_DESC_COOKIE_LEN)) {
889 auth_client = client;
890 break;
893 if (!auth_client) {
894 char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64];
895 base64_encode(descriptor_cookie_base64, sizeof(descriptor_cookie_base64),
896 descriptor_cookie, REND_DESC_COOKIE_LEN);
897 log_info(LD_REND, "No authorization found for descriptor cookie '%s'! "
898 "Dropping cell!",
899 descriptor_cookie_base64);
900 return 0;
903 /* Allow the request. */
904 log_debug(LD_REND, "Client %s authorized for service %s.",
905 auth_client->client_name, service->service_id);
906 return 1;
909 /** Remove elements from <b>service</b>'s replay cache that are old enough to
910 * be noticed by timestamp checking. */
911 static void
912 clean_accepted_intro_dh_parts(rend_service_t *service, time_t now)
914 const time_t cutoff = now - REND_REPLAY_TIME_INTERVAL;
916 service->last_cleaned_accepted_intro_dh_parts = now;
917 if (!service->accepted_intro_dh_parts)
918 return;
920 DIGESTMAP_FOREACH_MODIFY(service->accepted_intro_dh_parts, digest,
921 time_t *, t) {
922 if (*t < cutoff) {
923 tor_free(t);
924 MAP_DEL_CURRENT(digest);
926 } DIGESTMAP_FOREACH_END;
929 /** Called when <b>intro</b> will soon be removed from
930 * <b>service</b>'s list of intro points. */
931 static void
932 rend_service_note_removing_intro_point(rend_service_t *service,
933 rend_intro_point_t *intro)
935 time_t now = time(NULL);
937 /* Don't process an intro point twice here. */
938 if (intro->rend_service_note_removing_intro_point_called) {
939 return;
940 } else {
941 intro->rend_service_note_removing_intro_point_called = 1;
944 /* Update service->n_intro_points_wanted based on how long intro
945 * lasted and how many introductions it handled. */
946 if (intro->time_published == -1) {
947 /* This intro point was never used. Don't change
948 * n_intro_points_wanted. */
949 } else {
950 /* We want to increase the number of introduction points service
951 * operates if intro was heavily used, or decrease the number of
952 * intro points if intro was lightly used.
954 * We consider an intro point's target 'usage' to be
955 * INTRO_POINT_LIFETIME_INTRODUCTIONS introductions in
956 * INTRO_POINT_LIFETIME_MIN_SECONDS seconds. To calculate intro's
957 * fraction of target usage, we divide the fraction of
958 * _LIFETIME_INTRODUCTIONS introductions that it has handled by
959 * the fraction of _LIFETIME_MIN_SECONDS for which it existed.
961 * Then we multiply that fraction of desired usage by a fudge
962 * factor of 1.5, to decide how many new introduction points
963 * should ideally replace intro (which is now closed or soon to be
964 * closed). In theory, assuming that introduction load is
965 * distributed equally across all intro points and ignoring the
966 * fact that different intro points are established and closed at
967 * different times, that number of intro points should bring all
968 * of our intro points exactly to our target usage.
970 * Then we clamp that number to a number of intro points we might
971 * be willing to replace this intro point with and turn it into an
972 * integer. then we clamp it again to the number of new intro
973 * points we could establish now, then we adjust
974 * service->n_intro_points_wanted and let rend_services_introduce
975 * create the new intro points we want (if any).
977 const double intro_point_usage =
978 intro_point_accepted_intro_count(intro) /
979 (double)(now - intro->time_published);
980 const double intro_point_target_usage =
981 INTRO_POINT_LIFETIME_INTRODUCTIONS /
982 (double)INTRO_POINT_LIFETIME_MIN_SECONDS;
983 const double fractional_n_intro_points_wanted_to_replace_this_one =
984 (1.5 * (intro_point_usage / intro_point_target_usage));
985 unsigned int n_intro_points_wanted_to_replace_this_one;
986 unsigned int n_intro_points_wanted_now;
987 unsigned int n_intro_points_really_wanted_now;
988 int n_intro_points_really_replacing_this_one;
990 if (fractional_n_intro_points_wanted_to_replace_this_one >
991 NUM_INTRO_POINTS_MAX) {
992 n_intro_points_wanted_to_replace_this_one = NUM_INTRO_POINTS_MAX;
993 } else if (fractional_n_intro_points_wanted_to_replace_this_one < 0) {
994 n_intro_points_wanted_to_replace_this_one = 0;
995 } else {
996 n_intro_points_wanted_to_replace_this_one = (unsigned)
997 fractional_n_intro_points_wanted_to_replace_this_one;
1000 n_intro_points_wanted_now =
1001 service->n_intro_points_wanted +
1002 n_intro_points_wanted_to_replace_this_one - 1;
1004 if (n_intro_points_wanted_now < NUM_INTRO_POINTS_DEFAULT) {
1005 /* XXXX This should be NUM_INTRO_POINTS_MIN instead. Perhaps
1006 * another use of NUM_INTRO_POINTS_DEFAULT should be, too. */
1007 n_intro_points_really_wanted_now = NUM_INTRO_POINTS_DEFAULT;
1008 } else if (n_intro_points_wanted_now > NUM_INTRO_POINTS_MAX) {
1009 n_intro_points_really_wanted_now = NUM_INTRO_POINTS_MAX;
1010 } else {
1011 n_intro_points_really_wanted_now = n_intro_points_wanted_now;
1014 n_intro_points_really_replacing_this_one =
1015 n_intro_points_really_wanted_now - service->n_intro_points_wanted + 1;
1017 log_info(LD_REND, "Replacing closing intro point for service %s "
1018 "with %d new intro points (wanted %g replacements); "
1019 "service will now try to have %u intro points",
1020 rend_service_describe_for_log(service),
1021 n_intro_points_really_replacing_this_one,
1022 fractional_n_intro_points_wanted_to_replace_this_one,
1023 n_intro_points_really_wanted_now);
1025 service->n_intro_points_wanted = n_intro_points_really_wanted_now;
1029 /******
1030 * Handle cells
1031 ******/
1033 /** Respond to an INTRODUCE2 cell by launching a circuit to the chosen
1034 * rendezvous point.
1036 /* XXXX024 this function sure could use some organizing. -RD */
1038 rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
1039 size_t request_len)
1041 char *ptr, *r_cookie;
1042 extend_info_t *extend_info = NULL;
1043 char buf[RELAY_PAYLOAD_SIZE];
1044 char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */
1045 rend_service_t *service;
1046 rend_intro_point_t *intro_point;
1047 int r, i, v3_shift = 0;
1048 size_t len, keylen;
1049 crypto_dh_t *dh = NULL;
1050 origin_circuit_t *launched = NULL;
1051 crypt_path_t *cpath = NULL;
1052 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
1053 char hexcookie[9];
1054 int circ_needs_uptime;
1055 int reason = END_CIRC_REASON_TORPROTOCOL;
1056 crypto_pk_t *intro_key;
1057 char intro_key_digest[DIGEST_LEN];
1058 int auth_type;
1059 size_t auth_len = 0;
1060 char auth_data[REND_DESC_COOKIE_LEN];
1061 crypto_digest_t *digest = NULL;
1062 time_t now = time(NULL);
1063 char diffie_hellman_hash[DIGEST_LEN];
1064 time_t *access_time;
1065 const or_options_t *options = get_options();
1067 if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) {
1068 log_warn(LD_PROTOCOL,
1069 "Got an INTRODUCE2 over a non-introduction circuit %d.",
1070 circuit->_base.n_circ_id);
1071 return -1;
1074 #ifndef NON_ANONYMOUS_MODE_ENABLED
1075 tor_assert(!(circuit->build_state->onehop_tunnel));
1076 #endif
1077 tor_assert(circuit->rend_data);
1079 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
1080 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
1081 log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %d.",
1082 escaped(serviceid), circuit->_base.n_circ_id);
1084 /* min key length plus digest length plus nickname length */
1085 if (request_len < DIGEST_LEN+REND_COOKIE_LEN+(MAX_NICKNAME_LEN+1)+
1086 DH_KEY_LEN+42) {
1087 log_warn(LD_PROTOCOL, "Got a truncated INTRODUCE2 cell on circ %d.",
1088 circuit->_base.n_circ_id);
1089 return -1;
1092 /* look up service depending on circuit. */
1093 service = rend_service_get_by_pk_digest(
1094 circuit->rend_data->rend_pk_digest);
1095 if (!service) {
1096 log_warn(LD_BUG, "Internal error: Got an INTRODUCE2 cell on an intro "
1097 "circ for an unrecognized service %s.",
1098 escaped(serviceid));
1099 return -1;
1102 /* use intro key instead of service key. */
1103 intro_key = circuit->intro_key;
1105 /* first DIGEST_LEN bytes of request is intro or service pk digest */
1106 crypto_pk_get_digest(intro_key, intro_key_digest);
1107 if (tor_memneq(intro_key_digest, request, DIGEST_LEN)) {
1108 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
1109 (char*)request, REND_SERVICE_ID_LEN);
1110 log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).",
1111 escaped(serviceid));
1112 return -1;
1115 keylen = crypto_pk_keysize(intro_key);
1116 if (request_len < keylen+DIGEST_LEN) {
1117 log_warn(LD_PROTOCOL,
1118 "PK-encrypted portion of INTRODUCE2 cell was truncated.");
1119 return -1;
1122 intro_point = find_intro_point(circuit);
1123 if (intro_point == NULL) {
1124 log_warn(LD_BUG, "Internal error: Got an INTRODUCE2 cell on an intro circ "
1125 "(for service %s) with no corresponding rend_intro_point_t.",
1126 escaped(serviceid));
1127 return -1;
1130 if (!service->accepted_intro_dh_parts)
1131 service->accepted_intro_dh_parts = digestmap_new();
1133 if (!intro_point->accepted_intro_rsa_parts)
1134 intro_point->accepted_intro_rsa_parts = digestmap_new();
1137 char pkpart_digest[DIGEST_LEN];
1138 /* Check for replay of PK-encrypted portion. */
1139 crypto_digest(pkpart_digest, (char*)request+DIGEST_LEN, keylen);
1140 access_time = digestmap_get(intro_point->accepted_intro_rsa_parts,
1141 pkpart_digest);
1142 if (access_time != NULL) {
1143 log_warn(LD_REND, "Possible replay detected! We received an "
1144 "INTRODUCE2 cell with same PK-encrypted part %d seconds ago. "
1145 "Dropping cell.", (int)(now-*access_time));
1146 return -1;
1148 access_time = tor_malloc(sizeof(time_t));
1149 *access_time = now;
1150 digestmap_set(intro_point->accepted_intro_rsa_parts,
1151 pkpart_digest, access_time);
1154 /* Next N bytes is encrypted with service key */
1155 note_crypto_pk_op(REND_SERVER);
1156 r = crypto_pk_private_hybrid_decrypt(
1157 intro_key,buf,sizeof(buf),
1158 (char*)(request+DIGEST_LEN),request_len-DIGEST_LEN,
1159 PK_PKCS1_OAEP_PADDING,1);
1160 if (r<0) {
1161 log_warn(LD_PROTOCOL, "Couldn't decrypt INTRODUCE2 cell.");
1162 return -1;
1164 len = r;
1165 if (*buf == 3) {
1166 /* Version 3 INTRODUCE2 cell. */
1167 v3_shift = 1;
1168 auth_type = buf[1];
1169 switch (auth_type) {
1170 case REND_BASIC_AUTH:
1171 /* fall through */
1172 case REND_STEALTH_AUTH:
1173 auth_len = ntohs(get_uint16(buf+2));
1174 if (auth_len != REND_DESC_COOKIE_LEN) {
1175 log_info(LD_REND, "Wrong auth data size %d, should be %d.",
1176 (int)auth_len, REND_DESC_COOKIE_LEN);
1177 return -1;
1179 memcpy(auth_data, buf+4, sizeof(auth_data));
1180 v3_shift += 2+REND_DESC_COOKIE_LEN;
1181 break;
1182 case REND_NO_AUTH:
1183 break;
1184 default:
1185 log_info(LD_REND, "Unknown authorization type '%d'", auth_type);
1188 /* Skip the timestamp field. We no longer use it. */
1189 v3_shift += 4;
1191 if (*buf == 2 || *buf == 3) {
1192 /* Version 2 INTRODUCE2 cell. */
1193 int klen;
1194 extend_info = tor_malloc_zero(sizeof(extend_info_t));
1195 tor_addr_from_ipv4n(&extend_info->addr, get_uint32(buf+v3_shift+1));
1196 extend_info->port = ntohs(get_uint16(buf+v3_shift+5));
1197 memcpy(extend_info->identity_digest, buf+v3_shift+7,
1198 DIGEST_LEN);
1199 extend_info->nickname[0] = '$';
1200 base16_encode(extend_info->nickname+1, sizeof(extend_info->nickname)-1,
1201 extend_info->identity_digest, DIGEST_LEN);
1203 klen = ntohs(get_uint16(buf+v3_shift+7+DIGEST_LEN));
1204 if ((int)len != v3_shift+7+DIGEST_LEN+2+klen+20+128) {
1205 log_warn(LD_PROTOCOL, "Bad length %u for version %d INTRODUCE2 cell.",
1206 (int)len, *buf);
1207 reason = END_CIRC_REASON_TORPROTOCOL;
1208 goto err;
1210 extend_info->onion_key =
1211 crypto_pk_asn1_decode(buf+v3_shift+7+DIGEST_LEN+2, klen);
1212 if (!extend_info->onion_key) {
1213 log_warn(LD_PROTOCOL, "Error decoding onion key in version %d "
1214 "INTRODUCE2 cell.", *buf);
1215 reason = END_CIRC_REASON_TORPROTOCOL;
1216 goto err;
1218 ptr = buf+v3_shift+7+DIGEST_LEN+2+klen;
1219 len -= v3_shift+7+DIGEST_LEN+2+klen;
1220 } else {
1221 char *rp_nickname;
1222 size_t nickname_field_len;
1223 const node_t *node;
1224 int version;
1225 if (*buf == 1) {
1226 rp_nickname = buf+1;
1227 nickname_field_len = MAX_HEX_NICKNAME_LEN+1;
1228 version = 1;
1229 } else {
1230 nickname_field_len = MAX_NICKNAME_LEN+1;
1231 rp_nickname = buf;
1232 version = 0;
1234 ptr=memchr(rp_nickname,0,nickname_field_len);
1235 if (!ptr || ptr == rp_nickname) {
1236 log_warn(LD_PROTOCOL,
1237 "Couldn't find a nul-padded nickname in INTRODUCE2 cell.");
1238 return -1;
1240 if ((version == 0 && !is_legal_nickname(rp_nickname)) ||
1241 (version == 1 && !is_legal_nickname_or_hexdigest(rp_nickname))) {
1242 log_warn(LD_PROTOCOL, "Bad nickname in INTRODUCE2 cell.");
1243 return -1;
1245 /* Okay, now we know that a nickname is at the start of the buffer. */
1246 ptr = rp_nickname+nickname_field_len;
1247 len -= nickname_field_len;
1248 len -= rp_nickname - buf; /* also remove header space used by version, if
1249 * any */
1250 node = node_get_by_nickname(rp_nickname, 0);
1251 if (!node) {
1252 log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
1253 escaped_safe_str_client(rp_nickname));
1254 /* XXXX Add a no-such-router reason? */
1255 reason = END_CIRC_REASON_TORPROTOCOL;
1256 goto err;
1259 extend_info = extend_info_from_node(node, 0);
1262 if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
1263 log_warn(LD_PROTOCOL, "Bad length %u for INTRODUCE2 cell.", (int)len);
1264 reason = END_CIRC_REASON_TORPROTOCOL;
1265 goto err;
1268 /* Check if we'd refuse to talk to this router */
1269 if (options->StrictNodes &&
1270 routerset_contains_extendinfo(options->ExcludeNodes, extend_info)) {
1271 log_warn(LD_REND, "Client asked to rendezvous at a relay that we "
1272 "exclude, and StrictNodes is set. Refusing service.");
1273 reason = END_CIRC_REASON_INTERNAL; /* XXX might leak why we refused */
1274 goto err;
1277 r_cookie = ptr;
1278 base16_encode(hexcookie,9,r_cookie,4);
1280 /* Determine hash of Diffie-Hellman, part 1 to detect replays. */
1281 digest = crypto_digest_new();
1282 crypto_digest_add_bytes(digest, ptr+REND_COOKIE_LEN, DH_KEY_LEN);
1283 crypto_digest_get_digest(digest, diffie_hellman_hash, DIGEST_LEN);
1284 crypto_digest_free(digest);
1286 /* Check whether there is a past request with the same Diffie-Hellman,
1287 * part 1. */
1288 access_time = digestmap_get(service->accepted_intro_dh_parts,
1289 diffie_hellman_hash);
1290 if (access_time != NULL) {
1291 /* A Tor client will send a new INTRODUCE1 cell with the same rend
1292 * cookie and DH public key as its previous one if its intro circ
1293 * times out while in state CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT .
1294 * If we received the first INTRODUCE1 cell (the intro-point relay
1295 * converts it into an INTRODUCE2 cell), we are already trying to
1296 * connect to that rend point (and may have already succeeded);
1297 * drop this cell. */
1298 log_info(LD_REND, "We received an "
1299 "INTRODUCE2 cell with same first part of "
1300 "Diffie-Hellman handshake %d seconds ago. Dropping "
1301 "cell.",
1302 (int) (now - *access_time));
1303 goto err;
1306 /* Add request to access history, including time and hash of Diffie-Hellman,
1307 * part 1, and possibly remove requests from the history that are older than
1308 * one hour. */
1309 access_time = tor_malloc(sizeof(time_t));
1310 *access_time = now;
1311 digestmap_set(service->accepted_intro_dh_parts,
1312 diffie_hellman_hash, access_time);
1313 if (service->last_cleaned_accepted_intro_dh_parts + REND_REPLAY_TIME_INTERVAL
1314 < now)
1315 clean_accepted_intro_dh_parts(service, now);
1317 /* If the service performs client authorization, check included auth data. */
1318 if (service->clients) {
1319 if (auth_len > 0) {
1320 if (rend_check_authorization(service, auth_data)) {
1321 log_info(LD_REND, "Authorization data in INTRODUCE2 cell are valid.");
1322 } else {
1323 log_info(LD_REND, "The authorization data that are contained in "
1324 "the INTRODUCE2 cell are invalid. Dropping cell.");
1325 reason = END_CIRC_REASON_CONNECTFAILED;
1326 goto err;
1328 } else {
1329 log_info(LD_REND, "INTRODUCE2 cell does not contain authentication "
1330 "data, but we require client authorization. Dropping cell.");
1331 reason = END_CIRC_REASON_CONNECTFAILED;
1332 goto err;
1336 /* Try DH handshake... */
1337 dh = crypto_dh_new(DH_TYPE_REND);
1338 if (!dh || crypto_dh_generate_public(dh)<0) {
1339 log_warn(LD_BUG,"Internal error: couldn't build DH state "
1340 "or generate public key.");
1341 reason = END_CIRC_REASON_INTERNAL;
1342 goto err;
1344 if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, ptr+REND_COOKIE_LEN,
1345 DH_KEY_LEN, keys,
1346 DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
1347 log_warn(LD_BUG, "Internal error: couldn't complete DH handshake");
1348 reason = END_CIRC_REASON_INTERNAL;
1349 goto err;
1352 circ_needs_uptime = rend_service_requires_uptime(service);
1354 /* help predict this next time */
1355 rep_hist_note_used_internal(now, circ_needs_uptime, 1);
1357 /* Launch a circuit to alice's chosen rendezvous point.
1359 for (i=0;i<MAX_REND_FAILURES;i++) {
1360 int flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL;
1361 if (circ_needs_uptime) flags |= CIRCLAUNCH_NEED_UPTIME;
1362 launched = circuit_launch_by_extend_info(
1363 CIRCUIT_PURPOSE_S_CONNECT_REND, extend_info, flags);
1365 if (launched)
1366 break;
1368 if (!launched) { /* give up */
1369 log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous "
1370 "point %s for service %s.",
1371 safe_str_client(extend_info_describe(extend_info)),
1372 serviceid);
1373 reason = END_CIRC_REASON_CONNECTFAILED;
1374 goto err;
1376 log_info(LD_REND,
1377 "Accepted intro; launching circuit to %s "
1378 "(cookie %s) for service %s.",
1379 safe_str_client(extend_info_describe(extend_info)),
1380 hexcookie, serviceid);
1381 tor_assert(launched->build_state);
1382 /* Fill in the circuit's state. */
1383 launched->rend_data = tor_malloc_zero(sizeof(rend_data_t));
1384 memcpy(launched->rend_data->rend_pk_digest,
1385 circuit->rend_data->rend_pk_digest,
1386 DIGEST_LEN);
1387 memcpy(launched->rend_data->rend_cookie, r_cookie, REND_COOKIE_LEN);
1388 strlcpy(launched->rend_data->onion_address, service->service_id,
1389 sizeof(launched->rend_data->onion_address));
1391 launched->build_state->service_pending_final_cpath_ref =
1392 tor_malloc_zero(sizeof(crypt_path_reference_t));
1393 launched->build_state->service_pending_final_cpath_ref->refcount = 1;
1395 launched->build_state->service_pending_final_cpath_ref->cpath = cpath =
1396 tor_malloc_zero(sizeof(crypt_path_t));
1397 cpath->magic = CRYPT_PATH_MAGIC;
1398 launched->build_state->expiry_time = now + MAX_REND_TIMEOUT;
1400 cpath->dh_handshake_state = dh;
1401 dh = NULL;
1402 if (circuit_init_cpath_crypto(cpath,keys+DIGEST_LEN,1)<0)
1403 goto err;
1404 memcpy(cpath->handshake_digest, keys, DIGEST_LEN);
1405 if (extend_info) extend_info_free(extend_info);
1407 memset(keys, 0, sizeof(keys));
1408 return 0;
1409 err:
1410 memset(keys, 0, sizeof(keys));
1411 if (dh) crypto_dh_free(dh);
1412 if (launched)
1413 circuit_mark_for_close(TO_CIRCUIT(launched), reason);
1414 if (extend_info) extend_info_free(extend_info);
1415 return -1;
1418 /** Called when we fail building a rendezvous circuit at some point other
1419 * than the last hop: launches a new circuit to the same rendezvous point.
1421 void
1422 rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
1424 origin_circuit_t *newcirc;
1425 cpath_build_state_t *newstate, *oldstate;
1427 tor_assert(oldcirc->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
1429 /* Don't relaunch the same rend circ twice. */
1430 if (oldcirc->hs_service_side_rend_circ_has_been_relaunched) {
1431 log_info(LD_REND, "Rendezvous circuit to %s has already been relaunched; "
1432 "not relaunching it again.",
1433 oldcirc->build_state ?
1434 safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
1435 : "*unknown*");
1436 return;
1438 oldcirc->hs_service_side_rend_circ_has_been_relaunched = 1;
1440 if (!oldcirc->build_state ||
1441 oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
1442 oldcirc->build_state->expiry_time < time(NULL)) {
1443 log_info(LD_REND,
1444 "Attempt to build circuit to %s for rendezvous has failed "
1445 "too many times or expired; giving up.",
1446 oldcirc->build_state ?
1447 safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
1448 : "*unknown*");
1449 return;
1452 oldstate = oldcirc->build_state;
1453 tor_assert(oldstate);
1455 if (oldstate->service_pending_final_cpath_ref == NULL) {
1456 log_info(LD_REND,"Skipping relaunch of circ that failed on its first hop. "
1457 "Initiator will retry.");
1458 return;
1461 log_info(LD_REND,"Reattempting rendezvous circuit to '%s'",
1462 safe_str(extend_info_describe(oldstate->chosen_exit)));
1464 newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
1465 oldstate->chosen_exit,
1466 CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
1468 if (!newcirc) {
1469 log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.",
1470 safe_str(extend_info_describe(oldstate->chosen_exit)));
1471 return;
1473 newstate = newcirc->build_state;
1474 tor_assert(newstate);
1475 newstate->failure_count = oldstate->failure_count+1;
1476 newstate->expiry_time = oldstate->expiry_time;
1477 newstate->service_pending_final_cpath_ref =
1478 oldstate->service_pending_final_cpath_ref;
1479 ++(newstate->service_pending_final_cpath_ref->refcount);
1481 newcirc->rend_data = rend_data_dup(oldcirc->rend_data);
1484 /** Launch a circuit to serve as an introduction point for the service
1485 * <b>service</b> at the introduction point <b>nickname</b>
1487 static int
1488 rend_service_launch_establish_intro(rend_service_t *service,
1489 rend_intro_point_t *intro)
1491 origin_circuit_t *launched;
1493 log_info(LD_REND,
1494 "Launching circuit to introduction point %s for service %s",
1495 safe_str_client(extend_info_describe(intro->extend_info)),
1496 service->service_id);
1498 rep_hist_note_used_internal(time(NULL), 1, 0);
1500 ++service->n_intro_circuits_launched;
1501 launched = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
1502 intro->extend_info,
1503 CIRCLAUNCH_NEED_UPTIME|CIRCLAUNCH_IS_INTERNAL);
1505 if (!launched) {
1506 log_info(LD_REND,
1507 "Can't launch circuit to establish introduction at %s.",
1508 safe_str_client(extend_info_describe(intro->extend_info)));
1509 return -1;
1512 if (tor_memneq(intro->extend_info->identity_digest,
1513 launched->build_state->chosen_exit->identity_digest, DIGEST_LEN)) {
1514 char cann[HEX_DIGEST_LEN+1], orig[HEX_DIGEST_LEN+1];
1515 base16_encode(cann, sizeof(cann),
1516 launched->build_state->chosen_exit->identity_digest,
1517 DIGEST_LEN);
1518 base16_encode(orig, sizeof(orig),
1519 intro->extend_info->identity_digest, DIGEST_LEN);
1520 log_info(LD_REND, "The intro circuit we just cannibalized ends at $%s, "
1521 "but we requested an intro circuit to $%s. Updating "
1522 "our service.", cann, orig);
1523 extend_info_free(intro->extend_info);
1524 intro->extend_info = extend_info_dup(launched->build_state->chosen_exit);
1527 launched->rend_data = tor_malloc_zero(sizeof(rend_data_t));
1528 strlcpy(launched->rend_data->onion_address, service->service_id,
1529 sizeof(launched->rend_data->onion_address));
1530 memcpy(launched->rend_data->rend_pk_digest, service->pk_digest, DIGEST_LEN);
1531 launched->intro_key = crypto_pk_dup_key(intro->intro_key);
1532 if (launched->_base.state == CIRCUIT_STATE_OPEN)
1533 rend_service_intro_has_opened(launched);
1534 return 0;
1537 /** Return the number of introduction points that are or have been
1538 * established for the given service address in <b>query</b>. */
1539 static int
1540 count_established_intro_points(const char *query)
1542 int num_ipos = 0;
1543 circuit_t *circ;
1544 for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
1545 if (!circ->marked_for_close &&
1546 circ->state == CIRCUIT_STATE_OPEN &&
1547 (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
1548 circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
1549 origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
1550 if (oc->rend_data &&
1551 !rend_cmp_service_ids(query, oc->rend_data->onion_address))
1552 num_ipos++;
1555 return num_ipos;
1558 /** Called when we're done building a circuit to an introduction point:
1559 * sends a RELAY_ESTABLISH_INTRO cell.
1561 void
1562 rend_service_intro_has_opened(origin_circuit_t *circuit)
1564 rend_service_t *service;
1565 size_t len;
1566 int r;
1567 char buf[RELAY_PAYLOAD_SIZE];
1568 char auth[DIGEST_LEN + 9];
1569 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
1570 int reason = END_CIRC_REASON_TORPROTOCOL;
1571 crypto_pk_t *intro_key;
1573 tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
1574 #ifndef NON_ANONYMOUS_MODE_ENABLED
1575 tor_assert(!(circuit->build_state->onehop_tunnel));
1576 #endif
1577 tor_assert(circuit->cpath);
1578 tor_assert(circuit->rend_data);
1580 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
1581 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
1583 service = rend_service_get_by_pk_digest(
1584 circuit->rend_data->rend_pk_digest);
1585 if (!service) {
1586 log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.",
1587 serviceid, circuit->_base.n_circ_id);
1588 reason = END_CIRC_REASON_NOSUCHSERVICE;
1589 goto err;
1592 /* If we already have enough introduction circuits for this service,
1593 * redefine this one as a general circuit or close it, depending. */
1594 if (count_established_intro_points(serviceid) >
1595 (int)service->n_intro_points_wanted) { /* XXX023 remove cast */
1596 const or_options_t *options = get_options();
1597 if (options->ExcludeNodes) {
1598 /* XXXX in some future version, we can test whether the transition is
1599 allowed or not given the actual nodes in the circuit. But for now,
1600 this case, we might as well close the thing. */
1601 log_info(LD_CIRC|LD_REND, "We have just finished an introduction "
1602 "circuit, but we already have enough. Closing it.");
1603 circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_NONE);
1604 return;
1605 } else {
1606 tor_assert(circuit->build_state->is_internal);
1607 log_info(LD_CIRC|LD_REND, "We have just finished an introduction "
1608 "circuit, but we already have enough. Redefining purpose to "
1609 "general; leaving as internal.");
1611 circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_C_GENERAL);
1614 rend_data_t *rend_data = circuit->rend_data;
1615 circuit->rend_data = NULL;
1616 rend_data_free(rend_data);
1619 crypto_pk_t *intro_key = circuit->intro_key;
1620 circuit->intro_key = NULL;
1621 crypto_pk_free(intro_key);
1624 circuit_has_opened(circuit);
1625 return;
1629 log_info(LD_REND,
1630 "Established circuit %d as introduction point for service %s",
1631 circuit->_base.n_circ_id, serviceid);
1633 /* Use the intro key instead of the service key in ESTABLISH_INTRO. */
1634 intro_key = circuit->intro_key;
1635 /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
1636 r = crypto_pk_asn1_encode(intro_key, buf+2,
1637 RELAY_PAYLOAD_SIZE-2);
1638 if (r < 0) {
1639 log_warn(LD_BUG, "Internal error; failed to establish intro point.");
1640 reason = END_CIRC_REASON_INTERNAL;
1641 goto err;
1643 len = r;
1644 set_uint16(buf, htons((uint16_t)len));
1645 len += 2;
1646 memcpy(auth, circuit->cpath->prev->handshake_digest, DIGEST_LEN);
1647 memcpy(auth+DIGEST_LEN, "INTRODUCE", 9);
1648 if (crypto_digest(buf+len, auth, DIGEST_LEN+9))
1649 goto err;
1650 len += 20;
1651 note_crypto_pk_op(REND_SERVER);
1652 r = crypto_pk_private_sign_digest(intro_key, buf+len, sizeof(buf)-len,
1653 buf, len);
1654 if (r<0) {
1655 log_warn(LD_BUG, "Internal error: couldn't sign introduction request.");
1656 reason = END_CIRC_REASON_INTERNAL;
1657 goto err;
1659 len += r;
1661 if (relay_send_command_from_edge(0, TO_CIRCUIT(circuit),
1662 RELAY_COMMAND_ESTABLISH_INTRO,
1663 buf, len, circuit->cpath->prev)<0) {
1664 log_info(LD_GENERAL,
1665 "Couldn't send introduction request for service %s on circuit %d",
1666 serviceid, circuit->_base.n_circ_id);
1667 reason = END_CIRC_REASON_INTERNAL;
1668 goto err;
1671 return;
1672 err:
1673 circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
1676 /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
1677 * live introduction point, and note that the service descriptor is
1678 * now out-of-date. */
1680 rend_service_intro_established(origin_circuit_t *circuit,
1681 const uint8_t *request,
1682 size_t request_len)
1684 rend_service_t *service;
1685 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
1686 (void) request;
1687 (void) request_len;
1689 if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
1690 log_warn(LD_PROTOCOL,
1691 "received INTRO_ESTABLISHED cell on non-intro circuit.");
1692 goto err;
1694 tor_assert(circuit->rend_data);
1695 service = rend_service_get_by_pk_digest(
1696 circuit->rend_data->rend_pk_digest);
1697 if (!service) {
1698 log_warn(LD_REND, "Unknown service on introduction circuit %d.",
1699 circuit->_base.n_circ_id);
1700 goto err;
1702 service->desc_is_dirty = time(NULL);
1703 circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_INTRO);
1705 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32 + 1,
1706 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
1707 log_info(LD_REND,
1708 "Received INTRO_ESTABLISHED cell on circuit %d for service %s",
1709 circuit->_base.n_circ_id, serviceid);
1711 return 0;
1712 err:
1713 circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
1714 return -1;
1717 /** Called once a circuit to a rendezvous point is established: sends a
1718 * RELAY_COMMAND_RENDEZVOUS1 cell.
1720 void
1721 rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
1723 rend_service_t *service;
1724 char buf[RELAY_PAYLOAD_SIZE];
1725 crypt_path_t *hop;
1726 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
1727 char hexcookie[9];
1728 int reason;
1730 tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
1731 tor_assert(circuit->cpath);
1732 tor_assert(circuit->build_state);
1733 #ifndef NON_ANONYMOUS_MODE_ENABLED
1734 tor_assert(!(circuit->build_state->onehop_tunnel));
1735 #endif
1736 tor_assert(circuit->rend_data);
1737 hop = circuit->build_state->service_pending_final_cpath_ref->cpath;
1739 base16_encode(hexcookie,9,circuit->rend_data->rend_cookie,4);
1740 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
1741 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
1743 log_info(LD_REND,
1744 "Done building circuit %d to rendezvous with "
1745 "cookie %s for service %s",
1746 circuit->_base.n_circ_id, hexcookie, serviceid);
1748 /* Clear the 'in-progress HS circ has timed out' flag for
1749 * consistency with what happens on the client side; this line has
1750 * no effect on Tor's behaviour. */
1751 circuit->hs_circ_has_timed_out = 0;
1753 /* If hop is NULL, another rend circ has already connected to this
1754 * rend point. Close this circ. */
1755 if (hop == NULL) {
1756 log_info(LD_REND, "Another rend circ has already reached this rend point; "
1757 "closing this rend circ.");
1758 reason = END_CIRC_REASON_NONE;
1759 goto err;
1762 /* Remove our final cpath element from the reference, so that no
1763 * other circuit will try to use it. Store it in
1764 * pending_final_cpath for now to ensure that it will be freed if
1765 * our rendezvous attempt fails. */
1766 circuit->build_state->pending_final_cpath = hop;
1767 circuit->build_state->service_pending_final_cpath_ref->cpath = NULL;
1769 service = rend_service_get_by_pk_digest(
1770 circuit->rend_data->rend_pk_digest);
1771 if (!service) {
1772 log_warn(LD_GENERAL, "Internal error: unrecognized service ID on "
1773 "rendezvous circuit.");
1774 reason = END_CIRC_REASON_INTERNAL;
1775 goto err;
1778 /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
1779 memcpy(buf, circuit->rend_data->rend_cookie, REND_COOKIE_LEN);
1780 if (crypto_dh_get_public(hop->dh_handshake_state,
1781 buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
1782 log_warn(LD_GENERAL,"Couldn't get DH public key.");
1783 reason = END_CIRC_REASON_INTERNAL;
1784 goto err;
1786 memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->handshake_digest,
1787 DIGEST_LEN);
1789 /* Send the cell */
1790 if (relay_send_command_from_edge(0, TO_CIRCUIT(circuit),
1791 RELAY_COMMAND_RENDEZVOUS1,
1792 buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
1793 circuit->cpath->prev)<0) {
1794 log_warn(LD_GENERAL, "Couldn't send RENDEZVOUS1 cell.");
1795 reason = END_CIRC_REASON_INTERNAL;
1796 goto err;
1799 crypto_dh_free(hop->dh_handshake_state);
1800 hop->dh_handshake_state = NULL;
1802 /* Append the cpath entry. */
1803 hop->state = CPATH_STATE_OPEN;
1804 /* set the windows to default. these are the windows
1805 * that bob thinks alice has.
1807 hop->package_window = circuit_initial_package_window();
1808 hop->deliver_window = CIRCWINDOW_START;
1810 onion_append_to_cpath(&circuit->cpath, hop);
1811 circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
1813 /* Change the circuit purpose. */
1814 circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_REND_JOINED);
1816 return;
1817 err:
1818 circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
1822 * Manage introduction points
1825 /** Return the (possibly non-open) introduction circuit ending at
1826 * <b>intro</b> for the service whose public key is <b>pk_digest</b>.
1827 * (<b>desc_version</b> is ignored). Return NULL if no such service is
1828 * found.
1830 static origin_circuit_t *
1831 find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
1833 origin_circuit_t *circ = NULL;
1835 tor_assert(intro);
1836 while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
1837 CIRCUIT_PURPOSE_S_INTRO))) {
1838 if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
1839 intro->extend_info->identity_digest, DIGEST_LEN) &&
1840 circ->rend_data) {
1841 return circ;
1845 circ = NULL;
1846 while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
1847 CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
1848 if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
1849 intro->extend_info->identity_digest, DIGEST_LEN) &&
1850 circ->rend_data) {
1851 return circ;
1854 return NULL;
1857 /** Return a pointer to the rend_intro_point_t corresponding to the
1858 * service-side introduction circuit <b>circ</b>. */
1859 static rend_intro_point_t *
1860 find_intro_point(origin_circuit_t *circ)
1862 const char *serviceid;
1863 rend_service_t *service = NULL;
1865 tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
1866 TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO);
1867 tor_assert(circ->rend_data);
1868 serviceid = circ->rend_data->onion_address;
1870 SMARTLIST_FOREACH(rend_service_list, rend_service_t *, s,
1871 if (tor_memeq(s->service_id, serviceid, REND_SERVICE_ID_LEN_BASE32)) {
1872 service = s;
1873 break;
1876 if (service == NULL) return NULL;
1878 SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro_point,
1879 if (crypto_pk_cmp_keys(intro_point->intro_key, circ->intro_key) == 0) {
1880 return intro_point;
1883 return NULL;
1886 /** Determine the responsible hidden service directories for the
1887 * rend_encoded_v2_service_descriptor_t's in <b>descs</b> and upload them;
1888 * <b>service_id</b> and <b>seconds_valid</b> are only passed for logging
1889 * purposes. */
1890 static void
1891 directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
1892 smartlist_t *descs, const char *service_id,
1893 int seconds_valid)
1895 int i, j, failed_upload = 0;
1896 smartlist_t *responsible_dirs = smartlist_new();
1897 smartlist_t *successful_uploads = smartlist_new();
1898 routerstatus_t *hs_dir;
1899 for (i = 0; i < smartlist_len(descs); i++) {
1900 rend_encoded_v2_service_descriptor_t *desc = smartlist_get(descs, i);
1901 /* Determine responsible dirs. */
1902 if (hid_serv_get_responsible_directories(responsible_dirs,
1903 desc->desc_id) < 0) {
1904 log_warn(LD_REND, "Could not determine the responsible hidden service "
1905 "directories to post descriptors to.");
1906 smartlist_free(responsible_dirs);
1907 smartlist_free(successful_uploads);
1908 return;
1910 for (j = 0; j < smartlist_len(responsible_dirs); j++) {
1911 char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
1912 char *hs_dir_ip;
1913 const node_t *node;
1914 hs_dir = smartlist_get(responsible_dirs, j);
1915 if (smartlist_digest_isin(renddesc->successful_uploads,
1916 hs_dir->identity_digest))
1917 /* Don't upload descriptor if we succeeded in doing so last time. */
1918 continue;
1919 node = node_get_by_id(hs_dir->identity_digest);
1920 if (!node || !node_has_descriptor(node)) {
1921 log_info(LD_REND, "Not launching upload for for v2 descriptor to "
1922 "hidden service directory %s; we don't have its "
1923 "router descriptor. Queuing for later upload.",
1924 safe_str_client(routerstatus_describe(hs_dir)));
1925 failed_upload = -1;
1926 continue;
1928 /* Send publish request. */
1929 directory_initiate_command_routerstatus(hs_dir,
1930 DIR_PURPOSE_UPLOAD_RENDDESC_V2,
1931 ROUTER_PURPOSE_GENERAL,
1932 1, NULL, desc->desc_str,
1933 strlen(desc->desc_str), 0);
1934 base32_encode(desc_id_base32, sizeof(desc_id_base32),
1935 desc->desc_id, DIGEST_LEN);
1936 hs_dir_ip = tor_dup_ip(hs_dir->addr);
1937 log_info(LD_REND, "Launching upload for v2 descriptor for "
1938 "service '%s' with descriptor ID '%s' with validity "
1939 "of %d seconds to hidden service directory '%s' on "
1940 "%s:%d.",
1941 safe_str_client(service_id),
1942 safe_str_client(desc_id_base32),
1943 seconds_valid,
1944 hs_dir->nickname,
1945 hs_dir_ip,
1946 hs_dir->or_port);
1947 tor_free(hs_dir_ip);
1948 /* Remember successful upload to this router for next time. */
1949 if (!smartlist_digest_isin(successful_uploads, hs_dir->identity_digest))
1950 smartlist_add(successful_uploads, hs_dir->identity_digest);
1952 smartlist_clear(responsible_dirs);
1954 if (!failed_upload) {
1955 if (renddesc->successful_uploads) {
1956 SMARTLIST_FOREACH(renddesc->successful_uploads, char *, c, tor_free(c););
1957 smartlist_free(renddesc->successful_uploads);
1958 renddesc->successful_uploads = NULL;
1960 renddesc->all_uploads_performed = 1;
1961 } else {
1962 /* Remember which routers worked this time, so that we don't upload the
1963 * descriptor to them again. */
1964 if (!renddesc->successful_uploads)
1965 renddesc->successful_uploads = smartlist_new();
1966 SMARTLIST_FOREACH(successful_uploads, const char *, c, {
1967 if (!smartlist_digest_isin(renddesc->successful_uploads, c)) {
1968 char *hsdir_id = tor_memdup(c, DIGEST_LEN);
1969 smartlist_add(renddesc->successful_uploads, hsdir_id);
1973 smartlist_free(responsible_dirs);
1974 smartlist_free(successful_uploads);
1977 /** Encode and sign an up-to-date service descriptor for <b>service</b>,
1978 * and upload it/them to the responsible hidden service directories.
1980 static void
1981 upload_service_descriptor(rend_service_t *service)
1983 time_t now = time(NULL);
1984 int rendpostperiod;
1985 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
1986 int uploaded = 0;
1988 rendpostperiod = get_options()->RendPostPeriod;
1990 /* Upload descriptor? */
1991 if (get_options()->PublishHidServDescriptors) {
1992 networkstatus_t *c = networkstatus_get_latest_consensus();
1993 if (c && smartlist_len(c->routerstatus_list) > 0) {
1994 int seconds_valid, i, j, num_descs;
1995 smartlist_t *descs = smartlist_new();
1996 smartlist_t *client_cookies = smartlist_new();
1997 /* Either upload a single descriptor (including replicas) or one
1998 * descriptor for each authorized client in case of authorization
1999 * type 'stealth'. */
2000 num_descs = service->auth_type == REND_STEALTH_AUTH ?
2001 smartlist_len(service->clients) : 1;
2002 for (j = 0; j < num_descs; j++) {
2003 crypto_pk_t *client_key = NULL;
2004 rend_authorized_client_t *client = NULL;
2005 smartlist_clear(client_cookies);
2006 switch (service->auth_type) {
2007 case REND_NO_AUTH:
2008 /* Do nothing here. */
2009 break;
2010 case REND_BASIC_AUTH:
2011 SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *,
2012 cl, smartlist_add(client_cookies, cl->descriptor_cookie));
2013 break;
2014 case REND_STEALTH_AUTH:
2015 client = smartlist_get(service->clients, j);
2016 client_key = client->client_key;
2017 smartlist_add(client_cookies, client->descriptor_cookie);
2018 break;
2020 /* Encode the current descriptor. */
2021 seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
2022 now, 0,
2023 service->auth_type,
2024 client_key,
2025 client_cookies);
2026 if (seconds_valid < 0) {
2027 log_warn(LD_BUG, "Internal error: couldn't encode service "
2028 "descriptor; not uploading.");
2029 smartlist_free(descs);
2030 smartlist_free(client_cookies);
2031 return;
2033 /* Post the current descriptors to the hidden service directories. */
2034 rend_get_service_id(service->desc->pk, serviceid);
2035 log_info(LD_REND, "Launching upload for hidden service %s",
2036 serviceid);
2037 directory_post_to_hs_dir(service->desc, descs, serviceid,
2038 seconds_valid);
2039 /* Free memory for descriptors. */
2040 for (i = 0; i < smartlist_len(descs); i++)
2041 rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
2042 smartlist_clear(descs);
2043 /* Update next upload time. */
2044 if (seconds_valid - REND_TIME_PERIOD_OVERLAPPING_V2_DESCS
2045 > rendpostperiod)
2046 service->next_upload_time = now + rendpostperiod;
2047 else if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS)
2048 service->next_upload_time = now + seconds_valid + 1;
2049 else
2050 service->next_upload_time = now + seconds_valid -
2051 REND_TIME_PERIOD_OVERLAPPING_V2_DESCS + 1;
2052 /* Post also the next descriptors, if necessary. */
2053 if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS) {
2054 seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
2055 now, 1,
2056 service->auth_type,
2057 client_key,
2058 client_cookies);
2059 if (seconds_valid < 0) {
2060 log_warn(LD_BUG, "Internal error: couldn't encode service "
2061 "descriptor; not uploading.");
2062 smartlist_free(descs);
2063 smartlist_free(client_cookies);
2064 return;
2066 directory_post_to_hs_dir(service->desc, descs, serviceid,
2067 seconds_valid);
2068 /* Free memory for descriptors. */
2069 for (i = 0; i < smartlist_len(descs); i++)
2070 rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
2071 smartlist_clear(descs);
2074 smartlist_free(descs);
2075 smartlist_free(client_cookies);
2076 uploaded = 1;
2077 log_info(LD_REND, "Successfully uploaded v2 rend descriptors!");
2081 /* If not uploaded, try again in one minute. */
2082 if (!uploaded)
2083 service->next_upload_time = now + 60;
2085 /* Unmark dirty flag of this service. */
2086 service->desc_is_dirty = 0;
2089 /** Return the number of INTRODUCE2 cells this hidden service has received
2090 * from this intro point. */
2091 static int
2092 intro_point_accepted_intro_count(rend_intro_point_t *intro)
2094 if (intro->accepted_intro_rsa_parts == NULL) {
2095 return 0;
2096 } else {
2097 return digestmap_size(intro->accepted_intro_rsa_parts);
2101 /** Return non-zero iff <b>intro</b> should 'expire' now (i.e. we
2102 * should stop publishing it in new descriptors and eventually close
2103 * it). */
2104 static int
2105 intro_point_should_expire_now(rend_intro_point_t *intro,
2106 time_t now)
2108 tor_assert(intro != NULL);
2110 if (intro->time_published == -1) {
2111 /* Don't expire an intro point if we haven't even published it yet. */
2112 return 0;
2115 if (intro->time_expiring != -1) {
2116 /* We've already started expiring this intro point. *Don't* let
2117 * this function's result 'flap'. */
2118 return 1;
2121 if (intro_point_accepted_intro_count(intro) >=
2122 INTRO_POINT_LIFETIME_INTRODUCTIONS) {
2123 /* This intro point has been used too many times. Expire it now. */
2124 return 1;
2127 if (intro->time_to_expire == -1) {
2128 /* This intro point has been published, but we haven't picked an
2129 * expiration time for it. Pick one now. */
2130 int intro_point_lifetime_seconds =
2131 INTRO_POINT_LIFETIME_MIN_SECONDS +
2132 crypto_rand_int(INTRO_POINT_LIFETIME_MAX_SECONDS -
2133 INTRO_POINT_LIFETIME_MIN_SECONDS);
2135 /* Start the expiration timer now, rather than when the intro
2136 * point was first published. There shouldn't be much of a time
2137 * difference. */
2138 intro->time_to_expire = now + intro_point_lifetime_seconds;
2140 return 0;
2143 /* This intro point has a time to expire set already. Use it. */
2144 return (now >= intro->time_to_expire);
2147 /** For every service, check how many intro points it currently has, and:
2148 * - Pick new intro points as necessary.
2149 * - Launch circuits to any new intro points.
2151 void
2152 rend_services_introduce(void)
2154 int i,j,r;
2155 const node_t *node;
2156 rend_service_t *service;
2157 rend_intro_point_t *intro;
2158 int intro_point_set_changed, prev_intro_nodes;
2159 unsigned int n_intro_points_unexpired;
2160 unsigned int n_intro_points_to_open;
2161 smartlist_t *intro_nodes;
2162 time_t now;
2163 const or_options_t *options = get_options();
2165 intro_nodes = smartlist_new();
2166 now = time(NULL);
2168 for (i=0; i < smartlist_len(rend_service_list); ++i) {
2169 smartlist_clear(intro_nodes);
2170 service = smartlist_get(rend_service_list, i);
2172 tor_assert(service);
2174 /* intro_point_set_changed becomes non-zero iff the set of intro
2175 * points to be published in service's descriptor has changed. */
2176 intro_point_set_changed = 0;
2178 /* n_intro_points_unexpired collects the number of non-expiring
2179 * intro points we have, so that we know how many new intro
2180 * circuits we need to launch for this service. */
2181 n_intro_points_unexpired = 0;
2183 if (now > service->intro_period_started+INTRO_CIRC_RETRY_PERIOD) {
2184 /* One period has elapsed; we can try building circuits again. */
2185 service->intro_period_started = now;
2186 service->n_intro_circuits_launched = 0;
2187 } else if (service->n_intro_circuits_launched >=
2188 MAX_INTRO_CIRCS_PER_PERIOD) {
2189 /* We have failed too many times in this period; wait for the next
2190 * one before we try again. */
2191 continue;
2194 /* Find out which introduction points we have in progress for this
2195 service. */
2196 SMARTLIST_FOREACH_BEGIN(service->intro_nodes, rend_intro_point_t *,
2197 intro) {
2198 origin_circuit_t *intro_circ =
2199 find_intro_circuit(intro, service->pk_digest);
2201 if (intro->time_expiring + INTRO_POINT_EXPIRATION_GRACE_PERIOD > now) {
2202 /* This intro point has completely expired. Remove it, and
2203 * mark the circuit for close if it's still alive. */
2204 if (intro_circ != NULL) {
2205 circuit_mark_for_close(TO_CIRCUIT(intro_circ),
2206 END_CIRC_REASON_FINISHED);
2208 rend_intro_point_free(intro);
2209 intro = NULL; /* SMARTLIST_DEL_CURRENT takes a name, not a value. */
2210 SMARTLIST_DEL_CURRENT(service->intro_nodes, intro);
2211 /* We don't need to set intro_point_set_changed here, because
2212 * this intro point wouldn't have been published in a current
2213 * descriptor anyway. */
2214 continue;
2217 node = node_get_by_id(intro->extend_info->identity_digest);
2218 if (!node || !intro_circ) {
2219 int removing_this_intro_point_changes_the_intro_point_set = 1;
2220 log_info(LD_REND, "Giving up on %s as intro point for %s"
2221 " (circuit disappeared).",
2222 safe_str_client(extend_info_describe(intro->extend_info)),
2223 safe_str_client(service->service_id));
2224 rend_service_note_removing_intro_point(service, intro);
2225 if (intro->time_expiring != -1) {
2226 log_info(LD_REND, "We were already expiring the intro point; "
2227 "no need to mark the HS descriptor as dirty over this.");
2228 removing_this_intro_point_changes_the_intro_point_set = 0;
2229 } else if (intro->listed_in_last_desc) {
2230 log_info(LD_REND, "The intro point we are giving up on was "
2231 "included in the last published descriptor. "
2232 "Marking current descriptor as dirty.");
2233 service->desc_is_dirty = now;
2235 rend_intro_point_free(intro);
2236 intro = NULL; /* SMARTLIST_DEL_CURRENT takes a name, not a value. */
2237 SMARTLIST_DEL_CURRENT(service->intro_nodes, intro);
2238 if (removing_this_intro_point_changes_the_intro_point_set)
2239 intro_point_set_changed = 1;
2242 if (intro != NULL && intro_point_should_expire_now(intro, now)) {
2243 log_info(LD_REND, "Expiring %s as intro point for %s.",
2244 safe_str_client(extend_info_describe(intro->extend_info)),
2245 safe_str_client(service->service_id));
2247 rend_service_note_removing_intro_point(service, intro);
2249 /* The polite (and generally Right) way to expire an intro
2250 * point is to establish a new one to replace it, publish a
2251 * new descriptor that doesn't list any expiring intro points,
2252 * and *then*, once our upload attempts for the new descriptor
2253 * have ended (whether in success or failure), close the
2254 * expiring intro points.
2256 * Unfortunately, we can't find out when the new descriptor
2257 * has actually been uploaded, so we'll have to settle for a
2258 * five-minute timer. Start it. XXXX024 This sucks. */
2259 intro->time_expiring = now;
2261 intro_point_set_changed = 1;
2264 if (intro != NULL && intro->time_expiring == -1)
2265 ++n_intro_points_unexpired;
2267 if (node)
2268 smartlist_add(intro_nodes, (void*)node);
2269 } SMARTLIST_FOREACH_END(intro);
2271 if (!intro_point_set_changed &&
2272 (n_intro_points_unexpired >= service->n_intro_points_wanted)) {
2273 continue;
2276 /* Remember how many introduction circuits we started with.
2278 * prev_intro_nodes serves a different purpose than
2279 * n_intro_points_unexpired -- this variable tells us where our
2280 * previously-created intro points end and our new ones begin in
2281 * the intro-point list, so we don't have to launch the circuits
2282 * at the same time as we create the intro points they correspond
2283 * to. XXXX This is daft. */
2284 prev_intro_nodes = smartlist_len(service->intro_nodes);
2286 /* We have enough directory information to start establishing our
2287 * intro points. We want to end up with n_intro_points_wanted
2288 * intro points, but if we're just starting, we launch two extra
2289 * circuits and use the first n_intro_points_wanted that complete.
2291 * The ones after the first three will be converted to 'general'
2292 * internal circuits in rend_service_intro_has_opened(), and then
2293 * we'll drop them from the list of intro points next time we
2294 * go through the above "find out which introduction points we have
2295 * in progress" loop. */
2296 n_intro_points_to_open = (service->n_intro_points_wanted +
2297 (prev_intro_nodes == 0 ? 2 : 0));
2298 for (j = (int)n_intro_points_unexpired;
2299 j < (int)n_intro_points_to_open;
2300 ++j) { /* XXXX remove casts */
2301 router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
2302 if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
2303 flags |= CRN_ALLOW_INVALID;
2304 node = router_choose_random_node(intro_nodes,
2305 options->ExcludeNodes, flags);
2306 if (!node) {
2307 log_warn(LD_REND,
2308 "Could only establish %d introduction points for %s; "
2309 "wanted %u.",
2310 smartlist_len(service->intro_nodes), service->service_id,
2311 n_intro_points_to_open);
2312 break;
2314 intro_point_set_changed = 1;
2315 smartlist_add(intro_nodes, (void*)node);
2316 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
2317 intro->extend_info = extend_info_from_node(node, 0);
2318 intro->intro_key = crypto_pk_new();
2319 tor_assert(!crypto_pk_generate_key(intro->intro_key));
2320 intro->time_published = -1;
2321 intro->time_to_expire = -1;
2322 intro->time_expiring = -1;
2323 smartlist_add(service->intro_nodes, intro);
2324 log_info(LD_REND, "Picked router %s as an intro point for %s.",
2325 safe_str_client(node_describe(node)),
2326 safe_str_client(service->service_id));
2329 /* If there's no need to launch new circuits, stop here. */
2330 if (!intro_point_set_changed)
2331 continue;
2333 /* Establish new introduction points. */
2334 for (j=prev_intro_nodes; j < smartlist_len(service->intro_nodes); ++j) {
2335 intro = smartlist_get(service->intro_nodes, j);
2336 r = rend_service_launch_establish_intro(service, intro);
2337 if (r<0) {
2338 log_warn(LD_REND, "Error launching circuit to node %s for service %s.",
2339 safe_str_client(extend_info_describe(intro->extend_info)),
2340 safe_str_client(service->service_id));
2344 smartlist_free(intro_nodes);
2347 /** Regenerate and upload rendezvous service descriptors for all
2348 * services, if necessary. If the descriptor has been dirty enough
2349 * for long enough, definitely upload; else only upload when the
2350 * periodic timeout has expired.
2352 * For the first upload, pick a random time between now and two periods
2353 * from now, and pick it independently for each service.
2355 void
2356 rend_consider_services_upload(time_t now)
2358 int i;
2359 rend_service_t *service;
2360 int rendpostperiod = get_options()->RendPostPeriod;
2362 if (!get_options()->PublishHidServDescriptors)
2363 return;
2365 for (i=0; i < smartlist_len(rend_service_list); ++i) {
2366 service = smartlist_get(rend_service_list, i);
2367 if (!service->next_upload_time) { /* never been uploaded yet */
2368 /* The fixed lower bound of 30 seconds ensures that the descriptor
2369 * is stable before being published. See comment below. */
2370 service->next_upload_time =
2371 now + 30 + crypto_rand_int(2*rendpostperiod);
2373 if (service->next_upload_time < now ||
2374 (service->desc_is_dirty &&
2375 service->desc_is_dirty < now-30)) {
2376 /* if it's time, or if the directory servers have a wrong service
2377 * descriptor and ours has been stable for 30 seconds, upload a
2378 * new one of each format. */
2379 rend_service_update_descriptor(service);
2380 upload_service_descriptor(service);
2385 /** True if the list of available router descriptors might have changed so
2386 * that we should have a look whether we can republish previously failed
2387 * rendezvous service descriptors. */
2388 static int consider_republishing_rend_descriptors = 1;
2390 /** Called when our internal view of the directory has changed, so that we
2391 * might have router descriptors of hidden service directories available that
2392 * we did not have before. */
2393 void
2394 rend_hsdir_routers_changed(void)
2396 consider_republishing_rend_descriptors = 1;
2399 /** Consider republication of v2 rendezvous service descriptors that failed
2400 * previously, but without regenerating descriptor contents.
2402 void
2403 rend_consider_descriptor_republication(void)
2405 int i;
2406 rend_service_t *service;
2408 if (!consider_republishing_rend_descriptors)
2409 return;
2410 consider_republishing_rend_descriptors = 0;
2412 if (!get_options()->PublishHidServDescriptors)
2413 return;
2415 for (i=0; i < smartlist_len(rend_service_list); ++i) {
2416 service = smartlist_get(rend_service_list, i);
2417 if (service->desc && !service->desc->all_uploads_performed) {
2418 /* If we failed in uploading a descriptor last time, try again *without*
2419 * updating the descriptor's contents. */
2420 upload_service_descriptor(service);
2425 /** Log the status of introduction points for all rendezvous services
2426 * at log severity <b>severity</b>.
2428 void
2429 rend_service_dump_stats(int severity)
2431 int i,j;
2432 rend_service_t *service;
2433 rend_intro_point_t *intro;
2434 const char *safe_name;
2435 origin_circuit_t *circ;
2437 for (i=0; i < smartlist_len(rend_service_list); ++i) {
2438 service = smartlist_get(rend_service_list, i);
2439 log(severity, LD_GENERAL, "Service configured in \"%s\":",
2440 service->directory);
2441 for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
2442 intro = smartlist_get(service->intro_nodes, j);
2443 safe_name = safe_str_client(intro->extend_info->nickname);
2445 circ = find_intro_circuit(intro, service->pk_digest);
2446 if (!circ) {
2447 log(severity, LD_GENERAL, " Intro point %d at %s: no circuit",
2448 j, safe_name);
2449 continue;
2451 log(severity, LD_GENERAL, " Intro point %d at %s: circuit is %s",
2452 j, safe_name, circuit_state_to_string(circ->_base.state));
2457 /** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
2458 * 'circ', and look up the port and address based on conn-\>port.
2459 * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure,
2460 * or 0 for success.
2463 rend_service_set_connection_addr_port(edge_connection_t *conn,
2464 origin_circuit_t *circ)
2466 rend_service_t *service;
2467 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
2468 smartlist_t *matching_ports;
2469 rend_service_port_config_t *chosen_port;
2471 tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
2472 tor_assert(circ->rend_data);
2473 log_debug(LD_REND,"beginning to hunt for addr/port");
2474 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
2475 circ->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
2476 service = rend_service_get_by_pk_digest(
2477 circ->rend_data->rend_pk_digest);
2478 if (!service) {
2479 log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
2480 "rendezvous circuit %d; closing.",
2481 serviceid, circ->_base.n_circ_id);
2482 return -1;
2484 matching_ports = smartlist_new();
2485 SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
2487 if (conn->_base.port == p->virtual_port) {
2488 smartlist_add(matching_ports, p);
2491 chosen_port = smartlist_choose(matching_ports);
2492 smartlist_free(matching_ports);
2493 if (chosen_port) {
2494 tor_addr_copy(&conn->_base.addr, &chosen_port->real_addr);
2495 conn->_base.port = chosen_port->real_port;
2496 return 0;
2498 log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
2499 conn->_base.port,serviceid);
2500 return -1;